Merge branch 'features/remove-user-source_data' into 'develop'

User: remove source_data

Closes #820

See merge request pleroma/pleroma!2339
This commit is contained in:
rinpatch 2020-04-16 18:37:56 +00:00
commit 0ddee13c83
34 changed files with 293 additions and 308 deletions

View File

@ -38,22 +38,14 @@ def demojify(text) do
def demojify(text, nil), do: text def demojify(text, nil), do: text
@doc "Outputs a list of the emoji-shortcodes in a text"
def get_emoji(text) when is_binary(text) do
Enum.filter(Emoji.get_all(), fn {emoji, %Emoji{}} ->
String.contains?(text, ":#{emoji}:")
end)
end
def get_emoji(_), do: []
@doc "Outputs a list of the emoji-Maps in a text" @doc "Outputs a list of the emoji-Maps in a text"
def get_emoji_map(text) when is_binary(text) do def get_emoji_map(text) when is_binary(text) do
get_emoji(text) Emoji.get_all()
|> Enum.filter(fn {emoji, %Emoji{}} -> String.contains?(text, ":#{emoji}:") end)
|> Enum.reduce(%{}, fn {name, %Emoji{file: file}}, acc -> |> Enum.reduce(%{}, fn {name, %Emoji{file: file}}, acc ->
Map.put(acc, name, "#{Pleroma.Web.Endpoint.static_url()}#{file}") Map.put(acc, name, "#{Pleroma.Web.Endpoint.static_url()}#{file}")
end) end)
end end
def get_emoji_map(_), do: [] def get_emoji_map(_), do: %{}
end end

View File

@ -31,7 +31,7 @@ def escape_mention_handler("@" <> nickname = mention, buffer, _, _) do
def mention_handler("@" <> nickname, buffer, opts, acc) do def mention_handler("@" <> nickname, buffer, opts, acc) do
case User.get_cached_by_nickname(nickname) do case User.get_cached_by_nickname(nickname) do
%User{id: id} = user -> %User{id: id} = user ->
ap_id = get_ap_id(user) user_url = user.uri || user.ap_id
nickname_text = get_nickname_text(nickname, opts) nickname_text = get_nickname_text(nickname, opts)
link = link =
@ -42,7 +42,7 @@ def mention_handler("@" <> nickname, buffer, opts, acc) do
["@", Phoenix.HTML.Tag.content_tag(:span, nickname_text)], ["@", Phoenix.HTML.Tag.content_tag(:span, nickname_text)],
"data-user": id, "data-user": id,
class: "u-url mention", class: "u-url mention",
href: ap_id, href: user_url,
rel: "ugc" rel: "ugc"
), ),
class: "h-card" class: "h-card"
@ -146,9 +146,6 @@ def truncate(text, max_length \\ 200, omission \\ "...") do
end end
end end
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) defp get_nickname_text(nickname, %{mentions_format: :full}), do: User.full_nickname(nickname)
defp get_nickname_text(nickname, _), do: User.local_nickname(nickname) defp get_nickname_text(nickname, _), do: User.local_nickname(nickname)
end end

View File

