subs ++
Enum.map(mentions, fn {match, %User{ap_id: ap_id, info: info}, uuid} ->
ap_id =
- if is_binary(info["source_data"]["url"]) do
- info["source_data"]["url"]
+ if is_binary(info.source_data["url"]) do
+ info.source_data["url"]
else
ap_id
end
with token when not is_nil(token) <- token,
%Token{user_id: user_id} <- Repo.get_by(Token, token: token),
%User{} = user <- Repo.get(User, user_id),
- false <- !!user.info["deactivated"] do
+ false <- !!user.info.deactivated do
conn
|> assign(:user, user)
else
options
end
- def call(%{assigns: %{user: %User{info: %{"is_admin" => true}}}} = conn, _) do
+ def call(%{assigns: %{user: %User{info: %{is_admin: true}}}} = conn, _) do
conn
end
field(:ap_id, :string)
field(:avatar, :map)
field(:local, :boolean, default: true)
- field(:info, :map, default: %{})
field(:follower_address, :string)
field(:search_distance, :float, virtual: true)
field(:last_refreshed_at, :naive_datetime)
has_many(:notifications, Notification)
+ embeds_one(:info, Pleroma.User.Info)
timestamps()
end
end
def banner_url(user) do
- case user.info["banner"] do
+ case user.info.banner do
%{"url" => [%{"href" => href} | _]} -> href
_ -> "#{Web.base_url()}/images/banner.png"
end
end
- def profile_url(%User{info: %{"source_data" => %{"url" => url}}}), do: url
+ def profile_url(%User{info: %{source_data: %{"url" => url}}}), do: url
def profile_url(%User{ap_id: ap_id}), do: ap_id
def profile_url(_), do: nil
end
def info_changeset(struct, params \\ %{}) do
- struct
- |> cast(params, [:info])
- |> validate_required([:info])
+ raise "NOT VALID ANYMORE"
end
def user_info(%User{} = user) do
%{
following_count: length(user.following) - oneself,
- note_count: user.info["note_count"] || 0,
- follower_count: user.info["follower_count"] || 0,
- locked: user.info["locked"] || false,
- default_scope: user.info["default_scope"] || "public"
+ note_count: user.info.note_count,
+ follower_count: user.info.follower_count,
+ locked: user.info.locked,
+ default_scope: user.info.default_scope
}
end
@email_regex ~r/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/
def remote_user_creation(params) do
+ params =
+ params
+ |> Map.put(:info, params[:info] || %{})
+
+ info_cng = User.Info.remote_user_creation(%User.Info{}, params[:info])
+
changes =
%User{}
- |> cast(params, [:bio, :name, :ap_id, :nickname, :info, :avatar])
+ |> cast(params, [:bio, :name, :ap_id, :nickname, :avatar])
|> validate_required([:name, :ap_id])
|> unique_constraint(:nickname)
|> validate_format(:nickname, @email_regex)
|> validate_length(:bio, max: 5000)
|> validate_length(:name, max: 100)
|> put_change(:local, false)
+ |> put_embed(:info, info_cng)
if changes.valid? do
- case changes.changes[:info]["source_data"] do
+ case info_cng.changes[:source_data] do
%{"followers" => followers} ->
changes
|> put_change(:follower_address, followers)
end
end
+ # TODO: Check if this still used
def update_changeset(struct, params \\ %{}) do
struct
|> cast(params, [:bio, :name])
params
|> Map.put(:last_refreshed_at, NaiveDateTime.utc_now())
+ info_cng =
+ struct.info
+ |> User.Info.user_upgrade(params[:info])
+
struct
- |> cast(params, [:bio, :name, :info, :follower_address, :avatar, :last_refreshed_at])
+ |> cast(params, [:bio, :name, :follower_address, :avatar, :last_refreshed_at])
|> unique_constraint(:nickname)
|> validate_format(:nickname, ~r/^[a-zA-Z\d]+$/)
|> validate_length(:bio, max: 5000)
|> validate_length(:name, max: 100)
+ |> put_embed(:info, info_cng)
end
def password_update_changeset(struct, params) do
def needs_update?(_), do: true
- def maybe_direct_follow(%User{} = follower, %User{local: true, info: %{"locked" => true}}) do
+ def maybe_direct_follow(%User{} = follower, %User{local: true, info: %{locked: true}}) do
{:ok, follower}
end
ap_followers = followed.follower_address
cond do
- following?(follower, followed) or info["deactivated"] ->
+ following?(follower, followed) or info.deactivated ->
{:error, "Could not follow user: #{followed.nickname} is already on your list."}
deny_follow_blocked and blocks?(followed, follower) ->
end
def locked?(%User{} = user) do
- user.info["locked"] || false
+ user.info.locked || false
end
def get_by_ap_id(ap_id) do
end
def increase_note_count(%User{} = user) do
- note_count = (user.info["note_count"] || 0) + 1
- new_info = Map.put(user.info, "note_count", note_count)
+ info_cng = User.Info.add_to_note_count(user.info, 1)
- cs = info_changeset(user, %{info: new_info})
+ cng =
+ change(user)
+ |> put_embed(:info, info_cng)
- update_and_set_cache(cs)
+ update_and_set_cache(cng)
end
def decrease_note_count(%User{} = user) do
- note_count = user.info["note_count"] || 0
- note_count = if note_count <= 0, do: 0, else: note_count - 1
- new_info = Map.put(user.info, "note_count", note_count)
+ info_cng = User.Info.add_to_note_count(user.info, -1)
- cs = info_changeset(user, %{info: new_info})
+ cng =
+ change(user)
+ |> put_embed(:info, info_cng)
- update_and_set_cache(cs)
+ update_and_set_cache(cng)
end
def update_note_count(%User{} = user) do
note_count = Repo.one(note_count_query)
- new_info = Map.put(user.info, "note_count", note_count)
+ info_cng = User.Info.set_note_count(user.info, note_count)
- cs = info_changeset(user, %{info: new_info})
+ cng =
+ change(user)
+ |> put_embed(:info, info_cng)
- update_and_set_cache(cs)
+ update_and_set_cache(cng)
end
def update_follower_count(%User{} = user) do
follower_count = Repo.one(follower_count_query)
- new_info = Map.put(user.info, "follower_count", follower_count)
+ info_cng =
+ user.info
+ |> User.Info.set_follower_count(follower_count)
- cs = info_changeset(user, %{info: new_info})
+ cng =
+ change(user)
+ |> put_embed(:info, info_cng)
- update_and_set_cache(cs)
+ update_and_set_cache(cng)
end
def get_users_from_set_query(ap_ids, false) do
unfollow(blocked, blocker)
end
- blocks = blocker.info["blocks"] || []
- new_blocks = Enum.uniq([ap_id | blocks])
- new_info = Map.put(blocker.info, "blocks", new_blocks)
+ info_cng =
+ blocker.info
+ |> User.Info.add_to_block(ap_id)
+
+ cng =
+ change(blocker)
+ |> put_embed(:info, info_cng)
- cs = User.info_changeset(blocker, %{info: new_info})
- update_and_set_cache(cs)
+ update_and_set_cache(cng)
end
# helper to handle the block given only an actor's AP id
block(blocker, User.get_by_ap_id(ap_id))
end
- def unblock(user, %{ap_id: ap_id}) do
- blocks = user.info["blocks"] || []
- new_blocks = List.delete(blocks, ap_id)
- new_info = Map.put(user.info, "blocks", new_blocks)
+ def unblock(blocker, %{ap_id: ap_id}) do
+ info_cng =
+ blocker.info
+ |> User.Info.remove_from_block(ap_id)
- cs = User.info_changeset(user, %{info: new_info})
- update_and_set_cache(cs)
+ cng =
+ change(blocker)
+ |> put_embed(:info, info_cng)
+
+ update_and_set_cache(cng)
end
def blocks?(user, %{ap_id: ap_id}) do
- blocks = user.info["blocks"] || []
- domain_blocks = user.info["domain_blocks"] || []
+ blocks = user.info.blocks
+ domain_blocks = user.info.domain_blocks
%{host: host} = URI.parse(ap_id)
Enum.member?(blocks, ap_id) ||
end
def block_domain(user, domain) do
- domain_blocks = user.info["domain_blocks"] || []
- new_blocks = Enum.uniq([domain | domain_blocks])
- new_info = Map.put(user.info, "domain_blocks", new_blocks)
+ info_cng =
+ user.info
+ |> User.Info.add_to_domain_block(domain)
+
+ cng =
+ change(user)
+ |> put_embed(:info, info_cng)
- cs = User.info_changeset(user, %{info: new_info})
- update_and_set_cache(cs)
+ update_and_set_cache(cng)
end
def unblock_domain(user, domain) do
- blocks = user.info["domain_blocks"] || []
- new_blocks = List.delete(blocks, domain)
- new_info = Map.put(user.info, "domain_blocks", new_blocks)
+ info_cng =
+ user.info
+ |> User.Info.remove_from_domain_block(domain)
+
+ cng =
+ change(user)
+ |> put_embed(:info, info_cng)
- cs = User.info_changeset(user, %{info: new_info})
- update_and_set_cache(cs)
+ update_and_set_cache(cng)
end
def local_user_query() do
end
def deactivate(%User{} = user, status \\ true) do
- new_info = Map.put(user.info, "deactivated", status)
- cs = User.info_changeset(user, %{info: new_info})
- update_and_set_cache(cs)
+ info_cng = User.Info.set_activation_status(user.info, status)
+
+ cng =
+ change(user)
+ |> put_embed(:info, info_cng)
+
+ update_and_set_cache(cng)
end
def delete(%User{} = user) do
user
else
changes =
- %User{}
+ %User{info: %User.Info{}}
|> cast(%{}, [:ap_id, :nickname, :local])
|> put_change(:ap_id, relay_uri)
|> put_change(:nickname, nil)
# AP style
def public_key_from_info(%{
- "source_data" => %{"publicKey" => %{"publicKeyPem" => public_key_pem}}
+ source_data: %{"publicKey" => %{"publicKeyPem" => public_key_pem}}
}) do
key =
:public_key.pem_decode(public_key_pem)
end
# OStatus Magic Key
- def public_key_from_info(%{"magic_key" => magic_key}) do
+ def public_key_from_info(%{magic_key: magic_key}) do
{:ok, Pleroma.Web.Salmon.decode_key(magic_key)}
end
|> Map.put(:name, blank?(data[:name]) || data[:nickname])
cs = User.remote_user_creation(data)
+
Repo.insert(cs, on_conflict: :replace_all, conflict_target: :nickname)
end
def ap_enabled?(%User{local: true}), do: true
- def ap_enabled?(%User{info: info}), do: info["ap_enabled"]
+ def ap_enabled?(%User{info: info}), do: info.ap_enabled
def ap_enabled?(_), do: false
def get_or_fetch(uri_or_nickname) do
--- /dev/null
+defmodule Pleroma.User.Info do
+ use Ecto.Schema
+ import Ecto.Changeset
+
+ embedded_schema do
+ field(:banner, :map, default: %{})
+ field(:background, :string, default: nil)
+ field(:source_data, :map, default: %{})
+ field(:note_count, :integer, default: 0)
+ field(:follower_count, :integer, default: 0)
+ field(:locked, :boolean, default: false)
+ field(:default_scope, :string, default: "public")
+ field(:blocks, {:array, :string}, default: [])
+ field(:domain_blocks, {: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(:keys, :string, default: nil)
+ field(:settings, :map, default: nil)
+ field(:magic_key, :string, default: nil)
+ field(:uri, :string, default: nil)
+ field(:topic, :string, default: nil)
+ field(:hub, :string, default: nil)
+ # topic, subject, salmon, subscribe_address, uri
+ end
+
+ def set_activation_status(info, deactivated) do
+ params = %{deactivated: deactivated}
+
+ info
+ |> cast(params, [:deactivated])
+ |> validate_required([:deactivated])
+ 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_blocks(info, blocks) do
+ params = %{blocks: blocks}
+
+ info
+ |> cast(params, [:blocks])
+ |> validate_required([:blocks])
+ end
+
+ def add_to_block(info, blocked) do
+ set_blocks(info, Enum.uniq([blocked | info.blocks]))
+ end
+
+ def remove_from_block(info, blocked) do
+ set_blocks(info, List.delete(info.blocks, blocked))
+ end
+
+ def set_domain_blocks(info, domain_blocks) do
+ params = %{domain_blocks: domain_blocks}
+
+ info
+ |> cast(params, [:domain_blocks])
+ |> validate_required([:domain_blocks])
+ end
+
+ def add_to_domain_block(info, domain_blocked) do
+ set_domain_blocks(info, Enum.uniq([domain_blocked | info.domain_blocks]))
+ end
+
+ def remove_from_domain_block(info, domain_blocked) do
+ set_domain_blocks(info, List.delete(info.domain_blocks, domain_blocked))
+ end
+
+ def set_keys(info, keys) do
+ params = %{keys: keys}
+
+ info
+ |> cast(params, [:keys])
+ |> validate_required([:keys])
+ end
+
+ def remote_user_creation(info, params) do
+ info
+ |> cast(params, [
+ :ap_enabled,
+ :source_data,
+ :banner,
+ :locked,
+ :magic_key,
+ :uri,
+ :hub,
+ :topic
+ ])
+ end
+
+ def user_upgrade(info, params) do
+ info
+ |> cast(params, [
+ :ap_enabled,
+ :source_data,
+ :banner,
+ :locked,
+ :magic_key
+ ])
+ end
+
+ def profile_update(info, params) do
+ info
+ |> cast(params, [
+ :locked,
+ :no_rich_text,
+ :default_scope
+ ])
+ 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
+ ])
+ end
+end
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.info.deactivated do
:ok
else
_e -> :reject
end
defp restrict_blocked(query, %{"blocking_user" => %User{info: info}}) do
- blocks = info["blocks"] || []
- domain_blocks = info["domain_blocks"] || []
+ blocks = info.blocks || []
+ domain_blocks = info.domain_blocks || []
from(
activity in query,
remote_inboxes =
(Pleroma.Web.Salmon.remote_users(activity) ++ followers)
|> Enum.filter(fn user -> User.ap_enabled?(user) end)
- |> Enum.map(fn %{info: %{"source_data" => data}} ->
+ |> Enum.map(fn %{info: %{source_data: data}} ->
(is_map(data["endpoints"]) && Map.get(data["endpoints"], "sharedInbox")) || data["inbox"]
end)
|> Enum.uniq()
update_data =
new_user_data
|> Map.take([:name, :bio, :avatar])
- |> Map.put(:info, Map.merge(actor.info, %{"banner" => banner, "locked" => locked}))
+ |> Map.put(:info, %{"banner" => banner, "locked" => locked})
actor
|> User.upgrade_changeset(update_data)
def upgrade_user_from_ap_id(ap_id, async \\ true) do
with %User{local: false} = user <- User.get_by_ap_id(ap_id),
{:ok, data} <- ActivityPub.fetch_and_prepare_user_from_ap_id(ap_id) do
- data =
- data
- |> Map.put(:info, Map.merge(user.info, data[:info]))
-
already_ap = User.ap_enabled?(user)
{:ok, user} =
# the instance itself is not a Person, but instead an Application
def render("user.json", %{user: %{nickname: nil} = user}) do
{:ok, user} = WebFinger.ensure_keys_present(user)
- {:ok, _, public_key} = Salmon.keys_from_pem(user.info["keys"])
+ {:ok, _, public_key} = Salmon.keys_from_pem(user.info.keys)
public_key = :public_key.pem_entry_encode(:SubjectPublicKeyInfo, public_key)
public_key = :public_key.pem_encode([public_key])
def render("user.json", %{user: user}) do
{:ok, user} = WebFinger.ensure_keys_present(user)
- {:ok, _, public_key} = Salmon.keys_from_pem(user.info["keys"])
+ {:ok, _, public_key} = Salmon.keys_from_pem(user.info.keys)
public_key = :public_key.pem_entry_encode(:SubjectPublicKeyInfo, public_key)
public_key = :public_key.pem_encode([public_key])
"name" => user.name,
"summary" => user.bio,
"url" => user.ap_id,
- "manuallyApprovesFollowers" => user.info["locked"] || false,
+ "manuallyApprovesFollowers" => user.info.locked,
"publicKey" => %{
"id" => "#{user.ap_id}#main-key",
"owner" => user.ap_id,
"type" => "Image",
"url" => User.banner_url(user)
},
- "tag" => user.info["source_data"]["tag"] || []
+ "tag" => user.info.source_data["tag"] || []
}
|> Map.merge(Utils.make_json_ld_header())
end
user = User.get_by_nickname(nickname)
info =
- user.info
+ %{}
|> Map.put("is_" <> permission_group, true)
- cng = User.info_changeset(user, %{info: info})
+ info_cng = User.Info.admin_api_update(user.info, info)
+
+ cng =
+ Ecto.Changeset.change(user)
+ |> Ecto.Changeset.put_embed(:info, info_cng)
+
{:ok, user} = User.update_and_set_cache(cng)
conn
- |> json(user.info)
+ |> json(info)
end
def right_get(conn, %{"nickname" => nickname}) do
user = User.get_by_nickname(nickname)
conn
- |> json(user.info)
+ |> json(%{
+ is_moderator: user.info.is_moderator,
+ is_admin: user.info.is_admin
+ })
end
def right_add(conn, _) do
user = User.get_by_nickname(nickname)
info =
- user.info
+ %{}
|> Map.put("is_" <> permission_group, false)
- cng = User.info_changeset(user, %{info: info})
+ info_cng = User.Info.admin_api_update(user.info, info)
+
+ cng =
+ Ecto.Changeset.change(user)
+ |> Ecto.Changeset.put_embed(:info, info_cng)
+
{:ok, user} = User.update_and_set_cache(cng)
conn
- |> json(user.info)
+ |> json(info)
end
end
def delete(activity_id, user) do
with %Activity{data: %{"object" => %{"id" => object_id}}} <- Repo.get(Activity, activity_id),
%Object{} = object <- Object.normalize(object_id),
- true <- user.info["is_moderator"] || user.ap_id == object.data["actor"],
+ true <- user.info.is_moderator || user.ap_id == object.data["actor"],
{:ok, delete} <- ActivityPub.delete(object) do
{:ok, delete}
end
end
end
+ # Updates the emojis for a user based on their profile
def update(user) do
user =
with emoji <- emoji_from_profile(user),
- source_data <- (user.info["source_data"] || %{}) |> Map.put("tag", emoji),
- new_info <- Map.put(user.info, "source_data", source_data),
- change <- User.info_changeset(user, %{info: new_info}),
+ source_data <- (user.info.source_data || %{}) |> Map.put("tag", emoji),
+ info_cng <- Pleroma.User.Info.set_source_data(user.info, source_data),
+ change <- Ecto.Changeset.change(user) |> Ecto.Changeset.put_embed(:info, info_cng),
{:ok, user} <- User.update_and_set_cache(change) do
user
else
end
def sign(user, headers) do
- with {:ok, %{info: %{"keys" => keys}}} <- Pleroma.Web.WebFinger.ensure_keys_present(user),
+ with {:ok, %{info: %{keys: keys}}} <- Pleroma.Web.WebFinger.ensure_keys_present(user),
{:ok, private_key, _} = Pleroma.Web.Salmon.keys_from_pem(keys) do
sigstring = build_signing_string(headers, Map.keys(headers))
user
end
- user =
- if banner = params["header"] do
- with %Plug.Upload{} <- banner,
- {:ok, object} <- ActivityPub.upload(banner, type: :banner),
- new_info <- Map.put(user.info, "banner", object.data),
- change <- User.info_changeset(user, %{info: new_info}),
- {:ok, user} <- User.update_and_set_cache(change) do
- user
- else
- _e -> user
- end
- else
- user
- end
-
- user =
- if locked = params["locked"] do
- with locked <- locked == "true",
- new_info <- Map.put(user.info, "locked", locked),
- change <- User.info_changeset(user, %{info: new_info}),
- {:ok, user} <- User.update_and_set_cache(change) do
- user
- else
- _e -> user
- end
- else
- user
- end
+ # user =
+ # if banner = params["header"] do
+ # with %Plug.Upload{} <- banner,
+ # {:ok, object} <- ActivityPub.upload(banner, type: :banner),
+ # new_info <- Map.put(user.info, "banner", object.data),
+ # change <- User.info_changeset(user, %{info: new_info}),
+ # {:ok, user} <- User.update_and_set_cache(change) do
+ # user
+ # else
+ # _e -> user
+ # end
+ # else
+ # user
+ # end
+
+ # user =
+ # if locked = params["locked"] do
+ # with locked <- locked == "true",
+ # new_info <- Map.put(user.info, "locked", locked),
+ # change <- User.info_changeset(user, %{info: new_info}),
+ # {:ok, user} <- User.update_and_set_cache(change) do
+ # user
+ # else
+ # _e -> user
+ # end
+ # else
+ # user
+ # end
with changeset <- User.update_changeset(user, params),
{:ok, user} <- User.update_and_set_cache(changeset) do
# TODO: Use proper query
def blocks(%{assigns: %{user: user}} = conn, _) do
- with blocked_users <- user.info["blocks"] || [],
+ with blocked_users <- user.info.blocks || [],
accounts <- Enum.map(blocked_users, fn ap_id -> User.get_cached_by_ap_id(ap_id) end) do
res = AccountView.render("accounts.json", users: accounts, for: user, as: :user)
json(conn, res)
end
def domain_blocks(%{assigns: %{user: %{info: info}}} = conn, _) do
- json(conn, info["domain_blocks"] || [])
+ json(conn, info.domain_blocks || [])
end
def block_domain(%{assigns: %{user: blocker}} = conn, %{"domain" => domain}) do
max_toot_chars: limit
},
rights: %{
- delete_others_notice: !!user.info["is_moderator"]
+ delete_others_notice: !!user.info.is_moderator
},
compose: %{
me: "#{user.id}",
- default_privacy: user.info["default_scope"] || "public",
+ default_privacy: user.info.default_scope,
default_sensitive: false
},
media_attachments: %{
]
},
settings:
- Map.get(user.info, "settings") ||
+ Map.get(user.info, :settings) ||
%{
onboarded: true,
home: %{
image = User.avatar_url(user) |> MediaProxy.url()
header = User.banner_url(user) |> MediaProxy.url()
user_info = User.user_info(user)
- bot = (user.info["source_data"]["type"] || "Person") in ["Application", "Service"]
+ bot = (user.info.source_data["type"] || "Person") in ["Application", "Service"]
emojis =
- (user.info["source_data"]["tag"] || [])
+ (user.info.source_data["tag"] || [])
|> Enum.filter(fn %{"type" => t} -> t == "Emoji" end)
|> Enum.map(fn %{"icon" => %{"url" => url}, "name" => name} ->
%{
end)
fields =
- (user.info["source_data"]["attachment"] || [])
+ (user.info.source_data["attachment"] || [])
|> Enum.filter(fn %{"type" => t} -> t == "PropertyValue" end)
|> Enum.map(fn fields -> Map.take(fields, ["name", "value"]) end)
old_data = %{
avatar: user.avatar,
bio: user.bio,
- name: user.name,
- info: user.info
+ name: user.name
}
with false <- user.local,
avatar <- make_avatar_object(doc),
bio <- string_from_xpath("//author[1]/summary", doc),
name <- string_from_xpath("//author[1]/poco:displayName", doc),
- info <-
- Map.put(user.info, "banner", make_avatar_object(doc, "header") || user.info["banner"]),
new_data <- %{
avatar: avatar || old_data.avatar,
name: name || old_data.name,
- bio: bio || old_data.bio,
- info: info || old_data.info
+ bio: bio || old_data.bio
},
false <- new_data == old_data do
change = Ecto.Changeset.change(user, new_data)
- Repo.update(change)
+ User.update_and_set_cache(change)
else
_ ->
{:ok, user}
post("/account/update_profile_banner", TwitterAPI.Controller, :update_banner)
post("/qvitter/update_background_image", TwitterAPI.Controller, :update_background)
- post(
- "/account/most_recent_notification",
- TwitterAPI.Controller,
- :update_most_recent_notification
- )
-
get("/statuses/home_timeline", TwitterAPI.Controller, :friends_timeline)
get("/statuses/friends_timeline", TwitterAPI.Controller, :friends_timeline)
get("/statuses/mentions", TwitterAPI.Controller, :mentions_timeline)
# Get the current user so we have up-to-date blocks etc.
if socket.assigns[:user] do
user = User.get_cached_by_ap_id(socket.assigns[:user].ap_id)
- blocks = user.info["blocks"] || []
+ blocks = user.info.blocks || []
parent = Object.normalize(item.data["object"])
# Get the current user so we have up-to-date blocks etc.
if socket.assigns[:user] do
user = User.get_cached_by_ap_id(socket.assigns[:user].ap_id)
- blocks = user.info["blocks"] || []
+ blocks = user.info.blocks || []
unless item.actor in blocks do
send(socket.transport_pid, {:text, represent_update(item, user)})
cond do
registrations_open || (!is_nil(token) && !token.used) ->
- changeset = User.register_changeset(%User{}, params)
+ changeset = User.register_changeset(%User{info: %{}}, params)
with {:ok, user} <- Repo.insert(changeset) do
!registrations_open && UserInviteToken.mark_as_used(token.token)
def get_external_profile(for_user, uri) do
with %User{} = user <- User.get_or_fetch(uri) do
- spawn(fn ->
- with url <- user.info["topic"],
- {:ok, %{body: body}} <-
- @httpoison.get(url, [], follow_redirect: true, timeout: 10000, recv_timeout: 20000) do
- OStatus.handle_incoming(body)
- end
- end)
-
{:ok, UserView.render("show.json", %{user: user, for: for_user})}
else
_e ->
end
end
- def update_most_recent_notification(%{assigns: %{user: user}} = conn, %{"id" => id}) do
- with id when is_number(id) <- String.to_integer(id),
- info <- user.info,
- mrn <- max(id, user.info["most_recent_notification"] || 0),
- updated_info <- Map.put(info, "most_recent_notification", mrn),
- changeset <- User.info_changeset(user, %{info: updated_info}),
- {:ok, _user} <- User.update_and_set_cache(changeset) do
- conn
- |> json_reply(200, Jason.encode!(mrn))
- else
- _e -> bad_request_reply(conn, "Can't update.")
- end
- end
-
def followers(conn, params) do
with {:ok, user} <- TwitterAPI.get_user(conn.assigns[:user], params),
{:ok, followers} <- User.get_followers(user) do
json(conn, [])
end
- def update_profile(%{assigns: %{user: user}} = conn, params) do
- params =
- if bio = params["description"] do
- mentions = Formatter.parse_mentions(bio)
- tags = Formatter.parse_tags(bio)
-
- emoji =
- (user.info["source_data"]["tag"] || [])
- |> Enum.filter(fn %{"type" => t} -> t == "Emoji" end)
- |> Enum.map(fn %{"icon" => %{"url" => url}, "name" => name} ->
- {String.trim(name, ":"), url}
- end)
-
- bio_html = CommonUtils.format_input(bio, mentions, tags, "text/plain")
- Map.put(params, "bio", bio_html |> Formatter.emojify(emoji))
- else
- params
- end
-
- user =
- if locked = params["locked"] do
- with locked <- locked == "true",
- new_info <- Map.put(user.info, "locked", locked),
- change <- User.info_changeset(user, %{info: new_info}),
- {:ok, user} <- User.update_and_set_cache(change) do
- user
+ defp build_info_cng(user, params) do
+ info_params =
+ ["no_rich_text", "locked"]
+ |> Enum.reduce(%{}, fn key, res ->
+ if value = params[key] do
+ Map.put(res, key, value == "true")
else
- _e -> user
+ res
end
- else
- user
- end
+ end)
- user =
- if no_rich_text = params["no_rich_text"] do
- with no_rich_text <- no_rich_text == "true",
- new_info <- Map.put(user.info, "no_rich_text", no_rich_text),
- change <- User.info_changeset(user, %{info: new_info}),
- {:ok, user} <- User.update_and_set_cache(change) do
- user
- else
- _e -> user
- end
+ info_params =
+ if value = params["default_scope"] do
+ Map.put(info_params, "default_scope", value)
else
- user
+ info_params
end
- user =
- if default_scope = params["default_scope"] do
- with new_info <- Map.put(user.info, "default_scope", default_scope),
- change <- User.info_changeset(user, %{info: new_info}),
- {:ok, user} <- User.update_and_set_cache(change) do
- user
- else
- _e -> user
- end
- else
- user
- end
+ User.Info.profile_update(user.info, info_params)
+ end
+
+ defp add_profile_emoji(user, params) do
+ if bio = params["description"] do
+ mentions = Formatter.parse_mentions(bio)
+ tags = Formatter.parse_tags(bio)
+
+ emoji =
+ (user.info.source_data["tag"] || [])
+ |> Enum.filter(fn %{"type" => t} -> t == "Emoji" end)
+ |> Enum.map(fn %{"icon" => %{"url" => url}, "name" => name} ->
+ {String.trim(name, ":"), url}
+ end)
+
+ bio_html = CommonUtils.format_input(bio, mentions, tags, "text/plain")
+ Map.put(params, "bio", bio_html |> Formatter.emojify(emoji))
+ else
+ params
+ end
+ end
+
+ def update_profile(%{assigns: %{user: user}} = conn, params) do
+ params = add_profile_emoji(user, params)
+ info_cng = build_info_cng(user, params)
with changeset <- User.update_changeset(user, params),
+ changeset <- Ecto.Changeset.put_embed(changeset, :info, info_cng),
{:ok, user} <- User.update_and_set_cache(changeset) do
CommonAPI.update(user)
render(conn, UserView, "user.json", %{user: user, for: user})
user_info = User.get_cached_user_info(user)
emoji =
- (user.info["source_data"]["tag"] || [])
+ (user.info.source_data["tag"] || [])
|> Enum.filter(fn %{"type" => t} -> t == "Emoji" end)
|> Enum.map(fn %{"icon" => %{"url" => url}, "name" => name} ->
{String.trim(name, ":"), url}
# ``fields`` is an array of mastodon profile field, containing ``{"name": "…", "value": "…"}``.
# For example: [{"name": "Pronoun", "value": "she/her"}, …]
fields =
- (user.info["source_data"]["attachment"] || [])
+ (user.info.source_data["attachment"] || [])
|> Enum.filter(fn %{"type" => t} -> t == "PropertyValue" end)
|> Enum.map(fn fields -> Map.take(fields, ["name", "value"]) end)
"profile_image_url_profile_size" => image,
"profile_image_url_original" => image,
"rights" => %{
- "delete_others_notice" => !!user.info["is_moderator"]
+ "delete_others_notice" => !!user.info.is_moderator
},
"screen_name" => user.nickname,
"statuses_count" => user_info[:note_count],
"statusnet_profile_url" => user.ap_id,
"cover_photo" => User.banner_url(user) |> MediaProxy.url(),
- "background_image" => image_url(user.info["background"]) |> MediaProxy.url(),
+ "background_image" => image_url(user.info.background) |> MediaProxy.url(),
"is_local" => user.local,
- "locked" => !!user.info["locked"],
- "default_scope" => user.info["default_scope"] || "public",
- "no_rich_text" => user.info["no_rich_text"] || false,
+ "locked" => user.info.locked,
+ "default_scope" => user.info.default_scope,
+ "no_rich_text" => user.info.no_rich_text,
"fields" => fields
}
def represent_user(user, "JSON") do
{:ok, user} = ensure_keys_present(user)
- {:ok, _private, public} = Salmon.keys_from_pem(user.info["keys"])
+ {:ok, _private, public} = Salmon.keys_from_pem(user.info.keys)
magic_key = Salmon.encode_key(public)
%{
def represent_user(user, "XML") do
{:ok, user} = ensure_keys_present(user)
- {:ok, _private, public} = Salmon.keys_from_pem(user.info["keys"])
+ {:ok, _private, public} = Salmon.keys_from_pem(user.info.keys)
magic_key = Salmon.encode_key(public)
{
# This seems a better fit in Salmon
def ensure_keys_present(user) do
- info = user.info || %{}
+ info = user.info
- if info["keys"] do
+ if info.keys do
{:ok, user}
else
{:ok, pem} = Salmon.generate_rsa_pem()
- info = Map.put(info, "keys", pem)
- Ecto.Changeset.change(user, info: info)
- |> User.update_and_set_cache()
+ info_cng =
+ info
+ |> Pleroma.User.Info.set_keys(pem)
+
+ cng =
+ Ecto.Changeset.change(user)
+ |> Ecto.Changeset.put_embed(:info, info_cng)
+
+ User.update_and_set_cache(cng)
end
end
end
def subscribe(subscriber, subscribed, requester \\ &request_subscription/1) do
- topic = subscribed.info["topic"]
+ topic = subscribed.info.topic
# FIXME: Race condition, use transactions
{:ok, subscription} =
with subscription when not is_nil(subscription) <-
_e ->
subscription = %WebsubClientSubscription{
topic: topic,
- hub: subscribed.info["hub"],
+ hub: subscribed.info.hub,
subscribers: [subscriber.ap_id],
state: "requested",
secret: :crypto.strong_rand_bytes(8) |> Base.url_encode64(),
archaeme =
insert(:user, %{
nickname: "archaeme",
- info: %{"source_data" => %{"url" => "https://archeme/@archaeme"}}
+ info: %Pleroma.User.Info{source_data: %{"url" => "https://archeme/@archaeme"}}
})
archaeme_remote = insert(:user, %{nickname: "archaeme@archae.me"})
import Pleroma.Factory
test "accepts a user that is admin", %{conn: conn} do
- user = insert(:user, info: %{"is_admin" => true})
+ user = insert(:user, info: %{is_admin: true})
conn =
build_conn()
email: sequence(:email, &"user#{&1}@example.com"),
nickname: sequence(:nickname, &"nick#{&1}"),
password_hash: Comeonin.Pbkdf2.hashpwsalt("test"),
- bio: sequence(:bio, &"Tester Number #{&1}")
+ bio: sequence(:bio, &"Tester Number #{&1}"),
+ info: %{}
}
%{
user = Repo.get(User, user.id)
followed = User.get_by_ap_id(followed.ap_id)
- assert followed.info["follower_count"] == 1
+ assert followed.info.follower_count == 1
assert User.ap_followers(followed) in user.following
end
test "can't follow a deactivated users" do
user = insert(:user)
- followed = insert(:user, info: %{"deactivated" => true})
+ followed = insert(:user, info: %{deactivated: true})
{:error, _} = User.follow(user, followed)
end
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, info: %{locked: true})
+ followed = insert(:user, info: %{locked: true})
{:ok, follower} = User.maybe_direct_follow(follower, followed)
local: false,
nickname: "admin@mastodon.example.org",
ap_id: "http://mastodon.example.org/users/admin",
- last_refreshed_at: a_week_ago
+ last_refreshed_at: a_week_ago,
+ info: %{}
)
assert orig_user.last_refreshed_at == a_week_ago
user = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin")
+ assert user.info.source_data["endpoints"]
refute user.last_refreshed_at == orig_user.last_refreshed_at
end
user = User.get_by_ap_id(note.data["actor"])
- assert user.info["note_count"] == nil
+ assert user.info.note_count == 0
{:ok, user} = User.update_note_count(user)
- assert user.info["note_count"] == 1
+ assert user.info.note_count == 1
end
test "it increases the info->note_count property" do
note = insert(:note)
user = User.get_by_ap_id(note.data["actor"])
- assert user.info["note_count"] == nil
+ assert user.info.note_count == 0
{:ok, user} = User.increase_note_count(user)
- assert user.info["note_count"] == 1
+ assert user.info.note_count == 1
{:ok, user} = User.increase_note_count(user)
- assert user.info["note_count"] == 2
+ assert user.info.note_count == 2
end
test "it decreases the info->note_count property" do
note = insert(:note)
user = User.get_by_ap_id(note.data["actor"])
- assert user.info["note_count"] == nil
+ assert user.info.note_count == 0
{:ok, user} = User.increase_note_count(user)
- assert user.info["note_count"] == 1
+ assert user.info.note_count == 1
{:ok, user} = User.decrease_note_count(user)
- assert user.info["note_count"] == 0
+ assert user.info.note_count == 0
{:ok, user} = User.decrease_note_count(user)
- assert user.info["note_count"] == 0
+ assert user.info.note_count == 0
end
test "it sets the info->follower_count property" do
User.follow(follower, user)
- assert user.info["follower_count"] == nil
+ assert user.info.follower_count == 0
{:ok, user} = User.update_follower_count(user)
- assert user.info["follower_count"] == 1
+ assert user.info.follower_count == 1
end
end
test ".deactivate can de-activate then re-activate a user" do
user = insert(:user)
- assert false == !!user.info["deactivated"]
+ assert false == user.info.deactivated
{:ok, user} = User.deactivate(user)
- assert true == user.info["deactivated"]
+ assert true == user.info.deactivated
{:ok, user} = User.deactivate(user, false)
- assert false == !!user.info["deactivated"]
+ assert false == user.info.deactivated
end
test ".delete deactivates a user, all follow relationships and all create activities" do
follower = Repo.get(User, follower.id)
user = Repo.get(User, user.id)
- assert user.info["deactivated"]
+ assert user.info.deactivated
refute User.following?(user, followed)
refute User.following?(followed, follower)
{: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.info.source_data
+ assert user.info.ap_enabled
assert user.follower_address == "http://mastodon.example.org/users/admin/followers"
end
end
user = User.get_by_ap_id(object["actor"])
- assert user.info["note_count"] == 1
+ assert user.info.note_count == 1
end
test "it works for incoming notices with hashtags" do
}
]
- assert user.info["banner"]["url"] == [
+ assert user.info.banner["url"] == [
%{
"href" =>
"https://cd.niu.moe/accounts/headers/000/033/323/original/850b3448fa5fd477.png"
{: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.info.locked == true
end
test "it works for incoming deletes" do
test "it works for incoming accepts which were orphaned" do
follower = insert(:user)
- followed = insert(:user, %{info: %{"locked" => true}})
+ followed = insert(:user, %{info: %User.Info{locked: true}})
{:ok, follow_activity} = ActivityPub.follow(follower, followed)
test "it works for incoming accepts which are referenced by IRI only" do
follower = insert(:user)
- followed = insert(:user, %{info: %{"locked" => true}})
+ followed = insert(:user, %{info: %User.Info{locked: true}})
{:ok, follow_activity} = ActivityPub.follow(follower, followed)
test "it fails for incoming accepts which cannot be correlated" do
follower = insert(:user)
- followed = insert(:user, %{info: %{"locked" => true}})
+ followed = insert(:user, %{info: %User.Info{locked: true}})
accept_data =
File.read!("test/fixtures/mastodon-accept-activity.json")
test "it fails for incoming rejects which cannot be correlated" do
follower = insert(:user)
- followed = insert(:user, %{info: %{"locked" => true}})
+ followed = insert(:user, %{info: %User.Info{locked: true}})
accept_data =
File.read!("test/fixtures/mastodon-reject-activity.json")
test "it works for incoming rejects which are orphaned" do
follower = insert(:user)
- followed = insert(:user, %{info: %{"locked" => true}})
+ followed = insert(:user, %{info: %User.Info{locked: true}})
{:ok, follower} = User.follow(follower, followed)
{:ok, _follow_activity} = ActivityPub.follow(follower, followed)
test "it works for incoming rejects which are referenced by IRI only" do
follower = insert(:user)
- followed = insert(:user, %{info: %{"locked" => true}})
+ followed = insert(:user, %{info: %User.Info{locked: true}})
{:ok, follower} = User.follow(follower, followed)
{:ok, follow_activity} = ActivityPub.follow(follower, followed)
assert "http://localhost:4001/users/rye@niu.moe/followers" in activity.recipients
user = Repo.get(User, user.id)
- assert user.info["note_count"] == 1
+ assert user.info.note_count == 1
{:ok, user} = Transmogrifier.upgrade_user_from_ap_id("https://niu.moe/users/rye")
- assert user.info["ap_enabled"]
- assert user.info["note_count"] == 1
+ assert user.info.ap_enabled
+ assert user.info.note_count == 1
assert user.follower_address == "https://niu.moe/users/rye/followers"
# Wait for the background task
:timer.sleep(1000)
user = Repo.get(User, user.id)
- assert user.info["note_count"] == 1
+ assert user.info.note_count == 1
activity = Repo.get(Activity, activity.id)
assert user.follower_address in activity.recipients
"https://cdn.niu.moe/accounts/headers/000/033/323/original/850b3448fa5fd477.png"
}
]
- } = user.info["banner"]
+ } = user.info.banner
refute "..." in activity.recipients
describe "/api/pleroma/admin/user" do
test "Delete" do
- admin = insert(:user, info: %{"is_admin" => true})
+ admin = insert(:user, info: %{is_admin: true})
user = insert(:user)
conn =
end
test "Create" do
- admin = insert(:user, info: %{"is_admin" => true})
+ admin = insert(:user, info: %{is_admin: true})
conn =
build_conn()
describe "/api/pleroma/admin/permission_group" do
test "GET is giving user_info" do
- admin = insert(:user, info: %{"is_admin" => true})
+ admin = insert(:user, info: %{is_admin: true})
conn =
build_conn()
|> put_req_header("accept", "application/json")
|> get("/api/pleroma/admin/permission_group/#{admin.nickname}")
- assert json_response(conn, 200) == admin.info
+ assert json_response(conn, 200) == %{
+ "is_admin" => true,
+ "is_moderator" => false
+ }
end
test "/:right POST, can add to a permission group" do
- admin = insert(:user, info: %{"is_admin" => true})
+ admin = insert(:user, info: %{is_admin: true})
user = insert(:user)
- user_info =
- user.info
- |> Map.put("is_admin", true)
-
conn =
build_conn()
|> assign(:user, admin)
|> put_req_header("accept", "application/json")
|> post("/api/pleroma/admin/permission_group/#{user.nickname}/admin")
- assert json_response(conn, 200) == user_info
+ assert json_response(conn, 200) == %{
+ "is_admin" => true
+ }
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})
-
- user_info =
- user.info
- |> Map.put("is_admin", false)
+ admin = insert(:user, info: %{is_admin: true})
+ user = insert(:user, info: %{is_admin: true})
conn =
build_conn()
|> put_req_header("accept", "application/json")
|> delete("/api/pleroma/admin/permission_group/#{user.nickname}/admin")
- assert json_response(conn, 200) == user_info
+ assert json_response(conn, 200) == %{
+ "is_admin" => false
+ }
end
end
test "/api/pleroma/admin/invite_token" do
- admin = insert(:user, info: %{"is_admin" => true})
+ admin = insert(:user, info: %{is_admin: true})
conn =
build_conn()
end
test "/api/pleroma/admin/password_reset" do
- admin = insert(:user, info: %{"is_admin" => true})
- user = insert(:user, info: %{"is_admin" => true})
+ admin = insert(:user, info: %{is_admin: true})
+ user = insert(:user)
conn =
build_conn()
CommonAPI.update(user)
user = User.get_cached_by_ap_id(user.ap_id)
- [karjalanpiirakka] = user.info["source_data"]["tag"]
+ [karjalanpiirakka] = user.info.source_data["tag"]
assert karjalanpiirakka["name"] == ":karjalanpiirakka:"
end
user =
insert(:user, %{
- info: %{"note_count" => 5, "follower_count" => 3, "source_data" => source_data},
+ info: %{note_count: 5, follower_count: 3, source_data: source_data},
nickname: "shp@shitposter.club",
name: ":karjalanpiirakka: shp",
bio: "<script src=\"invalid-html\"></script><span>valid html</span>",
test "Represent a Service(bot) account" do
user =
insert(:user, %{
- info: %{"note_count" => 5, "follower_count" => 3, "source_data" => %{"type" => "Service"}},
+ info: %{note_count: 5, follower_count: 3, source_data: %{"type" => "Service"}},
nickname: "shp@shitposter.club",
inserted_at: ~N[2017-08-15 15:47:06.597036]
})
end
test "verify_credentials default scope unlisted", %{conn: conn} do
- user = insert(:user, %{info: %{"default_scope" => "unlisted"}})
+ user = insert(:user, %{info: %Pleroma.User.Info{default_scope: "unlisted"}})
conn =
conn
describe "locked accounts" do
test "/api/v1/follow_requests works" do
- user = insert(:user, %{info: %{"locked" => true}})
+ user = insert(:user, %{info: %Pleroma.User.Info{locked: true}})
other_user = insert(:user)
{:ok, activity} = ActivityPub.follow(other_user, user)
end
test "/api/v1/follow_requests/:id/authorize works" do
- user = insert(:user, %{info: %{"locked" => true}})
+ user = insert(:user, %{info: %Pleroma.User.Info{locked: true}})
other_user = insert(:user)
{:ok, activity} = ActivityPub.follow(other_user, user)
end
test "verify_credentials", %{conn: conn} do
- user = insert(:user, %{info: %{"default_scope" => "private"}})
+ user = insert(:user, %{info: %Pleroma.User.Info{default_scope: "private"}})
conn =
conn
end
test "/api/v1/follow_requests/:id/reject works" do
- user = insert(:user, %{info: %{"locked" => true}})
+ user = insert(:user, %{info: %Pleroma.User.Info{locked: true}})
other_user = insert(:user)
{:ok, activity} = ActivityPub.follow(other_user, user)
refute User.blocks?(user, other_user)
end
- test "getting a list of domain blocks" do
+ test "getting a list of domain blocks", %{conn: conn} do
user = insert(:user)
{:ok, user} = User.block_domain(user, "bad.site")
import Pleroma.Factory
test "nodeinfo shows staff accounts", %{conn: conn} do
- user = insert(:user, %{local: true, info: %{"is_moderator" => true}})
+ user = insert(:user, %{local: true, info: %{is_moderator: true}})
conn =
conn
assert user.ap_id in result["metadata"]["staffAccounts"]
end
- test "returns 404 when federation is disabled" do
+ test "returns 404 when federation is disabled", %{conn: conn} do
instance =
Application.get_env(:pleroma, :instance)
|> Keyword.put(:federating, false)
Application.put_env(:pleroma, :instance, instance)
end
- test "returns 200 when federation is enabled" do
+ test "returns 200 when federation is enabled", %{conn: conn} do
conn
|> get("/.well-known/nodeinfo")
|> json_response(200)
# Set a wrong magic-key for a user so it has to refetch
salmon_user = User.get_by_ap_id("http://gs.example.org:4040/index.php/user/1")
# Wrong key
- info =
- salmon_user.info
- |> Map.put(
- "magic_key",
- "RSA.pu0s-halox4tu7wmES1FVSx6u-4wc0YrUFXcqWXZG4-27UmbCOpMQftRCldNRfyA-qLbz-eqiwrong1EwUvjsD4cYbAHNGHwTvDOyx5AKthQUP44ykPv7kjKGh3DWKySJvcs9tlUG87hlo7AvnMo9pwRS_Zz2CacQ-MKaXyDepk=.AQAB"
- )
-
- Repo.update(User.info_changeset(salmon_user, %{info: info}))
+ info_cng =
+ User.Info.remote_user_creation(salmon_user.info, %{
+ magic_key:
+ "RSA.pu0s-halox4tu7wmES1FVSx6u-4wc0YrUFXcqWXZG4-27UmbCOpMQftRCldNRfyA-qLbz-eqiwrong1EwUvjsD4cYbAHNGHwTvDOyx5AKthQUP44ykPv7kjKGh3DWKySJvcs9tlUG87hlo7AvnMo9pwRS_Zz2CacQ-MKaXyDepk=.AQAB"
+ })
+
+ cng =
+ Ecto.Changeset.change(salmon_user)
+ |> Ecto.Changeset.put_embed(:info, info_cng)
+ |> Repo.update()
conn =
build_conn()
{:ok, [activity]} = OStatus.handle_incoming(incoming)
user = User.get_by_ap_id(activity.data["actor"])
- assert user.info["note_count"] == 1
+ assert user.info.note_count == 1
assert activity.data["type"] == "Create"
assert activity.data["object"]["type"] == "Note"
assert user.name == "Constance Variable"
assert user.nickname == "lambadalambda@social.heldscal.la"
assert user.local == false
- assert user.info["uri"] == uri
+ assert user.info.uri == uri
assert user.ap_id == uri
assert user.bio == "Call me Deacon Blues."
assert user.avatar["type"] == "Image"
end
end
- test "it doesn't add nil in the do field" do
+ test "it doesn't add nil in the to field" do
incoming = File.read!("test/fixtures/nil_mention_entry.xml")
{:ok, [activity]} = OStatus.handle_incoming(incoming)
alias Pleroma.User
test "returns a user with id, uri, name and link" do
- user = build(:user, nickname: "レイン")
+ user = insert(:user, %{nickname: "レイン"})
tuple = UserRepresenter.to_simple_form(user)
res = :xmerl.export_simple_content(tuple, :xmerl_xml) |> to_string
end
test "an activity" do
- {:ok, user} = UserBuilder.insert()
+ user = insert(:user)
# {:ok, mentioned_user } = UserBuilder.insert(%{nickname: "shp", ap_id: "shp"})
mentioned_user = insert(:user, %{nickname: "shp"})
end
end
- describe "POST /api/account/most_recent_notification" do
- setup [:valid_user]
-
- test "without valid credentials", %{conn: conn} do
- conn = post(conn, "/api/account/most_recent_notification.json")
- assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
- end
-
- test "with credentials", %{conn: conn, user: user} do
- conn =
- conn
- |> with_credentials(user.nickname, "test")
- |> post("/api/account/most_recent_notification.json", %{id: "200"})
-
- assert json_response(conn, 200)
- user = User.get_by_nickname(user.nickname)
- assert user.info["most_recent_notification"] == 200
- end
- end
-
describe "POST /statuses/update.json" do
setup [:valid_user]
describe "GET /statuses/public_timeline.json" do
test "returns statuses", %{conn: conn} do
- {:ok, user} = UserBuilder.insert()
+ user = insert(:user)
activities = ActivityBuilder.insert_list(30, %{}, %{user: user})
ActivityBuilder.insert_list(10, %{}, %{user: user})
since_id = List.last(activities).id
|> post("/api/blocks/destroy.json", %{user_id: blocked.id})
current_user = Repo.get(User, current_user.id)
- assert current_user.info["blocks"] == []
+ assert current_user.info.blocks == []
assert json_response(conn, 200) ==
UserView.render("show.json", %{user: blocked, for: current_user})
})
user = Repo.get!(User, user.id)
- assert user.info["locked"] == true
+ assert user.info.locked == true
assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
end
})
user = Repo.get!(User, user.id)
- assert user.info["locked"] == false
+ assert user.info.locked == false
assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
end
user = insert(:user, %{info: %{"locked" => true}})
other_user = insert(:user)
- {:ok, activity} = ActivityPub.follow(other_user, user)
+ {:ok, _activity} = ActivityPub.follow(other_user, user)
user = Repo.get(User, user.id)
other_user = Repo.get(User, other_user.id)
user = insert(:user, %{info: %{"locked" => true}})
other_user = insert(:user)
- {:ok, activity} = ActivityPub.follow(other_user, user)
+ {:ok, _activity} = ActivityPub.follow(other_user, user)
user = Repo.get(User, user.id)
other_user = Repo.get(User, other_user.id)
user = insert(:user, %{info: %{"locked" => true}})
other_user = insert(:user)
- {:ok, activity} = ActivityPub.follow(other_user, user)
+ {:ok, _activity} = ActivityPub.follow(other_user, user)
user = Repo.get(User, user.id)
other_user = Repo.get(User, other_user.id)
test "create a status" do
user = insert(:user)
- _mentioned_user = UserBuilder.insert(%{nickname: "shp", ap_id: "shp"})
+ _mentioned_user = insert(:user, %{nickname: "shp", ap_id: "shp"})
object_data = %{
"type" => "Image",
user = User.get_by_ap_id(user.ap_id)
- assert user.info["note_count"] == 1
+ assert user.info.note_count == 1
end
test "create a status that is a reply" do
assert User.ap_followers(followed) in user.following
followed = User.get_by_ap_id(followed.ap_id)
- assert followed.info["follower_count"] == 1
+ assert followed.info.follower_count == 1
{:error, msg} = TwitterAPI.follow(user, %{"screen_name" => followed.nickname})
assert msg == "Could not follow user: #{followed.nickname} is already on your list."
{:ok, user, _unblocked} = TwitterAPI.block(user, %{"user_id" => unblocked.id})
{:ok, user, _unblocked} = TwitterAPI.unblock(user, %{"user_id" => unblocked.id})
- assert user.info["blocks"] == []
+ assert user.info.blocks == []
end
test "Unblock another user using screen_name" do
{:ok, user, _unblocked} = TwitterAPI.block(user, %{"screen_name" => unblocked.nickname})
{:ok, user, _unblocked} = TwitterAPI.unblock(user, %{"screen_name" => unblocked.nickname})
- assert user.info["blocks"] == []
+ assert user.info.blocks == []
end
test "upload a file" do
expected =
"<img height=\"32px\" width=\"32px\" alt=\"karjalanpiirakka\" title=\"karjalanpiirakka\" src=\"/file.png\" /> man"
- user = %{
- user
- | info: %{
- "source_data" => %{
+ user =
+ insert(:user, %{
+ info: %{
+ source_data: %{
"tag" => [
%{
"type" => "Emoji",
}
]
}
- }
- }
+ },
+ name: ":karjalanpiirakka: man"
+ })
- user = %{user | name: ":karjalanpiirakka: man"}
represented = UserView.render("show.json", %{user: user})
assert represented["name_html"] == expected
end
end
test "A user for a given other follower", %{user: user} do
- {:ok, follower} = UserBuilder.insert(%{following: [User.ap_followers(user)]})
+ follower = insert(:user, %{following: [User.ap_followers(user)]})
{:ok, user} = User.update_follower_count(user)
image = "http://localhost:4001/images/avi.png"
banner = "http://localhost:4001/images/banner.png"
end
test "a user that is a moderator" do
- user = insert(:user, %{info: %{"is_moderator" => true}})
+ user = insert(:user, %{info: %{is_moderator: true}})
represented = UserView.render("show.json", %{user: user, for: user})
assert represented["rights"]["delete_others_notice"]
user =
insert(:user, %{
info: %{
- "source_data" => %{
+ source_data: %{
"attachment" =>
Enum.map(fields, fn field -> Map.put(field, "type", "PropertyValue") end)
}
describe "ensure_keys_present" do
test "it creates keys for a user and stores them in info" do
user = insert(:user)
- refute is_binary(user.info["keys"])
+ refute is_binary(user.info.keys)
{:ok, user} = WebFinger.ensure_keys_present(user)
- assert is_binary(user.info["keys"])
+ assert is_binary(user.info.keys)
end
test "it doesn't create keys if there already are some" do
- user = insert(:user, %{info: %{"keys" => "xxx"}})
+ user = insert(:user, %{info: %{keys: "xxx"}})
{:ok, user} = WebFinger.ensure_keys_present(user)
- assert user.info["keys"] == "xxx"
+ assert user.info.keys == "xxx"
end
end
end
test "initiate a subscription for a given user and topic" do
subscriber = insert(:user)
- user = insert(:user, %{info: %{"topic" => "some_topic", "hub" => "some_hub"}})
+ user = insert(:user, %{info: %Pleroma.User.Info{topic: "some_topic", hub: "some_hub"}})
{:ok, websub} = Websub.subscribe(subscriber, user, &accepting_verifier/1)
assert websub.subscribers == [subscriber.ap_id]