@ -15,6 +15,7 @@ defmodule Pleroma.User do
alias Pleroma.Config alias Pleroma.Config
alias Pleroma.Conversation.Participation alias Pleroma.Conversation.Participation
alias Pleroma.Delivery alias Pleroma.Delivery
alias Pleroma.Emoji
alias Pleroma.FollowingRelationship alias Pleroma.FollowingRelationship
alias Pleroma.Formatter alias Pleroma.Formatter
alias Pleroma.HTML alias Pleroma.HTML
@ -28,6 +29,7 @@ defmodule Pleroma.User do
alias Pleroma.UserRelationship alias Pleroma.UserRelationship
alias Pleroma.Web alias Pleroma.Web
alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.ActivityPub.ObjectValidators.Types
alias Pleroma.Web.ActivityPub.Utils alias Pleroma.Web.ActivityPub.Utils
alias Pleroma.Web.CommonAPI alias Pleroma.Web.CommonAPI
alias Pleroma.Web.CommonAPI.Utils, as: CommonUtils alias Pleroma.Web.CommonAPI.Utils, as: CommonUtils
@ -82,6 +84,7 @@ defmodule Pleroma.User do
field(:password, :string, virtual: true) field(:password, :string, virtual: true)
field(:password_confirmation, :string, virtual: true) field(:password_confirmation, :string, virtual: true)
field(:keys, :string) field(:keys, :string)
field(:public_key, :string)
field(:ap_id, :string) field(:ap_id, :string)
field(:avatar, :map) field(:avatar, :map)
field(:local, :boolean, default: true) field(:local, :boolean, default: true)
@ -94,7 +97,6 @@ defmodule Pleroma.User do
field(:last_digest_emailed_at, :naive_datetime) field(:last_digest_emailed_at, :naive_datetime)
field(:banner, :map, default: %{}) field(:banner, :map, default: %{})
field(:background, :map, default: %{}) field(:background, :map, default: %{})
field(:source_data, :map, default: %{})
field(:note_count, :integer, default: 0) field(:note_count, :integer, default: 0)
field(:follower_count, :integer, default: 0) field(:follower_count, :integer, default: 0)
field(:following_count, :integer, default: 0) field(:following_count, :integer, default: 0)
@ -112,7 +114,7 @@ defmodule Pleroma.User do
field(:show_role, :boolean, default: true) field(:show_role, :boolean, default: true)
field(:settings, :map, default: nil) field(:settings, :map, default: nil)
field(:magic_key, :string, default: nil) field(:magic_key, :string, default: nil)
field(:uri, :string, default: nil) field(:uri, Types.Uri, default: nil)
field(:hide_followers_count, :boolean, default: false) field(:hide_followers_count, :boolean, default: false)
field(:hide_follows_count, :boolean, default: false) field(:hide_follows_count, :boolean, default: false)
field(:hide_followers, :boolean, default: false) field(:hide_followers, :boolean, default: false)
@ -122,7 +124,7 @@ defmodule Pleroma.User do
field(:pinned_activities, {:array, :string}, default: []) field(:pinned_activities, {:array, :string}, default: [])
field(:email_notifications, :map, default: %{"digest" => false}) field(:email_notifications, :map, default: %{"digest" => false})
field(:mascot, :map, default: nil) field(:mascot, :map, default: nil)
field(:emoji, {:array, :map}, default: []) field(:emoji, :map, default: %{})
field(:pleroma_settings_store, :map, default: %{}) field(:pleroma_settings_store, :map, default: %{})
field(:fields, {:array, :map}, default: []) field(:fields, {:array, :map}, default: [])
field(:raw_fields, {:array, :map}, default: []) field(:raw_fields, {:array, :map}, default: [])
@ -132,6 +134,8 @@ defmodule Pleroma.User do
field(:skip_thread_containment, :boolean, default: false) field(:skip_thread_containment, :boolean, default: false)
field(:actor_type, :string, default: "Person") field(:actor_type, :string, default: "Person")
field(:also_known_as, {:array, :string}, default: []) field(:also_known_as, {:array, :string}, default: [])
field(:inbox, :string)
field(:shared_inbox, :string)
embeds_one( embeds_one(
:notification_settings, :notification_settings,
@ -306,6 +310,7 @@ def banner_url(user, options \\ []) do
end end
end end
# Should probably be renamed or removed
def ap_id(%User{nickname: nickname}), do: "#{Web.base_url()}/users/#{nickname}" def ap_id(%User{nickname: nickname}), do: "#{Web.base_url()}/users/#{nickname}"
def ap_followers(%User{follower_address: fa}) when is_binary(fa), do: fa def ap_followers(%User{follower_address: fa}) when is_binary(fa), do: fa
@ -339,6 +344,13 @@ defp truncate_if_exists(params, key, max_length) do
end end
end end
defp fix_follower_address(%{follower_address: _, following_address: _} = params), do: params
defp fix_follower_address(%{nickname: nickname} = params),
do: Map.put(params, :follower_address, ap_followers(%User{nickname: nickname}))
defp fix_follower_address(params), do: params
def remote_user_changeset(struct \\ %User{local: false}, params) do def remote_user_changeset(struct \\ %User{local: false}, params) do
bio_limit = Pleroma.Config.get([:instance, :user_bio_length], 5000) bio_limit = Pleroma.Config.get([:instance, :user_bio_length], 5000)
name_limit = Pleroma.Config.get([:instance, :user_name_length], 100) name_limit = Pleroma.Config.get([:instance, :user_name_length], 100)
@ -356,54 +368,48 @@ def remote_user_changeset(struct \\ %User{local: false}, params) do
|> truncate_if_exists(:name, name_limit) |> truncate_if_exists(:name, name_limit)
|> truncate_if_exists(:bio, bio_limit) |> truncate_if_exists(:bio, bio_limit)
|> truncate_fields_param() |> truncate_fields_param()
|> fix_follower_address()
changeset = struct
struct |> cast(
|> cast( params,
params, [
[ :bio,
:bio, :name,
:name, :emoji,
:ap_id, :ap_id,
:nickname, :inbox,
:avatar, :shared_inbox,
:ap_enabled, :nickname,
:source_data, :public_key,
:banner, :avatar,
:locked, :ap_enabled,
:magic_key, :banner,
:uri, :locked,
:hide_followers, :last_refreshed_at,
:hide_follows, :magic_key,
:hide_followers_count, :uri,
:hide_follows_count, :follower_address,
:follower_count, :following_address,
:fields, :hide_followers,
:following_count, :hide_follows,
:discoverable, :hide_followers_count,
:invisible, :hide_follows_count,
:actor_type, :follower_count,
:also_known_as, :fields,
:last_refreshed_at :following_count,
] :discoverable,
) :invisible,
|> validate_required([:name, :ap_id]) :actor_type,
|> unique_constraint(:nickname) :also_known_as
|> validate_format(:nickname, @email_regex) ]
|> validate_length(:bio, max: bio_limit) )
|> validate_length(:name, max: name_limit) |> validate_required([:name, :ap_id])
|> validate_fields(true) |> unique_constraint(:nickname)
|> validate_format(:nickname, @email_regex)
case params[:source_data] do |> validate_length(:bio, max: bio_limit)
%{"followers" => followers, "following" => following} -> |> validate_length(:name, max: name_limit)
changeset |> validate_fields(true)
|> put_change(:follower_address, followers)
|> put_change(:following_address, following)
_ ->
followers = ap_followers(%User{nickname: get_field(changeset, :nickname)})
put_change(changeset, :follower_address, followers)
end
end end
def update_changeset(struct, params \\ %{}) do def update_changeset(struct, params \\ %{}) do
@ -416,7 +422,11 @@ def update_changeset(struct, params \\ %{}) do
[ [
:bio, :bio,
:name, :name,
:emoji,
:avatar, :avatar,
:public_key,
:inbox,
:shared_inbox,
:locked, :locked,
:no_rich_text, :no_rich_text,
:default_scope, :default_scope,
@ -443,6 +453,7 @@ def update_changeset(struct, params \\ %{}) do
|> validate_length(:bio, max: bio_limit) |> validate_length(:bio, max: bio_limit)
|> validate_length(:name, min: 1, max: name_limit) |> validate_length(:name, min: 1, max: name_limit)
|> put_fields() |> put_fields()
|> put_emoji()
|> put_change_if_present(:bio, &{:ok, parse_bio(&1, struct)}) |> put_change_if_present(:bio, &{:ok, parse_bio(&1, struct)})
|> put_change_if_present(:avatar, &put_upload(&1, :avatar)) |> put_change_if_present(:avatar, &put_upload(&1, :avatar))
|> put_change_if_present(:banner, &put_upload(&1, :banner)) |> put_change_if_present(:banner, &put_upload(&1, :banner))
@ -478,6 +489,18 @@ defp parse_fields(value) do
|> elem(0) |> elem(0)
end end
defp put_emoji(changeset) do
bio = get_change(changeset, :bio)
name = get_change(changeset, :name)
if bio || name do
emoji = Map.merge(Emoji.Formatter.get_emoji_map(bio), Emoji.Formatter.get_emoji_map(name))
put_change(changeset, :emoji, emoji)
else
changeset
end
end
defp put_change_if_present(changeset, map_field, value_function) do defp put_change_if_present(changeset, map_field, value_function) do
if value = get_change(changeset, map_field) do if value = get_change(changeset, map_field) do
with {:ok, new_value} <- value_function.(value) do with {:ok, new_value} <- value_function.(value) do
@ -572,7 +595,7 @@ def register_changeset(struct, params \\ %{}, opts \\ []) do
struct struct
|> confirmation_changeset(need_confirmation: need_confirmation?) |> confirmation_changeset(need_confirmation: need_confirmation?)
|> cast(params, [:bio, :email, :name, :nickname, :password, :password_confirmation]) |> cast(params, [:bio, :email, :name, :nickname, :password, :password_confirmation, :emoji])
|> validate_required([:name, :nickname, :password, :password_confirmation]) |> validate_required([:name, :nickname, :password, :password_confirmation])
|> validate_confirmation(:password) |> validate_confirmation(:password)
|> unique_constraint(:email) |> unique_constraint(:email)
@ -1587,8 +1610,7 @@ defp create_service_actor(uri, nickname) do
|> set_cache() |> set_cache()
end end
# AP style def public_key(%{public_key: public_key_pem}) when is_binary(public_key_pem) do
def public_key(%{source_data: %{"publicKey" => %{"publicKeyPem" => public_key_pem}}}) do
key = key =
public_key_pem public_key_pem
|> :public_key.pem_decode() |> :public_key.pem_decode()
@ -1598,7 +1620,7 @@ def public_key(%{source_data: %{"publicKey" => %{"publicKeyPem" => public_key_pe
{:ok, key} {:ok, key}
end end
def public_key(_), do: {:error, "not found key"} def public_key(_), do: {:error, "key not found"}
def get_public_key_for_ap_id(ap_id) do def get_public_key_for_ap_id(ap_id) do
with {:ok, %User{} = user} <- get_or_fetch_by_ap_id(ap_id), with {:ok, %User{} = user} <- get_or_fetch_by_ap_id(ap_id),
@ -1917,12 +1939,6 @@ def update_background(user, background) do
|> update_and_set_cache() |> update_and_set_cache()
end end
def update_source_data(user, source_data) do
user
|> cast(%{source_data: source_data}, [:source_data])
|> update_and_set_cache()
end
def roles(%{is_moderator: is_moderator, is_admin: is_admin}) do def roles(%{is_moderator: is_moderator, is_admin: is_admin}) do
%{ %{
admin: is_admin, admin: is_admin,
@ -1930,21 +1946,6 @@ def roles(%{is_moderator: is_moderator, is_admin: is_admin}) do
} }
end end
# ``fields`` is an array of mastodon profile field, containing ``{"name": "…", "value": "…"}``.
# For example: [{"name": "Pronoun", "value": "she/her"}, …]
def fields(%{fields: nil, source_data: %{"attachment" => attachment}}) do
limit = Pleroma.Config.get([:instance, :max_remote_account_fields], 0)
attachment
|> Enum.filter(fn %{"type" => t} -> t == "PropertyValue" end)
|> Enum.map(fn fields -> Map.take(fields, ["name", "value"]) end)
|> Enum.take(limit)
end
def fields(%{fields: nil}), do: []
def fields(%{fields: fields}), do: fields
def validate_fields(changeset, remote? \\ false) do def validate_fields(changeset, remote? \\ false) do
limit_name = if remote?, do: :max_remote_account_fields, else: :max_account_fields limit_name = if remote?, do: :max_remote_account_fields, else: :max_account_fields
limit = Pleroma.Config.get([:instance, limit_name], 0) limit = Pleroma.Config.get([:instance, limit_name], 0)
@ -2132,9 +2133,7 @@ def sanitize_html(%User{} = user) do
# - display name # - display name
def sanitize_html(%User{} = user, filter) do def sanitize_html(%User{} = user, filter) do
fields = fields =
user Enum.map(user.fields, fn %{"name" => name, "value" => value} ->
|> User.fields()
|> Enum.map(fn %{"name" => name, "value" => value} ->
%{ %{
"name" => name, "name" => name,
"value" => HTML.filter_tags(value, Pleroma.HTML.Scrubber.LinksOnly) "value" => HTML.filter_tags(value, Pleroma.HTML.Scrubber.LinksOnly)

View File

@ -1427,19 +1427,41 @@ defp object_to_user_data(data) do
|> Enum.filter(fn %{"type" => t} -> t == "PropertyValue" end) |> Enum.filter(fn %{"type" => t} -> t == "PropertyValue" end)
|> Enum.map(fn fields -> Map.take(fields, ["name", "value"]) end) |> Enum.map(fn fields -> Map.take(fields, ["name", "value"]) end)
emojis =
data
|> Map.get("tag", [])
|> Enum.filter(fn %{"type" => t} -> t == "Emoji" end)
|> Enum.reduce(%{}, fn %{"icon" => %{"url" => url}, "name" => name}, acc ->
Map.put(acc, String.trim(name, ":"), url)
end)
locked = data["manuallyApprovesFollowers"] || false locked = data["manuallyApprovesFollowers"] || false
data = Transmogrifier.maybe_fix_user_object(data) data = Transmogrifier.maybe_fix_user_object(data)
discoverable = data["discoverable"] || false discoverable = data["discoverable"] || false
invisible = data["invisible"] || false invisible = data["invisible"] || false
actor_type = data["type"] || "Person" actor_type = data["type"] || "Person"
public_key =
if is_map(data["publicKey"]) && is_binary(data["publicKey"]["publicKeyPem"]) do
data["publicKey"]["publicKeyPem"]
else
nil
end
shared_inbox =
if is_map(data["endpoints"]) && is_binary(data["endpoints"]["sharedInbox"]) do
data["endpoints"]["sharedInbox"]
else
nil
end
user_data = %{ user_data = %{
ap_id: data["id"], ap_id: data["id"],
uri: get_actor_url(data["url"]), uri: get_actor_url(data["url"]),
ap_enabled: true, ap_enabled: true,
source_data: data,
banner: banner, banner: banner,
fields: fields, fields: fields,
emoji: emojis,
locked: locked, locked: locked,
discoverable: discoverable, discoverable: discoverable,
invisible: invisible, invisible: invisible,
@ -1449,7 +1471,10 @@ defp object_to_user_data(data) do
following_address: data["following"], following_address: data["following"],
bio: data["summary"], bio: data["summary"],
actor_type: actor_type, actor_type: actor_type,
also_known_as: Map.get(data, "alsoKnownAs", []) also_known_as: Map.get(data, "alsoKnownAs", []),
public_key: public_key,
inbox: data["inbox"],
shared_inbox: shared_inbox
} }
# nickname can be nil because of virtual actors # nickname can be nil because of virtual actors

View File

@ -35,6 +35,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.NoteValidator do
field(:like_count, :integer, default: 0) field(:like_count, :integer, default: 0)
field(:announcement_count, :integer, default: 0) field(:announcement_count, :integer, default: 0)
field(:inRepyTo, :string) field(:inRepyTo, :string)
field(:uri, Types.Uri)
field(:likes, {:array, :string}, default: []) field(:likes, {:array, :string}, default: [])
field(:announcements, {:array, :string}, default: []) field(:announcements, {:array, :string}, default: [])

View File

@ -15,15 +15,9 @@ def cast(object) when is_binary(object) do
def cast(%{"id" => object}), do: cast(object) def cast(%{"id" => object}), do: cast(object)
def cast(_) do def cast(_), do: :error
:error
end
def dump(data) do def dump(data), do: {:ok, data}
{:ok, data}
end
def load(data) do def load(data), do: {:ok, data}
{:ok, data}
end
end end

View File

@ -0,0 +1,20 @@
defmodule Pleroma.Web.ActivityPub.ObjectValidators.Types.Uri do
use Ecto.Type
def type, do: :string
def cast(uri) when is_binary(uri) do
case URI.parse(uri) do
%URI{host: nil} -> :error
%URI{host: ""} -> :error
%URI{scheme: scheme} when scheme in ["https", "http"] -> {:ok, uri}
_ -> :error
end
end
def cast(_), do: :error
def dump(data), do: {:ok, data}
def load(data), do: {:ok, data}
end

View File

@ -141,8 +141,8 @@ defp get_cc_ap_ids(ap_id, recipients) do
|> Enum.map(& &1.ap_id) |> Enum.map(& &1.ap_id)
end end
defp maybe_use_sharedinbox(%User{source_data: data}), defp maybe_use_sharedinbox(%User{shared_inbox: nil, inbox: inbox}), do: inbox
do: (is_map(data["endpoints"]) && Map.get(data["endpoints"], "sharedInbox")) || data["inbox"] defp maybe_use_sharedinbox(%User{shared_inbox: shared_inbox}), do: shared_inbox
@doc """ @doc """
Determine a user inbox to use based on heuristics. These heuristics Determine a user inbox to use based on heuristics. These heuristics
@ -157,7 +157,7 @@ defp maybe_use_sharedinbox(%User{source_data: data}),
""" """
def determine_inbox( def determine_inbox(
%Activity{data: activity_data}, %Activity{data: activity_data},
%User{source_data: data} = user %User{inbox: inbox} = user
) do ) do
to = activity_data["to"] || [] to = activity_data["to"] || []
cc = activity_data["cc"] || [] cc = activity_data["cc"] || []
@ -174,7 +174,7 @@ def determine_inbox(
maybe_use_sharedinbox(user) maybe_use_sharedinbox(user)
true -> true ->
data["inbox"] inbox
end end
end end
@ -192,14 +192,13 @@ def publish(%User{} = actor, %{data: %{"bcc" => bcc}} = activity)
inboxes = inboxes =
recipients recipients
|> Enum.filter(&User.ap_enabled?/1) |> Enum.filter(&User.ap_enabled?/1)
|> Enum.map(fn %{source_data: data} -> data["inbox"] end) |> Enum.map(fn actor -> actor.inbox end)
|> Enum.filter(fn inbox -> should_federate?(inbox, public) end) |> Enum.filter(fn inbox -> should_federate?(inbox, public) end)
|> Instances.filter_reachable() |> Instances.filter_reachable()
Repo.checkout(fn -> Repo.checkout(fn ->
Enum.each(inboxes, fn {inbox, unreachable_since} -> Enum.each(inboxes, fn {inbox, unreachable_since} ->
%User{ap_id: ap_id} = %User{ap_id: ap_id} = Enum.find(recipients, fn actor -> actor.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 # 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. # instance would only accept a first message for the first recipient and ignore the rest.

View File

@ -1160,7 +1160,7 @@ defp build_mention_tag(%{ap_id: ap_id, nickname: nickname} = _) do
def take_emoji_tags(%User{emoji: emoji}) do def take_emoji_tags(%User{emoji: emoji}) do
emoji emoji
|> Enum.flat_map(&Map.to_list/1) |> Map.to_list()
|> Enum.map(&build_emoji_tag/1) |> Enum.map(&build_emoji_tag/1)
end end

View File

@ -79,10 +79,7 @@ def render("user.json", %{user: user}) do
emoji_tags = Transmogrifier.take_emoji_tags(user) emoji_tags = Transmogrifier.take_emoji_tags(user)
fields = fields = Enum.map(user.fields, &Map.put(&1, "type", "PropertyValue"))
user
|> User.fields()
|> Enum.map(&Map.put(&1, "type", "PropertyValue"))
%{ %{
"id" => user.ap_id, "id" => user.ap_id,
@ -103,7 +100,7 @@ def render("user.json", %{user: user}) do
}, },
"endpoints" => endpoints, "endpoints" => endpoints,
"attachment" => fields, "attachment" => fields,
"tag" => (user.source_data["tag"] || []) ++ emoji_tags, "tag" => emoji_tags,
"discoverable" => user.discoverable "discoverable" => user.discoverable
} }
|> Map.merge(maybe_make_image(&User.avatar_url/2, "icon", user)) |> Map.merge(maybe_make_image(&User.avatar_url/2, "icon", user))

View File

@ -332,26 +332,6 @@ defp maybe_create_activity_expiration({:ok, activity}, %NaiveDateTime{} = expire
defp maybe_create_activity_expiration(result, _), do: result 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 = Map.put(user.source_data, "tag", emoji)
user =
case User.update_source_data(user, source_data) do
{:ok, user} -> user
_ -> user
end
ActivityPub.update(%{
local: true,
to: [Pleroma.Constants.as_public(), user.follower_address],
cc: [],
actor: user.ap_id,
object: Pleroma.Web.ActivityPub.UserView.render("user.json", %{user: user})
})
end
def pin(id_or_ap_id, %{ap_id: user_ap_id} = user) do def pin(id_or_ap_id, %{ap_id: user_ap_id} = user) do
with %Activity{ with %Activity{
actor: ^user_ap_id, actor: ^user_ap_id,

View File

@ -10,7 +10,6 @@ defmodule Pleroma.Web.CommonAPI.Utils do
alias Pleroma.Activity alias Pleroma.Activity
alias Pleroma.Config alias Pleroma.Config
alias Pleroma.Conversation.Participation alias Pleroma.Conversation.Participation
alias Pleroma.Emoji
alias Pleroma.Formatter alias Pleroma.Formatter
alias Pleroma.Object alias Pleroma.Object
alias Pleroma.Plugs.AuthenticationPlug alias Pleroma.Plugs.AuthenticationPlug
@ -18,7 +17,6 @@ defmodule Pleroma.Web.CommonAPI.Utils do
alias Pleroma.User alias Pleroma.User
alias Pleroma.Web.ActivityPub.Utils alias Pleroma.Web.ActivityPub.Utils
alias Pleroma.Web.ActivityPub.Visibility alias Pleroma.Web.ActivityPub.Visibility
alias Pleroma.Web.Endpoint
alias Pleroma.Web.MediaProxy alias Pleroma.Web.MediaProxy
require Logger require Logger
@ -175,7 +173,7 @@ def make_poll_data(%{"poll" => %{"options" => options, "expires_in" => expires_i
"replies" => %{"type" => "Collection", "totalItems" => 0} "replies" => %{"type" => "Collection", "totalItems" => 0}
} }
{note, Map.merge(emoji, Emoji.Formatter.get_emoji_map(option))} {note, Map.merge(emoji, Pleroma.Emoji.Formatter.get_emoji_map(option))}
end) end)
end_time = end_time =
@ -431,19 +429,6 @@ def confirm_current_password(user, password) do
end end
end end
def emoji_from_profile(%User{bio: bio, name: name}) do
[bio, name]
|> Enum.map(&Emoji.Formatter.get_emoji/1)
|> Enum.concat()
|> Enum.map(fn {shortcode, %Emoji{file: path}} ->
%{
"type" => "Emoji",
"icon" => %{"type" => "Image", "url" => "#{Endpoint.url()}#{path}"},
"name" => ":#{shortcode}:"
}
end)
end
def maybe_notify_to_recipients( def maybe_notify_to_recipients(
recipients, recipients,
%Activity{data: %{"to" => to, "type" => _type}} = _activity %Activity{data: %{"to" => to, "type" => _type}} = _activity

View File

@ -146,9 +146,7 @@ def verify_credentials(%{assigns: %{user: user}} = conn, _) do
end end
@doc "PATCH /api/v1/accounts/update_credentials" @doc "PATCH /api/v1/accounts/update_credentials"
def update_credentials(%{assigns: %{user: original_user}} = conn, params) do def update_credentials(%{assigns: %{user: user}} = conn, params) do
user = original_user
user_params = user_params =
[ [
:no_rich_text, :no_rich_text,
@ -184,8 +182,6 @@ def update_credentials(%{assigns: %{user: original_user}} = conn, params) do
changeset = User.update_changeset(user, user_params) changeset = User.update_changeset(user, user_params)
with {:ok, user} <- User.update_and_set_cache(changeset) do with {:ok, user} <- User.update_and_set_cache(changeset) do
if original_user != user, do: CommonAPI.update(user)
render(conn, "show.json", user: user, for: user, with_pleroma_settings: true) render(conn, "show.json", user: user, for: user, with_pleroma_settings: true)
else else
_e -> render_error(conn, :forbidden, "Invalid request") _e -> render_error(conn, :forbidden, "Invalid request")

View File

@ -181,13 +181,11 @@ defp do_render("show.json", %{user: user} = opts) do
bot = user.actor_type in ["Application", "Service"] bot = user.actor_type in ["Application", "Service"]
emojis = emojis =
(user.source_data["tag"] || []) Enum.map(user.emoji, fn {shortcode, url} ->
|> Enum.filter(fn %{"type" => t} -> t == "Emoji" end)
|> Enum.map(fn %{"icon" => %{"url" => url}, "name" => name} ->
%{ %{
"shortcode" => String.trim(name, ":"), "shortcode" => shortcode,
"url" => MediaProxy.url(url), "url" => url,
"static_url" => MediaProxy.url(url), "static_url" => url,
"visible_in_picker" => false "visible_in_picker" => false
} }
end) end)

View File

@ -13,7 +13,6 @@ defmodule Pleroma.Web.PleromaAPI.AccountController do
alias Pleroma.Plugs.RateLimiter alias Pleroma.Plugs.RateLimiter
alias Pleroma.User alias Pleroma.User
alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.CommonAPI
alias Pleroma.Web.MastodonAPI.StatusView alias Pleroma.Web.MastodonAPI.StatusView
require Pleroma.Constants require Pleroma.Constants
@ -58,38 +57,32 @@ def confirmation_resend(conn, params) do
@doc "PATCH /api/v1/pleroma/accounts/update_avatar" @doc "PATCH /api/v1/pleroma/accounts/update_avatar"
def update_avatar(%{assigns: %{user: user}} = conn, %{"img" => ""}) do def update_avatar(%{assigns: %{user: user}} = conn, %{"img" => ""}) do
{:ok, user} = {:ok, _user} =
user user
|> Changeset.change(%{avatar: nil}) |> Changeset.change(%{avatar: nil})
|> User.update_and_set_cache() |> User.update_and_set_cache()
CommonAPI.update(user)
json(conn, %{url: nil}) json(conn, %{url: nil})
end end
def update_avatar(%{assigns: %{user: user}} = conn, params) do def update_avatar(%{assigns: %{user: user}} = conn, params) do
{:ok, %{data: data}} = ActivityPub.upload(params, type: :avatar) {:ok, %{data: data}} = ActivityPub.upload(params, type: :avatar)
{:ok, user} = user |> Changeset.change(%{avatar: data}) |> User.update_and_set_cache() {:ok, _user} = user |> Changeset.change(%{avatar: data}) |> User.update_and_set_cache()
%{"url" => [%{"href" => href} | _]} = data %{"url" => [%{"href" => href} | _]} = data
CommonAPI.update(user)
json(conn, %{url: href}) json(conn, %{url: href})
end end
@doc "PATCH /api/v1/pleroma/accounts/update_banner" @doc "PATCH /api/v1/pleroma/accounts/update_banner"
def update_banner(%{assigns: %{user: user}} = conn, %{"banner" => ""}) do def update_banner(%{assigns: %{user: user}} = conn, %{"banner" => ""}) do
with {:ok, user} <- User.update_banner(user, %{}) do with {:ok, _user} <- User.update_banner(user, %{}) do
CommonAPI.update(user)
json(conn, %{url: nil}) json(conn, %{url: nil})
end end
end end
def update_banner(%{assigns: %{user: user}} = conn, params) do def update_banner(%{assigns: %{user: user}} = conn, params) do
with {:ok, object} <- ActivityPub.upload(%{"img" => params["banner"]}, type: :banner), with {:ok, object} <- ActivityPub.upload(%{"img" => params["banner"]}, type: :banner),
{:ok, user} <- User.update_banner(user, object.data) do {:ok, _user} <- User.update_banner(user, object.data) do
CommonAPI.update(user)
%{"url" => [%{"href" => href} | _]} = object.data %{"url" => [%{"href" => href} | _]} = object.data
json(conn, %{url: href}) json(conn, %{url: href})

View File

@ -18,15 +18,6 @@ defmodule Pleroma.Web.StaticFE.StaticFEView do
@media_types ["image", "audio", "video"] @media_types ["image", "audio", "video"]
def emoji_for_user(%User{} = user) do
user.source_data
|> Map.get("tag", [])
|> Enum.filter(fn %{"type" => t} -> t == "Emoji" end)
|> Enum.map(fn %{"icon" => %{"url" => url}, "name" => name} ->
{String.trim(name, ":"), url}
end)
end
def fetch_media_type(%{"mediaType" => mediaType}) do def fetch_media_type(%{"mediaType" => mediaType}) do
Utils.fetch_media_type(@media_types, mediaType) Utils.fetch_media_type(@media_types, mediaType)
end end

View File

@ -4,7 +4,7 @@
<img src="<%= User.avatar_url(@user) |> MediaProxy.url %>" width="48" height="48" alt=""> <img src="<%= User.avatar_url(@user) |> MediaProxy.url %>" width="48" height="48" alt="">
</div> </div>
<span class="display-name"> <span class="display-name">
<bdi><%= raw (@user.name |> Formatter.emojify(emoji_for_user(@user))) %></bdi> <bdi><%= raw Formatter.emojify(@user.name, @user.emoji) %></bdi>
<span class="nickname"><%= @user.nickname %></span> <span class="nickname"><%= @user.nickname %></span>
</span> </span>
</a> </a>

View File

@ -7,7 +7,7 @@
<input type="hidden" name="profile" value=""> <input type="hidden" name="profile" value="">
<button type="submit" class="collapse">Remote follow</button> <button type="submit" class="collapse">Remote follow</button>
</form> </form>
<%= raw Formatter.emojify(@user.name, emoji_for_user(@user)) %> | <%= raw Formatter.emojify(@user.name, @user.emoji) %> |
<%= link "@#{@user.nickname}@#{Endpoint.host()}", to: (@user.uri || @user.ap_id) %> <%= link "@#{@user.nickname}@#{Endpoint.host()}", to: (@user.uri || @user.ap_id) %>
</h3> </h3>
<p><%= raw @user.bio %></p> <p><%= raw @user.bio %></p>

View File

@ -0,0 +1,17 @@
defmodule Pleroma.Repo.Migrations.UsersAddPublicKey do
use Ecto.Migration
def up do
alter table(:users) do
add_if_not_exists(:public_key, :text)
end
execute("UPDATE users SET public_key = source_data->'publicKey'->>'publicKeyPem'")
end
def down do
alter table(:users) do
remove_if_exists(:public_key, :text)
end
end
end

View File

@ -0,0 +1,20 @@
defmodule Pleroma.Repo.Migrations.UsersAddInboxes do
use Ecto.Migration
def up do
alter table(:users) do
add_if_not_exists(:inbox, :text)
add_if_not_exists(:shared_inbox, :text)
end
execute("UPDATE users SET inbox = source_data->>'inbox'")
execute("UPDATE users SET shared_inbox = source_data->'endpoints'->>'sharedInbox'")
end
def down do
alter table(:users) do
remove_if_exists(:inbox, :text)
remove_if_exists(:shared_inbox, :text)
end
end
end

View File

@ -0,0 +1,35 @@
defmodule Pleroma.Repo.Migrations.UsersPopulateEmoji do
use Ecto.Migration
import Ecto.Query
alias Pleroma.User
alias Pleroma.Repo
def up do
execute("ALTER TABLE users ALTER COLUMN emoji SET DEFAULT '{}'::jsonb")
execute("UPDATE users SET emoji = DEFAULT WHERE emoji = '[]'::jsonb")
from(u in User)
|> select([u], struct(u, [:id, :ap_id, :source_data]))
|> Repo.stream()
|> Enum.each(fn user ->
emoji =
user.source_data
|> Map.get("tag", [])
|> Enum.filter(fn %{"type" => t} -> t == "Emoji" end)
|> Enum.reduce(%{}, fn %{"icon" => %{"url" => url}, "name" => name}, acc ->
Map.put(acc, String.trim(name, ":"), url)
end)
user
|> Ecto.Changeset.cast(%{emoji: emoji}, [:emoji])
|> Repo.update()
end)
end
def down do
execute("ALTER TABLE users ALTER COLUMN emoji SET DEFAULT '[]'::jsonb")
execute("UPDATE users SET emoji = DEFAULT WHERE emoji = '{}'::jsonb")
end
end

View File

@ -0,0 +1,15 @@
defmodule Pleroma.Repo.Migrations.UsersRemoveSourceData do
use Ecto.Migration
def up do
alter table(:users) do
remove_if_exists(:source_data, :map)
end
end
def down do
alter table(:users) do
add_if_not_exists(:source_data, :map, default: %{})
end
end
end

View File

@ -3,7 +3,6 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Emoji.FormatterTest do defmodule Pleroma.Emoji.FormatterTest do
alias Pleroma.Emoji
alias Pleroma.Emoji.Formatter alias Pleroma.Emoji.Formatter
use Pleroma.DataCase use Pleroma.DataCase
@ -32,30 +31,19 @@ test "it does not add XSS emoji" do
end end
end end
describe "get_emoji" do describe "get_emoji_map" do
test "it returns the emoji used in the text" do test "it returns the emoji used in the text" do
text = "I love :firefox:" assert Formatter.get_emoji_map("I love :firefox:") == %{
"firefox" => "http://localhost:4001/emoji/Firefox.gif"
assert Formatter.get_emoji(text) == [ }
{"firefox",
%Emoji{
code: "firefox",
file: "/emoji/Firefox.gif",
tags: ["Gif", "Fun"],
safe_code: "firefox",
safe_file: "/emoji/Firefox.gif"
}}
]
end end
test "it returns a nice empty result when no emojis are present" do test "it returns a nice empty result when no emojis are present" do
text = "I love moominamma" assert Formatter.get_emoji_map("I love moominamma") == %{}
assert Formatter.get_emoji(text) == []
end end
test "it doesn't die when text is absent" do test "it doesn't die when text is absent" do
text = nil assert Formatter.get_emoji_map(nil) == %{}
assert Formatter.get_emoji(text) == []
end end
end end
end end

View File

@ -140,7 +140,7 @@ test "gives a replacement for user links, using local nicknames in user links te
archaeme = archaeme =
insert(:user, insert(:user,
nickname: "archa_eme_", nickname: "archa_eme_",
source_data: %{"url" => "https://archeme/@archa_eme_"} uri: "https://archeme/@archa_eme_"
) )
archaeme_remote = insert(:user, %{nickname: "archaeme@archae.me"}) archaeme_remote = insert(:user, %{nickname: "archaeme@archae.me"})

View File

@ -19,12 +19,7 @@ defmodule Pleroma.SignatureTest do
@private_key "-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAKCAQEA48qb4v6kqigZutO9Ot0wkp27GIF2LiVaADgxQORZozZR63jH\nTaoOrS3Xhngbgc8SSOhfXET3omzeCLqaLNfXnZ8OXmuhJfJSU6mPUvmZ9QdT332j\nfN/g3iWGhYMf/M9ftCKh96nvFVO/tMruzS9xx7tkrfJjehdxh/3LlJMMImPtwcD7\nkFXwyt1qZTAU6Si4oQAJxRDQXHp1ttLl3Ob829VM7IKkrVmY8TD+JSlV0jtVJPj6\n1J19ytKTx/7UaucYvb9HIiBpkuiy5n/irDqKLVf5QEdZoNCdojOZlKJmTLqHhzKP\n3E9TxsUjhrf4/EqegNc/j982RvOxeu4i40zMQwIDAQABAoIBAQDH5DXjfh21i7b4\ncXJuw0cqget617CDUhemdakTDs9yH+rHPZd3mbGDWuT0hVVuFe4vuGpmJ8c+61X0\nRvugOlBlavxK8xvYlsqTzAmPgKUPljyNtEzQ+gz0I+3mH2jkin2rL3D+SksZZgKm\nfiYMPIQWB2WUF04gB46DDb2mRVuymGHyBOQjIx3WC0KW2mzfoFUFRlZEF+Nt8Ilw\nT+g/u0aZ1IWoszbsVFOEdghgZET0HEarum0B2Je/ozcPYtwmU10iBANGMKdLqaP/\nj954BPunrUf6gmlnLZKIKklJj0advx0NA+cL79+zeVB3zexRYSA5o9q0WPhiuTwR\n/aedWHnBAoGBAP0sDWBAM1Y4TRAf8ZI9PcztwLyHPzfEIqzbObJJnx1icUMt7BWi\n+/RMOnhrlPGE1kMhOqSxvXYN3u+eSmWTqai2sSH5Hdw2EqnrISSTnwNUPINX7fHH\njEkgmXQ6ixE48SuBZnb4w1EjdB/BA6/sjL+FNhggOc87tizLTkMXmMtTAoGBAOZV\n+wPuAMBDBXmbmxCuDIjoVmgSlgeRunB1SA8RCPAFAiUo3+/zEgzW2Oz8kgI+xVwM\n33XkLKrWG1Orhpp6Hm57MjIc5MG+zF4/YRDpE/KNG9qU1tiz0UD5hOpIU9pP4bR/\ngxgPxZzvbk4h5BfHWLpjlk8UUpgk6uxqfti48c1RAoGBALBOKDZ6HwYRCSGMjUcg\n3NPEUi84JD8qmFc2B7Tv7h2he2ykIz9iFAGpwCIyETQsJKX1Ewi0OlNnD3RhEEAy\nl7jFGQ+mkzPSeCbadmcpYlgIJmf1KN/x7fDTAepeBpCEzfZVE80QKbxsaybd3Dp8\nCfwpwWUFtBxr4c7J+gNhAGe/AoGAPn8ZyqkrPv9wXtyfqFjxQbx4pWhVmNwrkBPi\nZ2Qh3q4dNOPwTvTO8vjghvzIyR8rAZzkjOJKVFgftgYWUZfM5gE7T2mTkBYq8W+U\n8LetF+S9qAM2gDnaDx0kuUTCq7t87DKk6URuQ/SbI0wCzYjjRD99KxvChVGPBHKo\n1DjqMuECgYEAgJGNm7/lJCS2wk81whfy/ttKGsEIkyhPFYQmdGzSYC5aDc2gp1R3\nxtOkYEvdjfaLfDGEa4UX8CHHF+w3t9u8hBtcdhMH6GYb9iv6z0VBTt4A/11HUR49\n3Z7TQ18Iyh3jAUCzFV9IJlLIExq5Y7P4B3ojWFBN607sDCt8BMPbDYs=\n-----END RSA PRIVATE KEY-----" @private_key "-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAKCAQEA48qb4v6kqigZutO9Ot0wkp27GIF2LiVaADgxQORZozZR63jH\nTaoOrS3Xhngbgc8SSOhfXET3omzeCLqaLNfXnZ8OXmuhJfJSU6mPUvmZ9QdT332j\nfN/g3iWGhYMf/M9ftCKh96nvFVO/tMruzS9xx7tkrfJjehdxh/3LlJMMImPtwcD7\nkFXwyt1qZTAU6Si4oQAJxRDQXHp1ttLl3Ob829VM7IKkrVmY8TD+JSlV0jtVJPj6\n1J19ytKTx/7UaucYvb9HIiBpkuiy5n/irDqKLVf5QEdZoNCdojOZlKJmTLqHhzKP\n3E9TxsUjhrf4/EqegNc/j982RvOxeu4i40zMQwIDAQABAoIBAQDH5DXjfh21i7b4\ncXJuw0cqget617CDUhemdakTDs9yH+rHPZd3mbGDWuT0hVVuFe4vuGpmJ8c+61X0\nRvugOlBlavxK8xvYlsqTzAmPgKUPljyNtEzQ+gz0I+3mH2jkin2rL3D+SksZZgKm\nfiYMPIQWB2WUF04gB46DDb2mRVuymGHyBOQjIx3WC0KW2mzfoFUFRlZEF+Nt8Ilw\nT+g/u0aZ1IWoszbsVFOEdghgZET0HEarum0B2Je/ozcPYtwmU10iBANGMKdLqaP/\nj954BPunrUf6gmlnLZKIKklJj0advx0NA+cL79+zeVB3zexRYSA5o9q0WPhiuTwR\n/aedWHnBAoGBAP0sDWBAM1Y4TRAf8ZI9PcztwLyHPzfEIqzbObJJnx1icUMt7BWi\n+/RMOnhrlPGE1kMhOqSxvXYN3u+eSmWTqai2sSH5Hdw2EqnrISSTnwNUPINX7fHH\njEkgmXQ6ixE48SuBZnb4w1EjdB/BA6/sjL+FNhggOc87tizLTkMXmMtTAoGBAOZV\n+wPuAMBDBXmbmxCuDIjoVmgSlgeRunB1SA8RCPAFAiUo3+/zEgzW2Oz8kgI+xVwM\n33XkLKrWG1Orhpp6Hm57MjIc5MG+zF4/YRDpE/KNG9qU1tiz0UD5hOpIU9pP4bR/\ngxgPxZzvbk4h5BfHWLpjlk8UUpgk6uxqfti48c1RAoGBALBOKDZ6HwYRCSGMjUcg\n3NPEUi84JD8qmFc2B7Tv7h2he2ykIz9iFAGpwCIyETQsJKX1Ewi0OlNnD3RhEEAy\nl7jFGQ+mkzPSeCbadmcpYlgIJmf1KN/x7fDTAepeBpCEzfZVE80QKbxsaybd3Dp8\nCfwpwWUFtBxr4c7J+gNhAGe/AoGAPn8ZyqkrPv9wXtyfqFjxQbx4pWhVmNwrkBPi\nZ2Qh3q4dNOPwTvTO8vjghvzIyR8rAZzkjOJKVFgftgYWUZfM5gE7T2mTkBYq8W+U\n8LetF+S9qAM2gDnaDx0kuUTCq7t87DKk6URuQ/SbI0wCzYjjRD99KxvChVGPBHKo\n1DjqMuECgYEAgJGNm7/lJCS2wk81whfy/ttKGsEIkyhPFYQmdGzSYC5aDc2gp1R3\nxtOkYEvdjfaLfDGEa4UX8CHHF+w3t9u8hBtcdhMH6GYb9iv6z0VBTt4A/11HUR49\n3Z7TQ18Iyh3jAUCzFV9IJlLIExq5Y7P4B3ojWFBN607sDCt8BMPbDYs=\n-----END RSA PRIVATE KEY-----"
@public_key %{ @public_key "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw0P/Tq4gb4G/QVuMGbJo\nC/AfMNcv+m7NfrlOwkVzcU47jgESuYI4UtJayissCdBycHUnfVUd9qol+eznSODz\nCJhfJloqEIC+aSnuEPGA0POtWad6DU0E6/Ho5zQn5WAWUwbRQqowbrsm/GHo2+3v\neR5jGenwA6sYhINg/c3QQbksyV0uJ20Umyx88w8+TJuv53twOfmyDWuYNoQ3y5cc\nHKOZcLHxYOhvwg3PFaGfFHMFiNmF40dTXt9K96r7sbzc44iLD+VphbMPJEjkMuf8\nPGEFOBzy8pm3wJZw2v32RNW2VESwMYyqDzwHXGSq1a73cS7hEnc79gXlELsK04L9\nQQIDAQAB\n-----END PUBLIC KEY-----\n"
"id" => "https://mastodon.social/users/lambadalambda#main-key",
"owner" => "https://mastodon.social/users/lambadalambda",
"publicKeyPem" =>
"-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw0P/Tq4gb4G/QVuMGbJo\nC/AfMNcv+m7NfrlOwkVzcU47jgESuYI4UtJayissCdBycHUnfVUd9qol+eznSODz\nCJhfJloqEIC+aSnuEPGA0POtWad6DU0E6/Ho5zQn5WAWUwbRQqowbrsm/GHo2+3v\neR5jGenwA6sYhINg/c3QQbksyV0uJ20Umyx88w8+TJuv53twOfmyDWuYNoQ3y5cc\nHKOZcLHxYOhvwg3PFaGfFHMFiNmF40dTXt9K96r7sbzc44iLD+VphbMPJEjkMuf8\nPGEFOBzy8pm3wJZw2v32RNW2VESwMYyqDzwHXGSq1a73cS7hEnc79gXlELsK04L9\nQQIDAQAB\n-----END PUBLIC KEY-----\n"
}
@rsa_public_key { @rsa_public_key {
:RSAPublicKey, :RSAPublicKey,
@ -42,7 +37,7 @@ defp make_fake_conn(key_id),
test "it returns key" do test "it returns key" do
expected_result = {:ok, @rsa_public_key} expected_result = {:ok, @rsa_public_key}
user = insert(:user, source_data: %{"publicKey" => @public_key}) user = insert(:user, public_key: @public_key)
assert Signature.fetch_public_key(make_fake_conn(user.ap_id)) == expected_result assert Signature.fetch_public_key(make_fake_conn(user.ap_id)) == expected_result
end end
@ -53,8 +48,8 @@ test "it returns error when not found user" do
end) =~ "[error] Could not decode user" end) =~ "[error] Could not decode user"
end end
test "it returns error if public key is empty" do test "it returns error if public key is nil" do
user = insert(:user, source_data: %{"publicKey" => %{}}) user = insert(:user, public_key: nil)
assert Signature.fetch_public_key(make_fake_conn(user.ap_id)) == {:error, :error} assert Signature.fetch_public_key(make_fake_conn(user.ap_id)) == {:error, :error}
end end

View File

@ -582,7 +582,7 @@ test "updates an existing user, if stale" do
{:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin") {:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin")
assert user.source_data["endpoints"] assert user.inbox
refute user.last_refreshed_at == orig_user.last_refreshed_at refute user.last_refreshed_at == orig_user.last_refreshed_at
end end

View File

@ -180,7 +180,6 @@ test "it returns a user" do
{:ok, user} = ActivityPub.make_user_from_ap_id(user_id) {:ok, user} = ActivityPub.make_user_from_ap_id(user_id)
assert user.ap_id == user_id assert user.ap_id == user_id
assert user.nickname == "admin@mastodon.example.org" assert user.nickname == "admin@mastodon.example.org"
assert user.source_data
assert user.ap_enabled assert user.ap_enabled
assert user.follower_address == "http://mastodon.example.org/users/admin/followers" assert user.follower_address == "http://mastodon.example.org/users/admin/followers"
end end

View File

@ -48,10 +48,7 @@ test "it returns links" do
describe "determine_inbox/2" do describe "determine_inbox/2" do
test "it returns sharedInbox for messages involving as:Public in to" do test "it returns sharedInbox for messages involving as:Public in to" do
user = user = insert(:user, %{shared_inbox: "http://example.com/inbox"})
insert(:user, %{
source_data: %{"endpoints" => %{"sharedInbox" => "http://example.com/inbox"}}
})
activity = %Activity{ activity = %Activity{
data: %{"to" => [@as_public], "cc" => [user.follower_address]} data: %{"to" => [@as_public], "cc" => [user.follower_address]}
@ -61,10 +58,7 @@ test "it returns sharedInbox for messages involving as:Public in to" do
end end
test "it returns sharedInbox for messages involving as:Public in cc" do test "it returns sharedInbox for messages involving as:Public in cc" do
user = user = insert(:user, %{shared_inbox: "http://example.com/inbox"})
insert(:user, %{
source_data: %{"endpoints" => %{"sharedInbox" => "http://example.com/inbox"}}
})
activity = %Activity{ activity = %Activity{
data: %{"cc" => [@as_public], "to" => [user.follower_address]} data: %{"cc" => [@as_public], "to" => [user.follower_address]}
@ -74,11 +68,7 @@ test "it returns sharedInbox for messages involving as:Public in cc" do
end end
test "it returns sharedInbox for messages involving multiple recipients in to" do test "it returns sharedInbox for messages involving multiple recipients in to" do
user = user = insert(:user, %{shared_inbox: "http://example.com/inbox"})
insert(:user, %{
source_data: %{"endpoints" => %{"sharedInbox" => "http://example.com/inbox"}}
})
user_two = insert(:user) user_two = insert(:user)
user_three = insert(:user) user_three = insert(:user)
@ -90,11 +80,7 @@ test "it returns sharedInbox for messages involving multiple recipients in to" d
end end
test "it returns sharedInbox for messages involving multiple recipients in cc" do test "it returns sharedInbox for messages involving multiple recipients in cc" do
user = user = insert(:user, %{shared_inbox: "http://example.com/inbox"})
insert(:user, %{
source_data: %{"endpoints" => %{"sharedInbox" => "http://example.com/inbox"}}
})
user_two = insert(:user) user_two = insert(:user)
user_three = insert(:user) user_three = insert(:user)
@ -107,12 +93,10 @@ test "it returns sharedInbox for messages involving multiple recipients in cc" d
test "it returns sharedInbox for messages involving multiple recipients in total" do test "it returns sharedInbox for messages involving multiple recipients in total" do
user = user =
insert(:user, insert(:user, %{
source_data: %{ shared_inbox: "http://example.com/inbox",
"inbox" => "http://example.com/personal-inbox", inbox: "http://example.com/personal-inbox"
"endpoints" => %{"sharedInbox" => "http://example.com/inbox"} })
}
)
user_two = insert(:user) user_two = insert(:user)
@ -125,12 +109,10 @@ test "it returns sharedInbox for messages involving multiple recipients in total
test "it returns inbox for messages involving single recipients in total" do test "it returns inbox for messages involving single recipients in total" do
user = user =
insert(:user, insert(:user, %{
source_data: %{ shared_inbox: "http://example.com/inbox",
"inbox" => "http://example.com/personal-inbox", inbox: "http://example.com/personal-inbox"
"endpoints" => %{"sharedInbox" => "http://example.com/inbox"} })
}
)
activity = %Activity{ activity = %Activity{
data: %{"to" => [user.ap_id], "cc" => []} data: %{"to" => [user.ap_id], "cc" => []}
@ -258,11 +240,11 @@ test "it returns inbox for messages involving single recipients in total" do
[:passthrough], [:passthrough],
[] do [] do
follower = follower =
insert(:user, insert(:user, %{
local: false, local: false,
source_data: %{"inbox" => "https://domain.com/users/nick1/inbox"}, inbox: "https://domain.com/users/nick1/inbox",
ap_enabled: true ap_enabled: true
) })
actor = insert(:user, follower_address: follower.ap_id) actor = insert(:user, follower_address: follower.ap_id)
user = insert(:user) user = insert(:user)
@ -295,14 +277,14 @@ test "it returns inbox for messages involving single recipients in total" do
fetcher = fetcher =
insert(:user, insert(:user,
local: false, local: false,
source_data: %{"inbox" => "https://domain.com/users/nick1/inbox"}, inbox: "https://domain.com/users/nick1/inbox",
ap_enabled: true ap_enabled: true
) )
another_fetcher = another_fetcher =
insert(:user, insert(:user,
local: false, local: false,
source_data: %{"inbox" => "https://domain2.com/users/nick1/inbox"}, inbox: "https://domain2.com/users/nick1/inbox",
ap_enabled: true ap_enabled: true
) )

View File

@ -746,7 +746,7 @@ test "it works with custom profile fields" do
user = User.get_cached_by_ap_id(activity.actor) user = User.get_cached_by_ap_id(activity.actor)
assert User.fields(user) == [ assert user.fields == [
%{"name" => "foo", "value" => "bar"}, %{"name" => "foo", "value" => "bar"},
%{"name" => "foo1", "value" => "bar1"} %{"name" => "foo1", "value" => "bar1"}
] ]
@ -767,7 +767,7 @@ test "it works with custom profile fields" do
user = User.get_cached_by_ap_id(user.ap_id) user = User.get_cached_by_ap_id(user.ap_id)
assert User.fields(user) == [ assert user.fields == [
%{"name" => "foo", "value" => "updated"}, %{"name" => "foo", "value" => "updated"},
%{"name" => "foo1", "value" => "updated"} %{"name" => "foo1", "value" => "updated"}
] ]
@ -785,7 +785,7 @@ test "it works with custom profile fields" do
user = User.get_cached_by_ap_id(user.ap_id) user = User.get_cached_by_ap_id(user.ap_id)
assert User.fields(user) == [ assert user.fields == [
%{"name" => "foo", "value" => "updated"}, %{"name" => "foo", "value" => "updated"},
%{"name" => "foo1", "value" => "updated"} %{"name" => "foo1", "value" => "updated"}
] ]
@ -796,7 +796,7 @@ test "it works with custom profile fields" do
user = User.get_cached_by_ap_id(user.ap_id) user = User.get_cached_by_ap_id(user.ap_id)
assert User.fields(user) == [] assert user.fields == []
end end
test "it works for incoming update activities which lock the account" do test "it works for incoming update activities which lock the account" do
@ -2162,4 +2162,18 @@ test "sets `replies` collection with a limited number of self-replies" do
Transmogrifier.set_replies(object.data)["replies"] Transmogrifier.set_replies(object.data)["replies"]
end end
end end
test "take_emoji_tags/1" do
user = insert(:user, %{emoji: %{"firefox" => "https://example.org/firefox.png"}})
assert Transmogrifier.take_emoji_tags(user) == [
%{
"icon" => %{"type" => "Image", "url" => "https://example.org/firefox.png"},
"id" => "https://example.org/firefox.png",
"name" => ":firefox:",
"type" => "Emoji",
"updated" => "1970-01-01T00:00:00Z"
}
]
end
end end

View File

@ -38,7 +38,7 @@ test "Renders profile fields" do
end end
test "Renders with emoji tags" do test "Renders with emoji tags" do
user = insert(:user, emoji: [%{"bib" => "/test"}]) user = insert(:user, emoji: %{"bib" => "/test"})
assert %{ assert %{
"tag" => [ "tag" => [

View File

@ -97,18 +97,6 @@ test "it adds emoji in the object" do
assert Object.normalize(activity).data["emoji"]["firefox"] assert Object.normalize(activity).data["emoji"]["firefox"]
end end
test "it adds emoji when updating profiles" do
user = insert(:user, %{name: ":firefox:"})
{:ok, activity} = CommonAPI.update(user)
user = User.get_cached_by_ap_id(user.ap_id)
[firefox] = user.source_data["tag"]
assert firefox["name"] == ":firefox:"
assert Pleroma.Constants.as_public() in activity.recipients
end
describe "posting" do describe "posting" do
test "it supports explicit addressing" do test "it supports explicit addressing" do
user = insert(:user) user = insert(:user)

View File

@ -7,7 +7,6 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do
alias Pleroma.Object alias Pleroma.Object
alias Pleroma.Web.CommonAPI alias Pleroma.Web.CommonAPI
alias Pleroma.Web.CommonAPI.Utils alias Pleroma.Web.CommonAPI.Utils
alias Pleroma.Web.Endpoint
use Pleroma.DataCase use Pleroma.DataCase
import ExUnit.CaptureLog import ExUnit.CaptureLog
@ -42,28 +41,6 @@ test "correct password given" do
end end
end end
test "parses emoji from name and bio" do
{:ok, user} = UserBuilder.insert(%{name: ":blank:", bio: ":firefox:"})
expected = [
%{
"type" => "Emoji",
"icon" => %{"type" => "Image", "url" => "#{Endpoint.url()}/emoji/Firefox.gif"},
"name" => ":firefox:"
},
%{
"type" => "Emoji",
"icon" => %{
"type" => "Image",
"url" => "#{Endpoint.url()}/emoji/blank.png"
},
"name" => ":blank:"
}
]
assert expected == Utils.emoji_from_profile(user)
end
describe "format_input/3" do describe "format_input/3" do
test "works for bare text/plain" do test "works for bare text/plain" do
text = "hello world!" text = "hello world!"

View File

@ -78,7 +78,7 @@ test "it federates only to reachable instances via AP" do
local: false, local: false,
nickname: "nick1@domain.com", nickname: "nick1@domain.com",
ap_id: "https://domain.com/users/nick1", ap_id: "https://domain.com/users/nick1",
source_data: %{"inbox" => inbox1}, inbox: inbox1,
ap_enabled: true ap_enabled: true
}) })
@ -86,7 +86,7 @@ test "it federates only to reachable instances via AP" do
local: false, local: false,
nickname: "nick2@domain2.com", nickname: "nick2@domain2.com",
ap_id: "https://domain2.com/users/nick2", ap_id: "https://domain2.com/users/nick2",
source_data: %{"inbox" => inbox2}, inbox: inbox2,
ap_enabled: true ap_enabled: true
}) })

View File

@ -19,16 +19,6 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
end end
test "Represent a user account" do test "Represent a user account" do
source_data = %{
"tag" => [
%{
"type" => "Emoji",
"icon" => %{"url" => "/file.png"},
"name" => ":karjalanpiirakka:"
}
]
}
background_image = %{ background_image = %{
"url" => [%{"href" => "https://example.com/images/asuka_hospital.png"}] "url" => [%{"href" => "https://example.com/images/asuka_hospital.png"}]
} }
@ -37,13 +27,13 @@ test "Represent a user account" do
insert(:user, %{ insert(:user, %{
follower_count: 3, follower_count: 3,
note_count: 5, note_count: 5,
source_data: source_data,
background: background_image, background: background_image,
nickname: "shp@shitposter.club", nickname: "shp@shitposter.club",
name: ":karjalanpiirakka: shp", name: ":karjalanpiirakka: shp",
bio: bio:
"<script src=\"invalid-html\"></script><span>valid html</span>. a<br>b<br/>c<br >d<br />f", "<script src=\"invalid-html\"></script><span>valid html</span>. a<br>b<br/>c<br >d<br />f",
inserted_at: ~N[2017-08-15 15:47:06.597036] inserted_at: ~N[2017-08-15 15:47:06.597036],
emoji: %{"karjalanpiirakka" => "/file.png"}
}) })
expected = %{ expected = %{
@ -117,7 +107,6 @@ test "Represent a Service(bot) account" do
insert(:user, %{ insert(:user, %{
follower_count: 3, follower_count: 3,
note_count: 5, note_count: 5,
source_data: %{},
actor_type: "Service", actor_type: "Service",
nickname: "shp@shitposter.club", nickname: "shp@shitposter.club",
inserted_at: ~N[2017-08-15 15:47:06.597036] inserted_at: ~N[2017-08-15 15:47:06.597036]
@ -311,7 +300,6 @@ test "represent an embedded relationship" do
insert(:user, %{ insert(:user, %{
follower_count: 0, follower_count: 0,
note_count: 5, note_count: 5,
source_data: %{},
actor_type: "Service", actor_type: "Service",
nickname: "shp@shitposter.club", nickname: "shp@shitposter.club",
inserted_at: ~N[2017-08-15 15:47:06.597036] inserted_at: ~N[2017-08-15 15:47:06.597036]