Merge develop to refactor/mix-tasks

This commit is contained in:
Rin Toshaka 2018-12-05 14:16:55 +01:00
commit 9938fa3293
86 changed files with 1850 additions and 1406 deletions

View file

@ -72,6 +72,7 @@
config :pleroma, :websub, Pleroma.Web.Websub
config :pleroma, :ostatus, Pleroma.Web.OStatus
config :pleroma, :httpoison, Pleroma.HTTP
config :tesla, adapter: Tesla.Adapter.Hackney
# Configures http settings, upstream proxy etc.
config :pleroma, :http, proxy_url: nil

View file

@ -49,10 +49,9 @@
hostname: "localhost",
pool_size: 10
try do
if File.exists?("./config/dev.secret.exs") do
import_config "dev.secret.exs"
rescue
_ ->
else
IO.puts(
"!!! RUNNING IN LOCALHOST DEV MODE! !!!\nFEDERATION WON'T WORK UNTIL YOU CONFIGURE A dev.secret.exs"
)

View file

@ -25,7 +25,7 @@
config :pleroma, :websub, Pleroma.Web.WebsubMock
config :pleroma, :ostatus, Pleroma.Web.OStatusMock
config :pleroma, :httpoison, HTTPoisonMock
config :tesla, adapter: Tesla.Mock
try do
import_config "test.secret.exs"

View file

@ -1,9 +1,7 @@
CREATE USER <%= dbuser %> WITH ENCRYPTED PASSWORD '<%= dbpass %>' CREATEDB;
-- in case someone runs this second time accidentally
ALTER USER <%= dbuser %> WITH ENCRYPTED PASSWORD '<%= dbpass %>' CREATEDB;
CREATE DATABASE <%= dbname %>;
ALTER DATABASE <%= dbname %> OWNER TO <%= dbuser %>;
\c <%= dbname %>;
CREATE USER pleroma WITH ENCRYPTED PASSWORD '<%= dbpass %>';
CREATE DATABASE pleroma_dev OWNER pleroma;
\c pleroma_dev;
--Extensions made by ecto.migrate that need superuser access
CREATE EXTENSION IF NOT EXISTS citext;
CREATE EXTENSION IF NOT EXISTS pg_trgm;
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

View file

@ -116,8 +116,8 @@ def add_user_links({subs, text}, mentions) do
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

View file

@ -0,0 +1,27 @@
defmodule Pleroma.HTTP.Connection do
@moduledoc """
Connection for http-requests.
"""
@hackney_options [pool: :default]
@adapter Application.get_env(:tesla, :adapter)
@doc """
Configure a client connection
# Returns
Tesla.Env.client
"""
@spec new(Keyword.t()) :: Tesla.Env.client()
def new(opts \\ []) do
Tesla.client([], {@adapter, hackney_options(opts)})
end
# fetch Hackney options
#
defp hackney_options(opts \\ []) do
options = Keyword.get(opts, :adapter, [])
@hackney_options ++ options
end
end

View file

@ -1,14 +1,42 @@
defmodule Pleroma.HTTP do
require HTTPoison
@moduledoc """
"""
alias Pleroma.HTTP.Connection
alias Pleroma.HTTP.RequestBuilder, as: Builder
@doc """
Builds and perform http request.
# Arguments:
`method` - :get, :post, :put, :delete
`url`
`body`
`headers` - a keyworld list of headers, e.g. `[{"content-type", "text/plain"}]`
`options` - custom, per-request middleware or adapter options
# Returns:
`{:ok, %Tesla.Env{}}` or `{:error, error}`
"""
def request(method, url, body \\ "", headers \\ [], options \\ []) do
options =
process_request_options(options)
|> process_sni_options(url)
HTTPoison.request(method, url, body, headers, options)
%{}
|> Builder.method(method)
|> Builder.headers(headers)
|> Builder.opts(options)
|> Builder.url(url)
|> Builder.add_param(:body, :body, body)
|> Enum.into([])
|> (&Tesla.request(Connection.new(), &1)).()
end
defp process_sni_options(options, nil), do: options
defp process_sni_options(options, url) do
uri = URI.parse(url)
host = uri.host |> to_charlist()
@ -22,7 +50,7 @@ defp process_sni_options(options, url) do
def process_request_options(options) do
config = Application.get_env(:pleroma, :http, [])
proxy = Keyword.get(config, :proxy_url, nil)
options = options ++ [hackney: [pool: :default]]
options = options ++ [adapter: [pool: :default]]
case proxy do
nil -> options
@ -30,8 +58,19 @@ def process_request_options(options) do
end
end
def get(url, headers \\ [], options \\ []), do: request(:get, url, "", headers, options)
@doc """
Performs GET request.
See `Pleroma.HTTP.request/5`
"""
def get(url, headers \\ [], options \\ []),
do: request(:get, url, "", headers, options)
@doc """
Performs POST request.
See `Pleroma.HTTP.request/5`
"""
def post(url, body, headers \\ [], options \\ []),
do: request(:post, url, body, headers, options)
end

View file

@ -0,0 +1,126 @@
defmodule Pleroma.HTTP.RequestBuilder do
@moduledoc """
Helper functions for building Tesla requests
"""
@doc """
Specify the request method when building a request
## Parameters
- request (Map) - Collected request options
- m (atom) - Request method
## Returns
Map
"""
@spec method(map(), atom) :: map()
def method(request, m) do
Map.put_new(request, :method, m)
end
@doc """
Specify the request method when building a request
## Parameters
- request (Map) - Collected request options
- u (String) - Request URL
## Returns
Map
"""
@spec url(map(), String.t()) :: map()
def url(request, u) do
Map.put_new(request, :url, u)
end
@doc """
Add headers to the request
"""
@spec headers(map(), list(tuple)) :: map()
def headers(request, h) do
Map.put_new(request, :headers, h)
end
@doc """
Add custom, per-request middleware or adapter options to the request
"""
@spec opts(map(), Keyword.t()) :: map()
def opts(request, options) do
Map.put_new(request, :opts, options)
end
@doc """
Add optional parameters to the request
## Parameters
- request (Map) - Collected request options
- definitions (Map) - Map of parameter name to parameter location.
- options (KeywordList) - The provided optional parameters
## Returns
Map
"""
@spec add_optional_params(map(), %{optional(atom) => atom}, keyword()) :: map()
def add_optional_params(request, _, []), do: request
def add_optional_params(request, definitions, [{key, value} | tail]) do
case definitions do
%{^key => location} ->
request
|> add_param(location, key, value)
|> add_optional_params(definitions, tail)
_ ->
add_optional_params(request, definitions, tail)
end
end
@doc """
Add optional parameters to the request
## Parameters
- request (Map) - Collected request options
- location (atom) - Where to put the parameter
- key (atom) - The name of the parameter
- value (any) - The value of the parameter
## Returns
Map
"""
@spec add_param(map(), atom, atom, any()) :: map()
def add_param(request, :body, :body, value), do: Map.put(request, :body, value)
def add_param(request, :body, key, value) do
request
|> Map.put_new_lazy(:body, &Tesla.Multipart.new/0)
|> Map.update!(
:body,
&Tesla.Multipart.add_field(&1, key, Poison.encode!(value),
headers: [{:"Content-Type", "application/json"}]
)
)
end
def add_param(request, :file, name, path) do
request
|> Map.put_new_lazy(:body, &Tesla.Multipart.new/0)
|> Map.update!(:body, &Tesla.Multipart.add_file(&1, path, name: name))
end
def add_param(request, :form, name, value) do
request
|> Map.update(:body, %{name => value}, &Map.put(&1, name, value))
end
def add_param(request, location, key, value) do
Map.update(request, location, [{key, value}], &(&1 ++ [{key, value}]))
end
end

View file

@ -20,7 +20,7 @@ def call(conn, _) do
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

View file

@ -6,7 +6,7 @@ def init(options) do
options
end
def call(%{assigns: %{user: %User{info: %{"deactivated" => true}}}} = conn, _) do
def call(%{assigns: %{user: %User{info: %{deactivated: true}}}} = conn, _) do
conn
|> assign(:user, nil)
end

View file

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

View file

@ -20,7 +20,7 @@ def put_file(upload) do
extension = String.split(upload.name, ".") |> List.last()
query = "#{cgi}?#{extension}"
with {:ok, %{status_code: 200, body: body}} <- @httpoison.post(query, file_data) do
with {:ok, %{status: 200, body: body}} <- @httpoison.post(query, file_data) do
remote_file_name = String.split(body) |> List.first()
public_url = "#{files}/#{remote_file_name}.#{extension}"
{:ok, {:url, public_url}}

View file

@ -25,10 +25,10 @@ def get_token() do
["Content-Type": "application/json"],
hackney: [:insecure]
) do
{:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
{:ok, %Tesla.Env{status: 200, body: body}} ->
body["access"]["token"]["id"]
{:ok, %HTTPoison.Response{status_code: _}} ->
{:ok, %Tesla.Env{status: _}} ->
""
end
end

View file

@ -13,10 +13,10 @@ def upload_file(filename, body, content_type) do
token = Pleroma.Uploaders.Swift.Keystone.get_token()
case put("#{filename}", body, "X-Auth-Token": token, "Content-Type": content_type) do
{:ok, %HTTPoison.Response{status_code: 201}} ->
{:ok, %Tesla.Env{status: 201}} ->
{:ok, {:file, filename}}
{:ok, %HTTPoison.Response{status_code: 401}} ->
{:ok, %Tesla.Env{status: 401}} ->
{:error, "Unauthorized, Bad Token"}
{:error, _} ->

View file

@ -4,6 +4,8 @@ defmodule Pleroma.User do
import Ecto.{Changeset, Query}
alias Pleroma.{Repo, User, Object, Web, Activity, Notification}
alias Comeonin.Pbkdf2
alias Pleroma.Formatter
alias Pleroma.Web.CommonAPI.Utils, as: CommonUtils
alias Pleroma.Web.{OStatus, Websub, OAuth}
alias Pleroma.Web.ActivityPub.{Utils, ActivityPub}
@ -19,11 +21,11 @@ defmodule Pleroma.User do
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
@ -36,13 +38,13 @@ def avatar_url(user) do
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
@ -61,9 +63,7 @@ def follow_changeset(struct, params \\ %{}) do
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
@ -71,27 +71,34 @@ 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)
@ -109,7 +116,7 @@ def remote_user_creation(params) do
def update_changeset(struct, params \\ %{}) do
struct
|> cast(params, [:bio, :name])
|> cast(params, [:bio, :name, :avatar])
|> unique_constraint(:nickname)
|> validate_format(:nickname, ~r/^[a-zA-Z\d]+$/)
|> validate_length(:bio, max: 5000)
@ -121,12 +128,17 @@ def upgrade_changeset(struct, params \\ %{}) do
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
@ -165,6 +177,7 @@ def register_changeset(struct, params \\ %{}) do
|> validate_format(:email, @email_regex)
|> validate_length(:bio, max: 1000)
|> validate_length(:name, min: 1, max: 100)
|> put_change(:info, %Pleroma.User.Info{})
if changeset.valid? do
hashed = Pbkdf2.hashpwsalt(changeset.changes[:password])
@ -191,7 +204,7 @@ def needs_update?(%User{local: false} = user) 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
@ -222,7 +235,7 @@ def follow(%User{} = follower, %User{info: info} = followed) do
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) ->
@ -274,7 +287,7 @@ def following?(%User{} = follower, %User{} = followed) do
end
def locked?(%User{} = user) do
user.info["locked"] || false
user.info.locked || false
end
def get_by_ap_id(ap_id) do
@ -411,22 +424,23 @@ def get_follow_requests(%User{} = user) 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
@ -439,11 +453,13 @@ 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
@ -457,11 +473,15 @@ 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
@ -545,12 +565,15 @@ def block(blocker, %User{ap_id: ap_id} = blocked) 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)
cs = User.info_changeset(blocker, %{info: new_info})
update_and_set_cache(cs)
cng =
change(blocker)
|> put_embed(:info, info_cng)
update_and_set_cache(cng)
end
# helper to handle the block given only an actor's AP id
@ -558,18 +581,21 @@ def block(blocker, %{ap_id: ap_id}) do
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) ||
@ -579,21 +605,27 @@ def blocks?(user, %{ap_id: ap_id}) do
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)
cs = User.info_changeset(user, %{info: new_info})
update_and_set_cache(cs)
cng =
change(user)
|> put_embed(:info, info_cng)
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)
cs = User.info_changeset(user, %{info: new_info})
update_and_set_cache(cs)
cng =
change(user)
|> put_embed(:info, info_cng)
update_and_set_cache(cng)
end
def local_user_query() do
@ -613,9 +645,13 @@ def moderator_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
@ -649,7 +685,7 @@ def delete(%User{} = user) do
{:ok, user}
end
def html_filter_policy(%User{info: %{"no_rich_text" => true}}) do
def html_filter_policy(%User{info: %{no_rich_text: true}}) do
Pleroma.HTML.Scrubber.TwitterText
end
@ -683,7 +719,7 @@ def get_or_create_instance_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)
@ -697,7 +733,7 @@ def get_or_create_instance_user do
# 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)
@ -708,7 +744,7 @@ def public_key_from_info(%{
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
@ -730,11 +766,12 @@ def insert_or_update_user(data) do
|> 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
@ -768,4 +805,18 @@ def wait_and_refresh(timeout, %User{} = a, %User{} = b) do
:error
end
end
def parse_bio(bio, user \\ %User{info: %{source_data: %{}}}) 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)
CommonUtils.format_input(bio, mentions, tags, "text/plain") |> Formatter.emojify(emoji)
end
end

165
lib/pleroma/user/info.ex Normal file
View file

@ -0,0 +1,165 @@
defmodule Pleroma.User.Info do
use Ecto.Schema
import Ecto.Changeset
embedded_schema do
field(:banner, :map, default: %{})
field(:background, :map, default: %{})
field(:source_data, :map, default: %{})
field(:note_count, :integer, default: 0)
field(:follower_count, :integer, default: 0)
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)
field(:salmon, :string, default: nil)
# Found in the wild
# ap_id -> Where is this used?
# bio -> Where is this used?
# avatar -> Where is this used?
# fqn -> Where is this used?
# host -> Where is this used?
# subject _> Where is this used?
end
def set_activation_status(info, deactivated) do
params = %{deactivated: deactivated}
info
|> cast(params, [:deactivated])
|> validate_required([:deactivated])
end
def 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,
:salmon
])
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,
:banner,
:background
])
end
def mastodon_profile_update(info, params) do
info
|> cast(params, [
:locked,
:banner
])
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

View file

@ -42,7 +42,7 @@ defp get_recipients(data) do
defp check_actor_is_active(actor) do
if not is_nil(actor) do
with user <- User.get_cached_by_ap_id(actor),
false <- !!user.info["deactivated"] do
false <- user.info.deactivated do
:ok
else
_e -> :reject
@ -509,8 +509,8 @@ defp restrict_recent(query, _) do
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,
@ -676,7 +676,7 @@ def publish(actor, activity) do
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()
@ -762,7 +762,7 @@ def fetch_and_contain_remote_object_from_id(id) do
Logger.info("Fetching #{id} via AP")
with true <- String.starts_with?(id, "http"),
{:ok, %{body: body, status_code: code}} when code in 200..299 <-
{:ok, %{body: body, status: code}} when code in 200..299 <-
@httpoison.get(
id,
[Accept: "application/activity+json"],

View file

@ -23,7 +23,7 @@ defp check_reject(%{host: actor_host} = _actor_info, object) do
defp check_media_removal(
%{host: actor_host} = _actor_info,
%{"type" => "Create", "object" => %{"attachement" => child_attachment}} = object
%{"type" => "Create", "object" => %{"attachment" => child_attachment}} = object
)
when length(child_attachment) > 0 do
object =

View file

@ -447,7 +447,7 @@ def handle_incoming(
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)
@ -850,10 +850,6 @@ defp user_upgrade_task(user) do
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} =

View file

@ -12,7 +12,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
# 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])
@ -40,7 +40,7 @@ def render("user.json", %{user: %{nickname: nil} = user}) do
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])
@ -55,7 +55,7 @@ def render("user.json", %{user: user}) do
"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,
@ -72,7 +72,7 @@ def render("user.json", %{user: user}) do
"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

View file

@ -45,21 +45,29 @@ def right_add(conn, %{"permission_group" => permission_group, "nickname" => nick
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
@ -84,14 +92,19 @@ def right_delete(
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

View file

@ -8,7 +8,7 @@ defmodule Pleroma.Web.CommonAPI do
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
@ -135,12 +135,13 @@ def post(user, %{"status" => status} = data) do
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

View file

@ -17,7 +17,15 @@ def init(args) do
end
def start_link() do
enabled = Pleroma.Config.get([:retry_queue, :enabled], false)
if enabled do
Logger.info("Starting retry queue")
GenServer.start_link(__MODULE__, %{delivered: 0, dropped: 0}, name: __MODULE__)
else
Logger.info("Retry queue disabled")
:ignore
end
end
def enqueue(data, transport, retries \\ 0) do

View file

@ -65,7 +65,7 @@ def build_signing_string(headers, used_headers) do
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))

View file

@ -32,67 +32,55 @@ def create_app(conn, params) do
end
end
defp add_if_present(
map,
params,
params_field,
map_field,
value_function \\ fn x -> {:ok, x} end
) do
if Map.has_key?(params, params_field) do
case value_function.(params[params_field]) do
{:ok, new_value} -> Map.put(map, map_field, new_value)
:error -> map
end
else
map
end
end
def update_credentials(%{assigns: %{user: user}} = conn, params) do
original_user = user
params =
if bio = params["note"] do
Map.put(params, "bio", bio)
user_params =
%{}
|> add_if_present(params, "display_name", :name)
|> add_if_present(params, "note", :bio, fn value -> {:ok, User.parse_bio(value)} end)
|> add_if_present(params, "avatar", :avatar, fn value ->
with %Plug.Upload{} <- value,
{:ok, object} <- ActivityPub.upload(value, type: :avatar) do
{:ok, object.data}
else
params
_ -> :error
end
end)
params =
if name = params["display_name"] do
Map.put(params, "name", name)
info_params =
%{}
|> add_if_present(params, "locked", :locked, fn value -> {:ok, value == "true"} end)
|> add_if_present(params, "header", :banner, fn value ->
with %Plug.Upload{} <- value,
{:ok, object} <- ActivityPub.upload(value, type: :banner) do
{:ok, object.data}
else
params
_ -> :error
end
end)
user =
if avatar = params["avatar"] do
with %Plug.Upload{} <- avatar,
{:ok, object} <- ActivityPub.upload(avatar, type: :avatar),
change = Ecto.Changeset.change(user, %{avatar: object.data}),
{:ok, user} = User.update_and_set_cache(change) do
user
else
_e -> user
end
else
user
end
info_cng = User.Info.mastodon_profile_update(user.info, info_params)
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),
with changeset <- User.update_changeset(user, user_params),
changeset <- Ecto.Changeset.put_embed(changeset, :info, info_cng),
{:ok, user} <- User.update_and_set_cache(changeset) do
if original_user != user do
CommonAPI.update(user)
@ -644,7 +632,7 @@ def unblock(%{assigns: %{user: blocker}} = conn, %{"id" => id}) 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)
@ -652,7 +640,7 @@ def blocks(%{assigns: %{user: user}} = conn, _) do
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
@ -900,11 +888,11 @@ def index(%{assigns: %{user: user}} = conn, _params) 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: %{
@ -924,7 +912,7 @@ def index(%{assigns: %{user: user}} = conn, _params) do
]
},
settings:
Map.get(user.info, "settings") ||
Map.get(user.info, :settings) ||
%{
onboarded: true,
home: %{
@ -1180,7 +1168,7 @@ def suggestions(%{assigns: %{user: user}} = conn, _) do
user = user.nickname
url = String.replace(api, "{{host}}", host) |> String.replace("{{user}}", user)
with {:ok, %{status_code: 200, body: body}} <-
with {:ok, %{status: 200, body: body}} <-
@httpoison.get(url, [], timeout: timeout, recv_timeout: timeout),
{:ok, data} <- Jason.decode(body) do
data2 =

View file

@ -14,10 +14,10 @@ def render("account.json", %{user: user} = opts) do
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} ->
%{
@ -29,7 +29,7 @@ def render("account.json", %{user: user} = opts) do
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)

View file

@ -5,12 +5,12 @@ defmodule Pleroma.Web.MediaProxy.MediaProxyController do
@default_proxy_opts [max_body_length: 25 * 1_048_576]
def remote(conn, params = %{"sig" => sig64, "url" => url64}) do
with config <- Pleroma.Config.get([:media_proxy]),
with config <- Pleroma.Config.get([:media_proxy], []),
true <- Keyword.get(config, :enabled, false),
{:ok, url} <- MediaProxy.decode_url(sig64, url64),
filename <- Path.basename(URI.parse(url).path),
:ok <- filename_matches(Map.has_key?(params, "filename"), conn.request_path, url) do
ReverseProxy.call(conn, url, Keyword.get(config, :proxy_opts, @default_proxy_length))
ReverseProxy.call(conn, url, Keyword.get(config, :proxy_opts, @default_proxy_opts))
else
false ->
send_resp(conn, 404, Plug.Conn.Status.reason_phrase(404))

View file

@ -226,25 +226,21 @@ def maybe_update_ostatus(doc, user) do
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}
@ -350,13 +346,15 @@ def get_atom_url(body) do
def fetch_activity_from_atom_url(url) do
with true <- String.starts_with?(url, "http"),
{:ok, %{body: body, status_code: code}} when code in 200..299 <-
{:ok, %{body: body, status: code}} when code in 200..299 <-
@httpoison.get(
url,
[Accept: "application/atom+xml"],
follow_redirect: true,
adapter: [
timeout: 10000,
recv_timeout: 20000
]
) do
Logger.debug("Got document from #{url}, handling...")
handle_incoming(body)

View file

@ -297,12 +297,6 @@ defmodule Pleroma.Web.Router do
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)

View file

@ -157,15 +157,17 @@ def remote_users(%{data: %{"to" => to} = data}) do
|> Enum.filter(fn user -> user && !user.local end)
end
defp send_to_user(%{info: %{"salmon" => salmon}}, feed, poster) do
with {:ok, %{status_code: code}} <-
defp send_to_user(%{info: %{salmon: salmon}}, feed, poster) do
with {:ok, %{status: code}} <-
poster.(
salmon,
feed,
[{"Content-Type", "application/magic-envelope+xml"}],
adapter: [
timeout: 10000,
recv_timeout: 20000,
hackney: [pool: :default]
pool: :default
]
) do
Logger.debug(fn -> "Pushed to #{salmon}, code #{code}" end)
else
@ -185,7 +187,7 @@ defp send_to_user(_, _, _), do: nil
]
def publish(user, activity, poster \\ &@httpoison.post/4)
def publish(%{info: %{"keys" => keys}} = user, %{data: %{"type" => type}} = activity, poster)
def publish(%{info: %{keys: keys}} = user, %{data: %{"type" => type}} = activity, poster)
when type in @supported_activities do
feed = ActivityRepresenter.to_simple_form(activity, user, true)

View file

@ -188,7 +188,7 @@ def push_to_socket(topics, topic, %Activity{data: %{"type" => "Announce"}} = ite
# 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"])
@ -206,7 +206,7 @@ def push_to_socket(topics, topic, item) do
# 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)})

View file

@ -132,7 +132,7 @@ def register_user(params) do
params = %{
nickname: params["nickname"],
name: params["fullname"],
bio: params["bio"],
bio: User.parse_bio(params["bio"]),
email: params["email"],
password: params["password"],
password_confirmation: params["confirm"]
@ -148,7 +148,7 @@ def register_user(params) do
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)
@ -279,14 +279,6 @@ def conversation_id_to_context(id) do
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 ->

View file

@ -300,9 +300,10 @@ def update_avatar(%{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),
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
new_info <- %{"banner" => object.data},
info_cng <- User.Info.profile_update(user.info, new_info),
changeset <- Ecto.Changeset.change(user) |> Ecto.Changeset.put_embed(:info, info_cng),
{:ok, user} <- User.update_and_set_cache(changeset) do
CommonAPI.update(user)
%{"url" => [%{"href" => href} | _]} = object.data
response = %{url: href} |> Jason.encode!()
@ -314,9 +315,10 @@ def update_banner(%{assigns: %{user: user}} = conn, params) do
def update_background(%{assigns: %{user: user}} = conn, params) do
with {:ok, object} <- ActivityPub.upload(params, type: :background),
new_info <- Map.put(user.info, "background", object.data),
change <- User.info_changeset(user, %{info: new_info}),
{:ok, _user} <- User.update_and_set_cache(change) do
new_info <- %{"background" => object.data},
info_cng <- User.Info.profile_update(user.info, new_info),
changeset <- Ecto.Changeset.change(user) |> Ecto.Changeset.put_embed(:info, info_cng),
{:ok, _user} <- User.update_and_set_cache(changeset) do
%{"url" => [%{"href" => href} | _]} = object.data
response = %{url: href} |> Jason.encode!()
@ -338,20 +340,6 @@ def external_profile(%{assigns: %{user: current_user}} = conn, %{"profileurl" =>
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
@ -439,67 +427,41 @@ def raw_empty_array(conn, _params) 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}
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
res
end
end)
bio_html = CommonUtils.format_input(bio, mentions, tags, "text/plain")
Map.put(params, "bio", bio_html |> Formatter.emojify(emoji))
info_params =
if value = params["default_scope"] do
Map.put(info_params, "default_scope", value)
else
info_params
end
User.Info.profile_update(user.info, info_params)
end
defp parse_profile_bio(user, params) do
if bio = params["description"] do
Map.put(params, "bio", User.parse_bio(bio, user))
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
else
_e -> user
end
else
user
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
else
user
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
def update_profile(%{assigns: %{user: user}} = conn, params) do
params = parse_profile_bio(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})

View file

@ -31,7 +31,7 @@ def render("user.json", %{user: user = %User{}} = assigns) do
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}
@ -40,7 +40,7 @@ def render("user.json", %{user: user = %User{}} = assigns) do
# ``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)
@ -66,17 +66,17 @@ def render("user.json", %{user: user = %User{}} = assigns) do
"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
}

View file

@ -45,7 +45,7 @@ def webfinger(resource, fmt) when fmt in ["XML", "JSON"] do
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)
%{
@ -83,7 +83,7 @@ def represent_user(user, "JSON") do
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)
{
@ -113,16 +113,22 @@ def represent_user(user, "XML") do
# 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
@ -214,7 +220,7 @@ def get_template_from_xml(body) do
end
def find_lrdd_template(domain) do
with {:ok, %{status_code: status_code, body: body}} when status_code in 200..299 <-
with {:ok, %{status: status, body: body}} when status in 200..299 <-
@httpoison.get("http://#{domain}/.well-known/host-meta", [], follow_redirect: true) do
get_template_from_xml(body)
else
@ -253,7 +259,7 @@ def finger(account) do
[Accept: "application/xrd+xml,application/jrd+json"],
follow_redirect: true
),
{:ok, %{status_code: status_code, body: body}} when status_code in 200..299 <- response do
{:ok, %{status: status, body: body}} when status in 200..299 <- response do
doc = XML.parse_document(body)
if doc != :error do

View file

@ -146,7 +146,7 @@ defp valid_topic(%{"hub.topic" => topic}, user) do
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) <-
@ -158,7 +158,7 @@ def subscribe(subscriber, subscribed, requester \\ &request_subscription/1) do
_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(),
@ -173,7 +173,7 @@ def subscribe(subscriber, subscribed, requester \\ &request_subscription/1) do
def gather_feed_data(topic, getter \\ &@httpoison.get/1) do
with {:ok, response} <- getter.(topic),
status_code when status_code in 200..299 <- response.status_code,
status when status in 200..299 <- response.status,
body <- response.body,
doc <- XML.parse_document(body),
uri when not is_nil(uri) <- XML.string_from_xpath("/feed/author[1]/uri", doc),
@ -221,7 +221,7 @@ def request_subscription(websub, poster \\ &@httpoison.post/3, timeout \\ 10_000
task = Task.async(websub_checker)
with {:ok, %{status_code: 202}} <-
with {:ok, %{status: 202}} <-
poster.(websub.hub, {:form, data}, "Content-type": "application/x-www-form-urlencoded"),
{:ok, websub} <- Task.yield(task, timeout) do
{:ok, websub}
@ -257,7 +257,7 @@ def publish_one(%{xml: xml, topic: topic, callback: callback, secret: secret}) d
signature = sign(secret || "", xml)
Logger.info(fn -> "Pushing #{topic} to #{callback}" end)
with {:ok, %{status_code: code}} <-
with {:ok, %{status: code}} <-
@httpoison.post(
callback,
xml,
@ -265,9 +265,11 @@ def publish_one(%{xml: xml, topic: topic, callback: callback, secret: secret}) d
{"Content-Type", "application/atom+xml"},
{"X-Hub-Signature", "sha1=#{signature}"}
],
adapter: [
timeout: 10000,
recv_timeout: 20000,
hackney: [pool: :default]
pool: :default
]
) do
Logger.info(fn -> "Pushed to #{callback}, code #{code}" end)
{:ok, code}

View file

@ -56,6 +56,7 @@ defp deps do
{:calendar, "~> 0.17.4"},
{:cachex, "~> 3.0.2"},
{:httpoison, "~> 1.2.0"},
{:tesla, "~> 1.2"},
{:jason, "~> 1.0"},
{:mogrify, "~> 0.6.1"},
{:ex_aws, "~> 2.0"},

View file

@ -17,6 +17,7 @@
"eternal": {:hex, :eternal, "1.2.0", "e2a6b6ce3b8c248f7dc31451aefca57e3bdf0e48d73ae5043229380a67614c41", [:mix], [], "hexpm"},
"ex_aws": {:hex, :ex_aws, "2.1.0", "b92651527d6c09c479f9013caa9c7331f19cba38a650590d82ebf2c6c16a1d8a", [:mix], [{:configparser_ex, "~> 2.0", [hex: :configparser_ex, repo: "hexpm", optional: true]}, {:hackney, "1.6.3 or 1.6.5 or 1.7.1 or 1.8.6 or ~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jsx, "~> 2.8", [hex: :jsx, repo: "hexpm", optional: true]}, {:poison, ">= 1.2.0", [hex: :poison, repo: "hexpm", optional: true]}, {:sweet_xml, "~> 0.6", [hex: :sweet_xml, repo: "hexpm", optional: true]}, {:xml_builder, "~> 0.1.0", [hex: :xml_builder, repo: "hexpm", optional: true]}], "hexpm"},
"ex_aws_s3": {:hex, :ex_aws_s3, "2.0.1", "9e09366e77f25d3d88c5393824e613344631be8db0d1839faca49686e99b6704", [:mix], [{:ex_aws, "~> 2.0", [hex: :ex_aws, repo: "hexpm", optional: false]}, {:sweet_xml, ">= 0.0.0", [hex: :sweet_xml, repo: "hexpm", optional: true]}], "hexpm"},
"ex_doc": {:hex, :ex_doc, "0.19.1", "519bb9c19526ca51d326c060cb1778d4a9056b190086a8c6c115828eaccea6cf", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.7", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"},
"ex_machina": {:hex, :ex_machina, "2.2.0", "fec496331e04fc2db2a1a24fe317c12c0c4a50d2beb8ebb3531ed1f0d84be0ed", [:mix], [{:ecto, "~> 2.1", [hex: :ecto, repo: "hexpm", optional: true]}], "hexpm"},
"gettext": {:hex, :gettext, "0.15.0", "40a2b8ce33a80ced7727e36768499fc9286881c43ebafccae6bab731e2b2b8ce", [:mix], [], "hexpm"},
"hackney": {:hex, :hackney, "1.13.0", "24edc8cd2b28e1c652593833862435c80661834f6c9344e84b6a2255e7aeef03", [:rebar3], [{:certifi, "2.3.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "5.1.2", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"},
@ -25,6 +26,7 @@
"idna": {:hex, :idna, "5.1.2", "e21cb58a09f0228a9e0b95eaa1217f1bcfc31a1aaa6e1fdf2f53a33f7dbd9494", [:rebar3], [{:unicode_util_compat, "0.3.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"},
"jason": {:hex, :jason, "1.0.0", "0f7cfa9bdb23fed721ec05419bcee2b2c21a77e926bce0deda029b5adc716fe2", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"},
"makeup": {:hex, :makeup, "0.5.5", "9e08dfc45280c5684d771ad58159f718a7b5788596099bdfb0284597d368a882", [:mix], [{:nimble_parsec, "~> 0.4", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm"},
"makeup_elixir": {:hex, :makeup_elixir, "0.10.0", "0f09c2ddf352887a956d84f8f7e702111122ca32fbbc84c2f0569b8b65cbf7fa", [:mix], [{:makeup, "~> 0.5.5", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm"},
"meck": {:hex, :meck, "0.8.9", "64c5c0bd8bcca3a180b44196265c8ed7594e16bcc845d0698ec6b4e577f48188", [:rebar3], [], "hexpm"},
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm"},
"mime": {:hex, :mime, "1.3.0", "5e8d45a39e95c650900d03f897fbf99ae04f60ab1daa4a34c7a20a5151b7a5fe", [:mix], [], "hexpm"},
@ -45,6 +47,7 @@
"postgrex": {:hex, :postgrex, "0.13.5", "3d931aba29363e1443da167a4b12f06dcd171103c424de15e5f3fc2ba3e6d9c5", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 1.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm"},
"ranch": {:hex, :ranch, "1.3.2", "e4965a144dc9fbe70e5c077c65e73c57165416a901bd02ea899cfd95aa890986", [:rebar3], [], "hexpm"},
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:make, :rebar], [], "hexpm"},
"tesla": {:hex, :tesla, "1.2.1", "864783cc27f71dd8c8969163704752476cec0f3a51eb3b06393b3971dc9733ff", [:mix], [{:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]}, {:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "~> 4.4.0", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}], "hexpm"},
"trailing_format_plug": {:hex, :trailing_format_plug, "0.0.7", "64b877f912cf7273bed03379936df39894149e35137ac9509117e59866e10e45", [:mix], [{:plug, "> 0.12.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
"tzdata": {:hex, :tzdata, "0.5.17", "50793e3d85af49736701da1a040c415c97dc1caf6464112fd9bd18f425d3053b", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"},
"unicode_util_compat": {:hex, :unicode_util_compat, "0.3.1", "a1f612a7b512638634a603c8f401892afbf99b8ce93a45041f8aaca99cadb85e", [:rebar3], [], "hexpm"},

View file

@ -0,0 +1,7 @@
defmodule Pleroma.Repo.Migrations.AddUUIDExtension do
use Ecto.Migration
def change do
execute("create extension if not exists \"uuid-ossp\"")
end
end

View file

@ -0,0 +1,7 @@
defmodule Pleroma.Repo.Migrations.AddUUIDsToUserInfo do
use Ecto.Migration
def change do
execute("update users set info = jsonb_set(info, '{\"id\"}', to_jsonb(uuid_generate_v4()))")
end
end

View file

@ -1 +1 @@
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><title>Pleroma</title><link rel=icon type=image/png href=/favicon.png><link rel=stylesheet href=/static/font/css/fontello.css><link rel=stylesheet href=/static/font/css/animation.css><link href=/static/css/app.0808aeafc6252b3050ea95b17dcaff1a.css rel=stylesheet></head><body style="display: none"><div id=app></div><script type=text/javascript src=/static/js/manifest.34667c2817916147413f.js></script><script type=text/javascript src=/static/js/vendor.32c621c7157f34c20923.js></script><script type=text/javascript src=/static/js/app.065638d22ade92dea420.js></script></body></html>
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><title>Pleroma</title><link rel=icon type=image/png href=/favicon.png><link rel=stylesheet href=/static/font/css/fontello.css><link rel=stylesheet href=/static/font/css/animation.css><link href=/static/css/app.0808aeafc6252b3050ea95b17dcaff1a.css rel=stylesheet></head><body style="display: none"><div id=app></div><script type=text/javascript src=/static/js/manifest.18df0da570d88ba76ec5.js></script><script type=text/javascript src=/static/js/vendor.0e895ca116d5ba12f2b6.js></script><script type=text/javascript src=/static/js/app.3f7c9aaedc6b87fa9653.js></script></body></html>

View file

@ -11,6 +11,8 @@
"scopeOptionsEnabled": false,
"formattingOptionsEnabled": false,
"collapseMessageWithSubject": false,
"scopeCopy": false,
"subjectLineBehavior": "email",
"hidePostStats": false,
"hideUserStats": false,
"loginMethod": "password"

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,2 @@
!function(e){function t(a){if(r[a])return r[a].exports;var n=r[a]={exports:{},id:a,loaded:!1};return e[a].call(n.exports,n,n.exports,t),n.loaded=!0,n.exports}var a=window.webpackJsonp;window.webpackJsonp=function(c,o){for(var p,l,s=0,i=[];s<c.length;s++)l=c[s],n[l]&&i.push.apply(i,n[l]),n[l]=0;for(p in o)Object.prototype.hasOwnProperty.call(o,p)&&(e[p]=o[p]);for(a&&a(c,o);i.length;)i.shift().call(null,t);if(o[0])return r[0]=0,t(0)};var r={},n={0:0};t.e=function(e,a){if(0===n[e])return a.call(null,t);if(void 0!==n[e])n[e].push(a);else{n[e]=[a];var r=document.getElementsByTagName("head")[0],c=document.createElement("script");c.type="text/javascript",c.charset="utf-8",c.async=!0,c.src=t.p+"static/js/"+e+"."+{1:"0e895ca116d5ba12f2b6",2:"3f7c9aaedc6b87fa9653"}[e]+".js",r.appendChild(c)}},t.m=e,t.c=r,t.p="/"}([]);
//# sourceMappingURL=manifest.18df0da570d88ba76ec5.js.map

View file

@ -1,2 +0,0 @@
!function(e){function t(r){if(n[r])return n[r].exports;var a=n[r]={exports:{},id:r,loaded:!1};return e[r].call(a.exports,a,a.exports,t),a.loaded=!0,a.exports}var r=window.webpackJsonp;window.webpackJsonp=function(c,o){for(var p,l,s=0,i=[];s<c.length;s++)l=c[s],a[l]&&i.push.apply(i,a[l]),a[l]=0;for(p in o)Object.prototype.hasOwnProperty.call(o,p)&&(e[p]=o[p]);for(r&&r(c,o);i.length;)i.shift().call(null,t);if(o[0])return n[0]=0,t(0)};var n={},a={0:0};t.e=function(e,r){if(0===a[e])return r.call(null,t);if(void 0!==a[e])a[e].push(r);else{a[e]=[r];var n=document.getElementsByTagName("head")[0],c=document.createElement("script");c.type="text/javascript",c.charset="utf-8",c.async=!0,c.src=t.p+"static/js/"+e+"."+{1:"32c621c7157f34c20923",2:"065638d22ade92dea420"}[e]+".js",n.appendChild(c)}},t.m=e,t.c=n,t.p="/"}([]);
//# sourceMappingURL=manifest.34667c2817916147413f.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0"><hm:Host xmlns:hm="http://host-meta.net/xrd/1.0">framatube.org</hm:Host><Link rel="lrdd" template="http://framatube.org/main/xrd?uri={uri}"><Title>Resource Descriptor</Title></Link></XRD>

View file

@ -0,0 +1,10 @@
<?xml version='1.0' encoding='UTF-8'?><XRD xmlns='http://docs.oasis-open.org/ns/xri/xrd-1.0'
xmlns:hm='http://host-meta.net/xrd/1.0'>
<hm:Host>gerzilla.de</hm:Host>
<Link rel='lrdd' type="application/xrd+xml" template='https://gerzilla.de/xrd/?uri={uri}' />
<Link rel="http://oexchange.org/spec/0.8/rel/resident-target" type="application/xrd+xml"
href="https://gerzilla.de/oexchange/xrd" />
</XRD>

View file

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0"><hm:Host xmlns:hm="http://host-meta.net/xrd/1.0">gnusocial.de</hm:Host><Link rel="lrdd" template="http://gnusocial.de/main/xrd?uri={uri}"><Title>Resource Descriptor</Title></Link></XRD>

View file

@ -5,6 +5,11 @@ defmodule Pleroma.FormatterTest do
import Pleroma.Factory
setup_all do
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
:ok
end
describe ".add_hashtag_links" do
test "turns hashtags into links" do
text = "I love #cofe and #2hu"
@ -110,7 +115,7 @@ test "gives a replacement for user links" do
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"})

55
test/http_test.exs Normal file
View file

@ -0,0 +1,55 @@
defmodule Pleroma.HTTPTest do
use Pleroma.DataCase
import Tesla.Mock
setup do
mock(fn
%{
method: :get,
url: "http://example.com/hello",
headers: [{"content-type", "application/json"}]
} ->
json(%{"my" => "data"})
%{method: :get, url: "http://example.com/hello"} ->
%Tesla.Env{status: 200, body: "hello"}
%{method: :post, url: "http://example.com/world"} ->
%Tesla.Env{status: 200, body: "world"}
end)
:ok
end
describe "get/1" do
test "returns successfully result" do
assert Pleroma.HTTP.get("http://example.com/hello") == {
:ok,
%Tesla.Env{status: 200, body: "hello"}
}
end
end
describe "get/2 (with headers)" do
test "returns successfully result for json content-type" do
assert Pleroma.HTTP.get("http://example.com/hello", [{"content-type", "application/json"}]) ==
{
:ok,
%Tesla.Env{
status: 200,
body: "{\"my\":\"data\"}",
headers: [{"content-type", "application/json"}]
}
}
end
end
describe "post/2" do
test "returns successfully result" do
assert Pleroma.HTTP.post("http://example.com/world", "") == {
:ok,
%Tesla.Env{status: 200, body: "world"}
}
end
end
end

View file

@ -13,7 +13,7 @@ test "doesn't do anything if the user isn't set", %{conn: conn} do
end
test "with a user that is deactivated, it removes that user", %{conn: conn} do
user = insert(:user, info: %{"deactivated" => true})
user = insert(:user, info: %{deactivated: true})
conn =
conn

View file

@ -5,7 +5,7 @@ defmodule Pleroma.Plugs.UserIsAdminPlugTest do
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()

View file

@ -7,7 +7,8 @@ def user_factory do
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: %{}
}
%{

View file

@ -0,0 +1,675 @@
defmodule HttpRequestMock do
require Logger
def request(
%Tesla.Env{
url: url,
method: method,
headers: headers,
query: query,
body: body
} = _env
) do
with {:ok, res} <- apply(__MODULE__, method, [url, query, body, headers]) do
res
else
{_, r} = error ->
# Logger.warn(r)
error
end
end
# GET Requests
#
def get(url, query \\ [], body \\ [], headers \\ [])
def get("https://osada.macgirvin.com/channel/mike", _, _, _) do
{:ok,
%Tesla.Env{
status: 200,
body:
File.read!("test/fixtures/httpoison_mock/https___osada.macgirvin.com_channel_mike.json")
}}
end
def get(
"https://osada.macgirvin.com/.well-known/webfinger?resource=acct:mike@osada.macgirvin.com",
_,
_,
Accept: "application/xrd+xml,application/jrd+json"
) do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/mike@osada.macgirvin.com.json")
}}
end
def get(
"https://social.heldscal.la/.well-known/webfinger?resource=https://social.heldscal.la/user/29191",
_,
_,
Accept: "application/xrd+xml,application/jrd+json"
) do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/https___social.heldscal.la_user_29191.xml")
}}
end
def get("https://pawoo.net/users/pekorino.atom", _, _, _) do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/https___pawoo.net_users_pekorino.atom")
}}
end
def get(
"https://pawoo.net/.well-known/webfinger?resource=acct:https://pawoo.net/users/pekorino",
_,
_,
Accept: "application/xrd+xml,application/jrd+json"
) do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/https___pawoo.net_users_pekorino.xml")
}}
end
def get(
"https://social.stopwatchingus-heidelberg.de/api/statuses/user_timeline/18330.atom",
_,
_,
_
) do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/atarifrosch_feed.xml")
}}
end
def get(
"https://social.stopwatchingus-heidelberg.de/.well-known/webfinger?resource=acct:https://social.stopwatchingus-heidelberg.de/user/18330",
_,
_,
Accept: "application/xrd+xml,application/jrd+json"
) do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/atarifrosch_webfinger.xml")
}}
end
def get("https://mamot.fr/users/Skruyb.atom", _, _, _) do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/https___mamot.fr_users_Skruyb.atom")
}}
end
def get(
"https://mamot.fr/.well-known/webfinger?resource=acct:https://mamot.fr/users/Skruyb",
_,
_,
Accept: "application/xrd+xml,application/jrd+json"
) do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/skruyb@mamot.fr.atom")
}}
end
def get(
"https://social.heldscal.la/.well-known/webfinger?resource=nonexistant@social.heldscal.la",
_,
_,
Accept: "application/xrd+xml,application/jrd+json"
) do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/nonexistant@social.heldscal.la.xml")
}}
end
def get("https://squeet.me/xrd/?uri=lain@squeet.me", _, _,
Accept: "application/xrd+xml,application/jrd+json"
) do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/lain_squeet.me_webfinger.xml")
}}
end
def get("https://mst3k.interlinked.me/users/luciferMysticus", _, _,
Accept: "application/activity+json"
) do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/lucifermysticus.json")
}}
end
def get("https://prismo.news/@mxb", _, _, _) do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/https___prismo.news__mxb.json")
}}
end
def get("https://hubzilla.example.org/channel/kaniini", _, _,
Accept: "application/activity+json"
) do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/kaniini@hubzilla.example.org.json")
}}
end
def get("https://niu.moe/users/rye", _, _, Accept: "application/activity+json") do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/rye.json")
}}
end
def get("http://mastodon.example.org/users/admin/statuses/100787282858396771", _, _, _) do
{:ok,
%Tesla.Env{
status: 200,
body:
File.read!(
"test/fixtures/httpoison_mock/http___mastodon.example.org_users_admin_status_1234.json"
)
}}
end
def get("https://puckipedia.com/", _, _, Accept: "application/activity+json") do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/puckipedia.com.json")
}}
end
def get("https://peertube.moe/accounts/7even", _, _, _) do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/7even.json")
}}
end
def get("https://peertube.moe/videos/watch/df5f464b-be8d-46fb-ad81-2d4c2d1630e3", _, _, _) do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/peertube.moe-vid.json")
}}
end
def get("https://baptiste.gelez.xyz/@/BaptisteGelez", _, _, _) do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/baptiste.gelex.xyz-user.json")
}}
end
def get("https://baptiste.gelez.xyz/~/PlumeDevelopment/this-month-in-plume-june-2018/", _, _, _) do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/baptiste.gelex.xyz-article.json")
}}
end
def get("http://mastodon.example.org/users/admin", _, _, Accept: "application/activity+json") do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/admin@mastdon.example.org.json")
}}
end
def get("http://mastodon.example.org/@admin/99541947525187367", _, _,
Accept: "application/activity+json"
) do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/mastodon-note-object.json")
}}
end
def get("https://shitposter.club/notice/7369654", _, _, _) do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/7369654.html")
}}
end
def get("https://mstdn.io/users/mayuutann", _, _, Accept: "application/activity+json") do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/mayumayu.json")
}}
end
def get("https://mstdn.io/users/mayuutann/statuses/99568293732299394", _, _,
Accept: "application/activity+json"
) do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/mayumayupost.json")
}}
end
def get("https://pleroma.soykaf.com/users/lain/feed.atom", _, _, _) do
{:ok,
%Tesla.Env{
status: 200,
body:
File.read!(
"test/fixtures/httpoison_mock/https___pleroma.soykaf.com_users_lain_feed.atom.xml"
)
}}
end
def get(url, _, _, Accept: "application/xrd+xml,application/jrd+json")
when url in [
"https://pleroma.soykaf.com/.well-known/webfinger?resource=acct:https://pleroma.soykaf.com/users/lain",
"https://pleroma.soykaf.com/.well-known/webfinger?resource=https://pleroma.soykaf.com/users/lain"
] do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/https___pleroma.soykaf.com_users_lain.xml")
}}
end
def get("https://shitposter.club/api/statuses/user_timeline/1.atom", _, _, _) do
{:ok,
%Tesla.Env{
status: 200,
body:
File.read!(
"test/fixtures/httpoison_mock/https___shitposter.club_api_statuses_user_timeline_1.atom.xml"
)
}}
end
def get(
"https://shitposter.club/.well-known/webfinger?resource=https://shitposter.club/user/1",
_,
_,
Accept: "application/xrd+xml,application/jrd+json"
) do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/https___shitposter.club_user_1.xml")
}}
end
def get("https://shitposter.club/notice/2827873", _, _, _) do
{:ok,
%Tesla.Env{
status: 200,
body:
File.read!("test/fixtures/httpoison_mock/https___shitposter.club_notice_2827873.html")
}}
end
def get("https://shitposter.club/api/statuses/show/2827873.atom", _, _, _) do
{:ok,
%Tesla.Env{
status: 200,
body:
File.read!(
"test/fixtures/httpoison_mock/https___shitposter.club_api_statuses_show_2827873.atom.xml"
)
}}
end
def get("https://testing.pleroma.lol/objects/b319022a-4946-44c5-9de9-34801f95507b", _, _, _) do
{:ok, %Tesla.Env{status: 200}}
end
def get("https://shitposter.club/api/statuses/user_timeline/5381.atom", _, _, _) do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/spc_5381.atom")
}}
end
def get(
"https://shitposter.club/.well-known/webfinger?resource=https://shitposter.club/user/5381",
_,
_,
Accept: "application/xrd+xml,application/jrd+json"
) do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/spc_5381_xrd.xml")
}}
end
def get("http://shitposter.club/.well-known/host-meta", _, _, _) do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/shitposter.club_host_meta")
}}
end
def get("https://shitposter.club/api/statuses/show/7369654.atom", _, _, _) do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/7369654.atom")
}}
end
def get("https://shitposter.club/notice/4027863", _, _, _) do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/7369654.html")
}}
end
def get("https://social.sakamoto.gq/users/eal/feed.atom", _, _, _) do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/sakamoto_eal_feed.atom")
}}
end
def get("http://social.sakamoto.gq/.well-known/host-meta", _, _, _) do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/social.sakamoto.gq_host_meta")
}}
end
def get(
"https://social.sakamoto.gq/.well-known/webfinger?resource=https://social.sakamoto.gq/users/eal",
_,
_,
Accept: "application/xrd+xml,application/jrd+json"
) do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/eal_sakamoto.xml")
}}
end
def get("https://social.sakamoto.gq/objects/0ccc1a2c-66b0-4305-b23a-7f7f2b040056", _, _,
Accept: "application/atom+xml"
) do
{:ok, %Tesla.Env{status: 200, body: File.read!("test/fixtures/httpoison_mock/sakamoto.atom")}}
end
def get("http://mastodon.social/.well-known/host-meta", _, _, _) do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/mastodon.social_host_meta")
}}
end
def get(
"https://mastodon.social/.well-known/webfinger?resource=https://mastodon.social/users/lambadalambda",
_,
_,
Accept: "application/xrd+xml,application/jrd+json"
) do
{:ok,
%Tesla.Env{
status: 200,
body:
File.read!(
"test/fixtures/httpoison_mock/https___mastodon.social_users_lambadalambda.xml"
)
}}
end
def get("http://gs.example.org/.well-known/host-meta", _, _, _) do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/gs.example.org_host_meta")
}}
end
def get(
"http://gs.example.org/.well-known/webfinger?resource=http://gs.example.org:4040/index.php/user/1",
_,
_,
Accept: "application/xrd+xml,application/jrd+json"
) do
{:ok,
%Tesla.Env{
status: 200,
body:
File.read!(
"test/fixtures/httpoison_mock/http___gs.example.org_4040_index.php_user_1.xml"
)
}}
end
def get("http://gs.example.org/index.php/api/statuses/user_timeline/1.atom", _, _, _) do
{:ok,
%Tesla.Env{
status: 200,
body:
File.read!(
"test/fixtures/httpoison_mock/http__gs.example.org_index.php_api_statuses_user_timeline_1.atom.xml"
)
}}
end
def get("https://social.heldscal.la/api/statuses/user_timeline/29191.atom", _, _, _) do
{:ok,
%Tesla.Env{
status: 200,
body:
File.read!(
"test/fixtures/httpoison_mock/https___social.heldscal.la_api_statuses_user_timeline_29191.atom.xml"
)
}}
end
def get("http://squeet.me/.well-known/host-meta", _, _, _) do
{:ok,
%Tesla.Env{status: 200, body: File.read!("test/fixtures/httpoison_mock/squeet.me_host_meta")}}
end
def get("https://squeet.me/xrd?uri=lain@squeet.me", _, _,
Accept: "application/xrd+xml,application/jrd+json"
) do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/lain_squeet.me_webfinger.xml")
}}
end
def get(
"https://social.heldscal.la/.well-known/webfinger?resource=shp@social.heldscal.la",
_,
_,
Accept: "application/xrd+xml,application/jrd+json"
) do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/shp@social.heldscal.la.xml")
}}
end
def get("http://framatube.org/.well-known/host-meta", _, _, _) do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/framatube.org_host_meta")
}}
end
def get("http://framatube.org/main/xrd?uri=framasoft@framatube.org", _, _,
Accept: "application/xrd+xml,application/jrd+json"
) do
{:ok,
%Tesla.Env{
status: 200,
headers: [{"content-type", "application/json"}],
body: File.read!("test/fixtures/httpoison_mock/framasoft@framatube.org.json")
}}
end
def get("http://gnusocial.de/.well-known/host-meta", _, _, _) do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/gnusocial.de_host_meta")
}}
end
def get("http://gnusocial.de/main/xrd?uri=winterdienst@gnusocial.de", _, _,
Accept: "application/xrd+xml,application/jrd+json"
) do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/winterdienst_webfinger.json")
}}
end
def get("http://status.alpicola.com/.well-known/host-meta", _, _, _) do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/status.alpicola.com_host_meta")
}}
end
def get("http://macgirvin.com/.well-known/host-meta", _, _, _) do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/macgirvin.com_host_meta")
}}
end
def get("http://gerzilla.de/.well-known/host-meta", _, _, _) do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/gerzilla.de_host_meta")
}}
end
def get("https://gerzilla.de/xrd/?uri=kaniini@gerzilla.de", _, _,
Accept: "application/xrd+xml,application/jrd+json"
) do
{:ok,
%Tesla.Env{
status: 200,
headers: [{"content-type", "application/json"}],
body: File.read!("test/fixtures/httpoison_mock/kaniini@gerzilla.de.json")
}}
end
def get("https://social.heldscal.la/api/statuses/user_timeline/23211.atom", _, _, _) do
{:ok,
%Tesla.Env{
status: 200,
body:
File.read!(
"test/fixtures/httpoison_mock/https___social.heldscal.la_api_statuses_user_timeline_23211.atom.xml"
)
}}
end
def get(
"https://social.heldscal.la/.well-known/webfinger?resource=https://social.heldscal.la/user/23211",
_,
_,
_
) do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/https___social.heldscal.la_user_23211.xml")
}}
end
def get("http://social.heldscal.la/.well-known/host-meta", _, _, _) do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/social.heldscal.la_host_meta")
}}
end
def get("https://social.heldscal.la/.well-known/host-meta", _, _, _) do
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/httpoison_mock/social.heldscal.la_host_meta")
}}
end
def get("https://mastodon.social/users/lambadalambda.atom", _, _, _) do
{:ok, %Tesla.Env{status: 200, body: File.read!("test/fixtures/lambadalambda.atom")}}
end
def get("https://social.heldscal.la/user/23211", _, _, Accept: "application/activity+json") do
{:ok, Tesla.Mock.json(%{"id" => "https://social.heldscal.la/user/23211"}, status: 200)}
end
def get(url, query, body, headers) do
{:error,
"Not implemented the mock response for get #{inspect(url)}, #{query}, #{inspect(body)}, #{
inspect(headers)
}"}
end
# POST Requests
#
def post(url, query \\ [], body \\ [], headers \\ [])
def post("http://example.org/needs_refresh", _, _, _) do
{:ok,
%Tesla.Env{
status: 200,
body: ""
}}
end
def post(url, _query, _body, _headers) do
{:error, "Not implemented the mock response for post #{inspect(url)}"}
end
end

View file

@ -1,883 +0,0 @@
defmodule HTTPoisonMock do
alias HTTPoison.Response
def process_request_options(options), do: options
def get(url, body \\ [], headers \\ [])
def get("https://prismo.news/@mxb", _, _) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/https___prismo.news__mxb.json")
}}
end
def get("https://osada.macgirvin.com/channel/mike", _, _) do
{:ok,
%Response{
status_code: 200,
body:
File.read!("test/fixtures/httpoison_mock/https___osada.macgirvin.com_channel_mike.json")
}}
end
def get(
"https://osada.macgirvin.com/.well-known/webfinger?resource=acct:mike@osada.macgirvin.com",
_,
_
) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/mike@osada.macgirvin.com.json")
}}
end
def get("https://info.pleroma.site/activity.json", _, _) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/https__info.pleroma.site_activity.json")
}}
end
def get("https://info.pleroma.site/activity2.json", _, _) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/https__info.pleroma.site_activity2.json")
}}
end
def get("https://info.pleroma.site/activity3.json", _, _) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/https__info.pleroma.site_activity3.json")
}}
end
def get("https://info.pleroma.site/activity4.json", _, _) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/https__info.pleroma.site_activity4.json")
}}
end
def get("https://info.pleroma.site/actor.json", _, _) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/https___info.pleroma.site_actor.json")
}}
end
def get("https://puckipedia.com/", [Accept: "application/activity+json"], _) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/puckipedia.com.json")
}}
end
def get(
"https://gerzilla.de/.well-known/webfinger?resource=acct:kaniini@gerzilla.de",
[Accept: "application/xrd+xml,application/jrd+json"],
follow_redirect: true
) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/kaniini@gerzilla.de.json")
}}
end
def get(
"https://framatube.org/.well-known/webfinger?resource=acct:framasoft@framatube.org",
[Accept: "application/xrd+xml,application/jrd+json"],
follow_redirect: true
) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/framasoft@framatube.org.json")
}}
end
def get(
"https://gnusocial.de/.well-known/webfinger?resource=acct:winterdienst@gnusocial.de",
[Accept: "application/xrd+xml,application/jrd+json"],
follow_redirect: true
) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/winterdienst_webfinger.json")
}}
end
def get(
"https://social.heldscal.la/.well-known/webfinger",
[Accept: "application/xrd+xml,application/jrd+json"],
params: [resource: "nonexistant@social.heldscal.la"],
follow_redirect: true
) do
{:ok,
%Response{
status_code: 500,
body: File.read!("test/fixtures/httpoison_mock/nonexistant@social.heldscal.la.xml")
}}
end
def get(
"https://social.heldscal.la/.well-known/webfinger?resource=shp@social.heldscal.la",
[Accept: "application/xrd+xml,application/jrd+json"],
follow_redirect: true
) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/shp@social.heldscal.la.xml")
}}
end
def get(
"https://social.heldscal.la/.well-known/webfinger",
[Accept: "application/xrd+xml,application/jrd+json"],
params: [resource: "shp@social.heldscal.la"],
follow_redirect: true
) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/shp@social.heldscal.la.xml")
}}
end
def get(
"https://social.heldscal.la/.well-known/webfinger",
[Accept: "application/xrd+xml,application/jrd+json"],
params: [resource: "https://social.heldscal.la/user/23211"],
follow_redirect: true
) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/https___social.heldscal.la_user_23211.xml")
}}
end
def get(
"https://social.heldscal.la/.well-known/webfinger?resource=https://social.heldscal.la/user/23211",
[Accept: "application/xrd+xml,application/jrd+json"],
follow_redirect: true
) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/https___social.heldscal.la_user_23211.xml")
}}
end
def get(
"https://social.heldscal.la/.well-known/webfinger",
[Accept: "application/xrd+xml,application/jrd+json"],
params: [resource: "https://social.heldscal.la/user/29191"],
follow_redirect: true
) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/https___social.heldscal.la_user_29191.xml")
}}
end
def get(
"https://social.heldscal.la/.well-known/webfinger?resource=https://social.heldscal.la/user/29191",
[Accept: "application/xrd+xml,application/jrd+json"],
follow_redirect: true
) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/https___social.heldscal.la_user_29191.xml")
}}
end
def get(
"https://mastodon.social/.well-known/webfinger",
[Accept: "application/xrd+xml,application/jrd+json"],
params: [resource: "https://mastodon.social/users/lambadalambda"],
follow_redirect: true
) do
{:ok,
%Response{
status_code: 200,
body:
File.read!(
"test/fixtures/httpoison_mock/https___mastodon.social_users_lambadalambda.xml"
)
}}
end
def get(
"https://mastodon.social/.well-known/webfinger?resource=https://mastodon.social/users/lambadalambda",
[Accept: "application/xrd+xml,application/jrd+json"],
follow_redirect: true
) do
{:ok,
%Response{
status_code: 200,
body:
File.read!(
"test/fixtures/httpoison_mock/https___mastodon.social_users_lambadalambda.xml"
)
}}
end
def get(
"https://shitposter.club/.well-known/webfinger",
[Accept: "application/xrd+xml,application/jrd+json"],
params: [resource: "https://shitposter.club/user/1"],
follow_redirect: true
) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/https___shitposter.club_user_1.xml")
}}
end
def get(
"https://shitposter.club/.well-known/webfinger?resource=https://shitposter.club/user/1",
[Accept: "application/xrd+xml,application/jrd+json"],
follow_redirect: true
) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/https___shitposter.club_user_1.xml")
}}
end
def get(
"https://shitposter.club/.well-known/webfinger?resource=https://shitposter.club/user/5381",
[Accept: "application/xrd+xml,application/jrd+json"],
follow_redirect: true
) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/spc_5381_xrd.xml")
}}
end
def get(
"http://gs.example.org/.well-known/webfinger",
[Accept: "application/xrd+xml,application/jrd+json"],
params: [resource: "http://gs.example.org:4040/index.php/user/1"],
follow_redirect: true
) do
{:ok,
%Response{
status_code: 200,
body:
File.read!(
"test/fixtures/httpoison_mock/http___gs.example.org_4040_index.php_user_1.xml"
)
}}
end
def get(
"http://gs.example.org/.well-known/webfinger?resource=http://gs.example.org:4040/index.php/user/1",
[Accept: "application/xrd+xml,application/jrd+json"],
follow_redirect: true
) do
{:ok,
%Response{
status_code: 200,
body:
File.read!(
"test/fixtures/httpoison_mock/http___gs.example.org_4040_index.php_user_1.xml"
)
}}
end
def get(
"https://social.stopwatchingus-heidelberg.de/.well-known/webfinger?resource=https://social.stopwatchingus-heidelberg.de/user/18330",
[Accept: "application/xrd+xml,application/jrd+json"],
follow_redirect: true
) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/atarifrosch_webfinger.xml")
}}
end
def get(
"https://pleroma.soykaf.com/.well-known/webfinger",
[Accept: "application/xrd+xml,application/jrd+json"],
params: [resource: "https://pleroma.soykaf.com/users/lain"],
follow_redirect: true
) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/https___pleroma.soykaf.com_users_lain.xml")
}}
end
def get(
"https://pleroma.soykaf.com/.well-known/webfinger?resource=https://pleroma.soykaf.com/users/lain",
[Accept: "application/xrd+xml,application/jrd+json"],
follow_redirect: true
) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/https___pleroma.soykaf.com_users_lain.xml")
}}
end
def get("https://social.heldscal.la/api/statuses/user_timeline/29191.atom", _body, _headers) do
{:ok,
%Response{
status_code: 200,
body:
File.read!(
"test/fixtures/httpoison_mock/https___social.heldscal.la_api_statuses_user_timeline_29191.atom.xml"
)
}}
end
def get("https://shitposter.club/api/statuses/user_timeline/5381.atom", _body, _headers) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/spc_5381.atom")
}}
end
def get("https://social.heldscal.la/api/statuses/user_timeline/23211.atom", _body, _headers) do
{:ok,
%Response{
status_code: 200,
body:
File.read!(
"test/fixtures/httpoison_mock/https___social.heldscal.la_api_statuses_user_timeline_23211.atom.xml"
)
}}
end
def get("https://mastodon.social/users/lambadalambda.atom", _body, _headers) do
{:ok,
%Response{
status_code: 200,
body:
File.read!(
"test/fixtures/httpoison_mock/https___mastodon.social_users_lambadalambda.atom"
)
}}
end
def get(
"https://social.stopwatchingus-heidelberg.de/api/statuses/user_timeline/18330.atom",
_body,
_headers
) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/atarifrosch_feed.xml")
}}
end
def get("https://pleroma.soykaf.com/users/lain/feed.atom", _body, _headers) do
{:ok,
%Response{
status_code: 200,
body:
File.read!(
"test/fixtures/httpoison_mock/https___pleroma.soykaf.com_users_lain_feed.atom.xml"
)
}}
end
def get("https://social.sakamoto.gq/users/eal/feed.atom", _body, _headers) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/sakamoto_eal_feed.atom")
}}
end
def get("http://gs.example.org/index.php/api/statuses/user_timeline/1.atom", _body, _headers) do
{:ok,
%Response{
status_code: 200,
body:
File.read!(
"test/fixtures/httpoison_mock/http__gs.example.org_index.php_api_statuses_user_timeline_1.atom.xml"
)
}}
end
def get("https://shitposter.club/notice/2827873", _body, _headers) do
{:ok,
%Response{
status_code: 200,
body:
File.read!("test/fixtures/httpoison_mock/https___shitposter.club_notice_2827873.html")
}}
end
def get("https://shitposter.club/api/statuses/show/2827873.atom", _body, _headers) do
{:ok,
%Response{
status_code: 200,
body:
File.read!(
"test/fixtures/httpoison_mock/https___shitposter.club_api_statuses_show_2827873.atom.xml"
)
}}
end
def get("https://shitposter.club/api/statuses/user_timeline/1.atom", _body, _headers) do
{:ok,
%Response{
status_code: 200,
body:
File.read!(
"test/fixtures/httpoison_mock/https___shitposter.club_api_statuses_user_timeline_1.atom.xml"
)
}}
end
def post(
"https://social.heldscal.la/main/push/hub",
{:form, _data},
"Content-type": "application/x-www-form-urlencoded"
) do
{:ok,
%Response{
status_code: 202
}}
end
def get("http://mastodon.example.org/users/admin/statuses/100787282858396771", _, _) do
{:ok,
%Response{
status_code: 200,
body:
File.read!(
"test/fixtures/httpoison_mock/http___mastodon.example.org_users_admin_status_1234.json"
)
}}
end
def get(
"https://pawoo.net/.well-known/webfinger",
[Accept: "application/xrd+xml,application/jrd+json"],
params: [resource: "https://pawoo.net/users/pekorino"],
follow_redirect: true
) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/https___pawoo.net_users_pekorino.xml")
}}
end
def get(
"https://pawoo.net/.well-known/webfinger?resource=https://pawoo.net/users/pekorino",
[Accept: "application/xrd+xml,application/jrd+json"],
follow_redirect: true
) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/https___pawoo.net_users_pekorino.xml")
}}
end
def get("https://pawoo.net/users/pekorino.atom", _, _) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/https___pawoo.net_users_pekorino.atom")
}}
end
def get(
"https://mamot.fr/.well-known/webfinger",
[Accept: "application/xrd+xml,application/jrd+json"],
params: [resource: "https://mamot.fr/users/Skruyb"],
follow_redirect: true
) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/skruyb@mamot.fr.atom")
}}
end
def get(
"https://mamot.fr/.well-known/webfinger?resource=https://mamot.fr/users/Skruyb",
[Accept: "application/xrd+xml,application/jrd+json"],
follow_redirect: true
) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/skruyb@mamot.fr.atom")
}}
end
def get(
"https://social.sakamoto.gq/.well-known/webfinger",
[Accept: "application/xrd+xml,application/jrd+json"],
params: [resource: "https://social.sakamoto.gq/users/eal"],
follow_redirect: true
) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/eal_sakamoto.xml")
}}
end
def get(
"https://social.sakamoto.gq/.well-known/webfinger?resource=https://social.sakamoto.gq/users/eal",
[Accept: "application/xrd+xml,application/jrd+json"],
follow_redirect: true
) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/eal_sakamoto.xml")
}}
end
def get(
"https://pleroma.soykaf.com/.well-known/webfinger?resource=https://pleroma.soykaf.com/users/shp",
[Accept: "application/xrd+xml,application/jrd+json"],
follow_redirect: true
) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/shp@pleroma.soykaf.com.webfigner")
}}
end
def get(
"https://squeet.me/xrd/?uri=lain@squeet.me",
[Accept: "application/xrd+xml,application/jrd+json"],
follow_redirect: true
) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/lain_squeet.me_webfinger.xml")
}}
end
def get("https://mamot.fr/users/Skruyb.atom", _, _) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/https___mamot.fr_users_Skruyb.atom")
}}
end
def get(
"https://social.sakamoto.gq/objects/0ccc1a2c-66b0-4305-b23a-7f7f2b040056",
[Accept: "application/atom+xml"],
_
) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/sakamoto.atom")
}}
end
def get("https://pleroma.soykaf.com/users/shp/feed.atom", _, _) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/shp@pleroma.soykaf.com.feed")
}}
end
def get("http://social.heldscal.la/.well-known/host-meta", [], follow_redirect: true) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/social.heldscal.la_host_meta")
}}
end
def get("http://status.alpicola.com/.well-known/host-meta", [], follow_redirect: true) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/status.alpicola.com_host_meta")
}}
end
def get("http://macgirvin.com/.well-known/host-meta", [], follow_redirect: true) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/macgirvin.com_host_meta")
}}
end
def get("http://mastodon.social/.well-known/host-meta", [], follow_redirect: true) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/mastodon.social_host_meta")
}}
end
def get("http://shitposter.club/.well-known/host-meta", [], follow_redirect: true) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/shitposter.club_host_meta")
}}
end
def get("http://pleroma.soykaf.com/.well-known/host-meta", [], follow_redirect: true) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/pleroma.soykaf.com_host_meta")
}}
end
def get("http://social.sakamoto.gq/.well-known/host-meta", [], follow_redirect: true) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/social.sakamoto.gq_host_meta")
}}
end
def get("http://gs.example.org/.well-known/host-meta", [], follow_redirect: true) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/gs.example.org_host_meta")
}}
end
def get("http://pawoo.net/.well-known/host-meta", [], follow_redirect: true) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/pawoo.net_host_meta")
}}
end
def get("http://mamot.fr/.well-known/host-meta", [], follow_redirect: true) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/mamot.fr_host_meta")
}}
end
def get("http://mastodon.xyz/.well-known/host-meta", [], follow_redirect: true) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/mastodon.xyz_host_meta")
}}
end
def get("http://social.wxcafe.net/.well-known/host-meta", [], follow_redirect: true) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/social.wxcafe.net_host_meta")
}}
end
def get("http://squeet.me/.well-known/host-meta", [], follow_redirect: true) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/squeet.me_host_meta")
}}
end
def get(
"http://social.stopwatchingus-heidelberg.de/.well-known/host-meta",
[],
follow_redirect: true
) do
{:ok,
%Response{
status_code: 200,
body:
File.read!("test/fixtures/httpoison_mock/social.stopwatchingus-heidelberg.de_host_meta")
}}
end
def get("http://mastodon.example.org/users/admin", [Accept: "application/activity+json"], _) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/admin@mastdon.example.org.json")
}}
end
def get(
"https://hubzilla.example.org/channel/kaniini",
[Accept: "application/activity+json"],
_
) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/kaniini@hubzilla.example.org.json")
}}
end
def get("https://masto.quad.moe/users/_HellPie", [Accept: "application/activity+json"], _) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/hellpie.json")
}}
end
def get("https://niu.moe/users/rye", [Accept: "application/activity+json"], _) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/rye.json")
}}
end
def get("https://n1u.moe/users/rye", [Accept: "application/activity+json"], _) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/rye.json")
}}
end
def get(
"https://mst3k.interlinked.me/users/luciferMysticus",
[Accept: "application/activity+json"],
_
) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/lucifermysticus.json")
}}
end
def get("https://mstdn.io/users/mayuutann", [Accept: "application/activity+json"], _) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/mayumayu.json")
}}
end
def get(
"http://mastodon.example.org/@admin/99541947525187367",
[Accept: "application/activity+json"],
_
) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/mastodon-note-object.json")
}}
end
def get(
"https://mstdn.io/users/mayuutann/statuses/99568293732299394",
[Accept: "application/activity+json"],
_
) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/mayumayupost.json")
}}
end
def get("https://shitposter.club/notice/7369654", _, _) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/7369654.html")
}}
end
def get("https://shitposter.club/api/statuses/show/7369654.atom", _body, _headers) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/7369654.atom")
}}
end
def get("https://baptiste.gelez.xyz/~/PlumeDevelopment/this-month-in-plume-june-2018/", _, _) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/baptiste.gelex.xyz-article.json")
}}
end
def get("https://baptiste.gelez.xyz/@/BaptisteGelez", _, _) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/baptiste.gelex.xyz-user.json")
}}
end
def get("https://peertube.moe/videos/watch/df5f464b-be8d-46fb-ad81-2d4c2d1630e3", _, _) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/peertube.moe-vid.json")
}}
end
def get("https://peertube.moe/accounts/7even", _, _) do
{:ok,
%Response{
status_code: 200,
body: File.read!("test/fixtures/httpoison_mock/7even.json")
}}
end
def get(url, body, headers) do
{:error,
"Not implemented the mock response for get #{inspect(url)}, #{inspect(body)}, #{
inspect(headers)
}"}
end
def post(url, _body, _headers) do
{:error, "Not implemented the mock response for post #{inspect(url)}"}
end
def post(url, _body, _headers, _options) do
{:error, "Not implemented the mock response for post #{inspect(url)}"}
end
end

View file

@ -9,6 +9,11 @@ defmodule Pleroma.UserTest do
import Pleroma.Factory
import Ecto.Query
setup_all do
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
:ok
end
test "ap_id returns the activity pub id for the user" do
user = UserBuilder.build()
@ -34,14 +39,14 @@ test "follow takes a user and another user" do
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
@ -56,8 +61,8 @@ test "can't follow a user who blocked us" do
end
test "local users do not automatically follow local locked accounts" do
follower = insert(:user, info: %{"locked" => true})
followed = insert(:user, info: %{"locked" => true})
follower = insert(:user, info: %{locked: true})
followed = insert(:user, info: %{locked: true})
{:ok, follower} = User.maybe_direct_follow(follower, followed)
@ -144,6 +149,18 @@ test "it sets the password_hash, ap_id and following fields" do
assert changeset.changes.follower_address == "#{changeset.changes.ap_id}/followers"
end
test "it ensures info is not nil" do
changeset = User.register_changeset(%User{}, @full_user_data)
assert changeset.valid?
{:ok, user} =
changeset
|> Repo.insert()
refute is_nil(user.info)
end
end
describe "fetching a user from nickname or trying to build one" do
@ -185,12 +202,14 @@ test "updates an existing user, if stale" do
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
@ -311,45 +330,45 @@ test "it sets the info->note_count property" do
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
@ -358,11 +377,11 @@ 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
@ -489,11 +508,11 @@ test "get recipients from activity" do
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
@ -517,7 +536,7 @@ test ".delete deactivates a user, all follow relationships and all create activi
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)
@ -546,7 +565,7 @@ test "html_filter_policy returns nil when rich-text is enabled" do
end
test "html_filter_policy returns TwitterText scrubber when rich-text is disabled" do
user = insert(:user, %{info: %{"no_rich_text" => true}})
user = insert(:user, %{info: %{no_rich_text: true}})
assert Pleroma.HTML.Scrubber.TwitterText == User.html_filter_policy(user)
end

View file

@ -5,6 +5,11 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
alias Pleroma.{Repo, User}
alias Pleroma.Activity
setup_all do
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
:ok
end
describe "/relay" do
test "with the relay active, it returns the relay user", %{conn: conn} do
res =

View file

@ -7,6 +7,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
alias Pleroma.Builders.ActivityBuilder
import Pleroma.Factory
import Tesla.Mock
setup do
mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
:ok
end
describe "building a user from his ap id" do
test "it returns a user" do
@ -14,8 +20,8 @@ test "it returns a user" do
{:ok, user} = ActivityPub.make_user_from_ap_id(user_id)
assert user.ap_id == user_id
assert user.nickname == "admin@mastodon.example.org"
assert user.info["source_data"]
assert user.info["ap_enabled"]
assert user.info.source_data
assert user.info.ap_enabled
assert user.follower_address == "http://mastodon.example.org/users/admin/followers"
end
end

View file

@ -12,6 +12,11 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
import Pleroma.Factory
alias Pleroma.Web.CommonAPI
setup_all do
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
:ok
end
describe "handle_incoming" do
test "it ignores an incoming notice if we already have it" do
activity = insert(:note_activity)
@ -92,7 +97,7 @@ test "it works for incoming notices" do
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
@ -307,7 +312,7 @@ test "it works for incoming update activities" do
}
]
assert user.info["banner"]["url"] == [
assert user.info.banner["url"] == [
%{
"href" =>
"https://cd.niu.moe/accounts/headers/000/033/323/original/850b3448fa5fd477.png"
@ -337,7 +342,7 @@ test "it works for incoming update activities which lock the account" do
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(update_data)
user = User.get_cached_by_ap_id(data["actor"])
assert user.info["locked"] == true
assert user.info.locked == true
end
test "it works for incoming deletes" do
@ -543,7 +548,7 @@ test "it works for incoming accepts which were pre-accepted" do
test "it works for incoming accepts which were orphaned" do
follower = insert(:user)
followed = insert(:user, %{info: %{"locked" => true}})
followed = insert(:user, %{info: %User.Info{locked: true}})
{:ok, follow_activity} = ActivityPub.follow(follower, followed)
@ -565,7 +570,7 @@ test "it works for incoming accepts which were orphaned" do
test "it works for incoming accepts which are referenced by IRI only" do
follower = insert(:user)
followed = insert(:user, %{info: %{"locked" => true}})
followed = insert(:user, %{info: %User.Info{locked: true}})
{:ok, follow_activity} = ActivityPub.follow(follower, followed)
@ -585,7 +590,7 @@ test "it works for incoming accepts which are referenced by IRI only" do
test "it fails for incoming accepts which cannot be correlated" do
follower = insert(:user)
followed = insert(:user, %{info: %{"locked" => true}})
followed = insert(:user, %{info: %User.Info{locked: true}})
accept_data =
File.read!("test/fixtures/mastodon-accept-activity.json")
@ -604,7 +609,7 @@ test "it fails for incoming accepts which cannot be correlated" do
test "it fails for incoming rejects which cannot be correlated" do
follower = insert(:user)
followed = insert(:user, %{info: %{"locked" => true}})
followed = insert(:user, %{info: %User.Info{locked: true}})
accept_data =
File.read!("test/fixtures/mastodon-reject-activity.json")
@ -623,7 +628,7 @@ test "it fails for incoming rejects which cannot be correlated" do
test "it works for incoming rejects which are orphaned" do
follower = insert(:user)
followed = insert(:user, %{info: %{"locked" => true}})
followed = insert(:user, %{info: %User.Info{locked: true}})
{:ok, follower} = User.follow(follower, followed)
{:ok, _follow_activity} = ActivityPub.follow(follower, followed)
@ -648,7 +653,7 @@ test "it works for incoming rejects which are orphaned" do
test "it works for incoming rejects which are referenced by IRI only" do
follower = insert(:user)
followed = insert(:user, %{info: %{"locked" => true}})
followed = insert(:user, %{info: %User.Info{locked: true}})
{:ok, follower} = User.follow(follower, followed)
{:ok, follow_activity} = ActivityPub.follow(follower, followed)
@ -815,18 +820,18 @@ test "it upgrades a user to activitypub" do
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
@ -847,7 +852,7 @@ test "it upgrades a user to activitypub" do
"https://cdn.niu.moe/accounts/headers/000/033/323/original/850b3448fa5fd477.png"
}
]
} = user.info["banner"]
} = user.info.banner
refute "..." in activity.recipients

View file

@ -8,7 +8,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
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 =
@ -21,7 +21,7 @@ test "Delete" do
end
test "Create" do
admin = insert(:user, info: %{"is_admin" => true})
admin = insert(:user, info: %{is_admin: true})
conn =
build_conn()
@ -39,7 +39,7 @@ test "Create" do
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()
@ -47,33 +47,30 @@ test "GET is giving user_info" do
|> 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()
@ -81,12 +78,14 @@ test "/:right DELETE, can remove from a permission group" do
|> 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()
@ -98,8 +97,8 @@ test "/api/pleroma/admin/invite_token" do
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()

View file

@ -17,7 +17,7 @@ test "it adds emoji when updating profiles" do
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

View file

@ -5,6 +5,11 @@ defmodule Pleroma.Web.FederatorTest do
import Pleroma.Factory
import Mock
setup_all do
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
:ok
end
test "enqueues an element according to priority" do
queue = [%{item: 1, priority: 2}]

View file

@ -4,6 +4,12 @@ defmodule Pleroma.Web.HTTPSignaturesTest do
use Pleroma.DataCase
alias Pleroma.Web.HTTPSignatures
import Pleroma.Factory
import Tesla.Mock
setup do
mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
:ok
end
@private_key hd(:public_key.pem_decode(File.read!("test/web/http_sigs/priv.key")))
|> :public_key.pem_entry_decode()

View file

@ -17,7 +17,7 @@ test "Represent a user account" do
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>",
@ -63,7 +63,7 @@ test "Represent a user account" do
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]
})

View file

@ -8,6 +8,12 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
import Pleroma.Factory
import ExUnit.CaptureLog
import Tesla.Mock
setup do
mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
:ok
end
test "the home timeline", %{conn: conn} do
user = insert(:user)
@ -252,7 +258,7 @@ test "verify_credentials", %{conn: conn} do
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
@ -845,7 +851,7 @@ test "returns the relationships for the current user", %{conn: conn} do
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)
@ -865,7 +871,7 @@ test "/api/v1/follow_requests works" do
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)
@ -890,7 +896,7 @@ test "/api/v1/follow_requests/:id/authorize works" do
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
@ -902,7 +908,7 @@ test "verify_credentials", %{conn: conn} do
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)
@ -1105,7 +1111,7 @@ test "blocking / unblocking a domain", %{conn: conn} do
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")
@ -1253,14 +1259,33 @@ test "returns the favorites of a user", %{conn: conn} do
describe "updating credentials" do
test "updates the user's bio", %{conn: conn} do
user = insert(:user)
user2 = insert(:user)
conn =
conn
|> assign(:user, user)
|> patch("/api/v1/accounts/update_credentials", %{"note" => "I drink #cofe"})
|> patch("/api/v1/accounts/update_credentials", %{
"note" => "I drink #cofe with @#{user2.nickname}"
})
assert user = json_response(conn, 200)
assert user["note"] == "I drink #cofe"
assert user["note"] ==
"I drink <a href=\"http://localhost:4001/tag/cofe\">#cofe</a> with <span><a href=\"#{
user2.ap_id
}\">@<span>#{user2.nickname}</span></a></span>"
end
test "updates the user's locking status", %{conn: conn} do
user = insert(:user)
conn =
conn
|> assign(:user, user)
|> patch("/api/v1/accounts/update_credentials", %{locked: "true"})
assert user = json_response(conn, 200)
assert user["locked"] == true
end
test "updates the user's name", %{conn: conn} do
@ -1289,8 +1314,8 @@ test "updates the user's avatar", %{conn: conn} do
|> assign(:user, user)
|> patch("/api/v1/accounts/update_credentials", %{"avatar" => new_avatar})
assert user = json_response(conn, 200)
assert user["avatar"] != "https://placehold.it/48x48"
assert user_response = json_response(conn, 200)
assert user_response["avatar"] != User.avatar_url(user)
end
test "updates the user's banner", %{conn: conn} do
@ -1307,8 +1332,8 @@ test "updates the user's banner", %{conn: conn} do
|> assign(:user, user)
|> patch("/api/v1/accounts/update_credentials", %{"header" => new_header})
assert user = json_response(conn, 200)
assert user["header"] != "https://placehold.it/700x335"
assert user_response = json_response(conn, 200)
assert user_response["header"] != User.banner_url(user)
end
end

View file

@ -6,6 +6,12 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
alias Pleroma.Web.OStatus
alias Pleroma.Web.CommonAPI
import Pleroma.Factory
import Tesla.Mock
setup do
mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
:ok
end
test "a note with null content" do
note = insert(:note_activity)

View file

@ -4,7 +4,7 @@ defmodule Pleroma.Web.NodeInfoTest do
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
@ -15,7 +15,7 @@ test "nodeinfo shows staff accounts", %{conn: conn} do
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)
@ -37,7 +37,7 @@ test "returns 404 when federation is disabled" do
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)

View file

@ -7,6 +7,12 @@ defmodule Pleroma.Web.OStatus.ActivityRepresenterTest do
alias Pleroma.Web.OStatus
import Pleroma.Factory
import Tesla.Mock
setup do
mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
:ok
end
test "an external note activity" do
incoming = File.read!("test/fixtures/mastodon-note-cw.xml")

View file

@ -5,6 +5,11 @@ defmodule Pleroma.Web.OStatus.OStatusControllerTest do
alias Pleroma.Web.CommonAPI
alias Pleroma.Web.OStatus.ActivityRepresenter
setup_all do
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
:ok
end
test "decodes a salmon", %{conn: conn} do
user = insert(:user)
salmon = File.read!("test/fixtures/salmon.xml")
@ -31,14 +36,16 @@ test "decodes a salmon with a changed magic key", %{conn: conn} do
# 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",
info_cng =
User.Info.remote_user_creation(salmon_user.info, %{
magic_key:
"RSA.pu0s-halox4tu7wmES1FVSx6u-4wc0YrUFXcqWXZG4-27UmbCOpMQftRCldNRfyA-qLbz-eqiwrong1EwUvjsD4cYbAHNGHwTvDOyx5AKthQUP44ykPv7kjKGh3DWKySJvcs9tlUG87hlo7AvnMo9pwRS_Zz2CacQ-MKaXyDepk=.AQAB"
)
})
Repo.update(User.info_changeset(salmon_user, %{info: info}))
cng =
Ecto.Changeset.change(salmon_user)
|> Ecto.Changeset.put_embed(:info, info_cng)
|> Repo.update()
conn =
build_conn()

View file

@ -6,6 +6,11 @@ defmodule Pleroma.Web.OStatusTest do
import Pleroma.Factory
import ExUnit.CaptureLog
setup_all do
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
:ok
end
test "don't insert create notes twice" do
incoming = File.read!("test/fixtures/incoming_note_activity.xml")
{:ok, [activity]} = OStatus.handle_incoming(incoming)
@ -17,7 +22,7 @@ test "handle incoming note - GS, Salmon" do
{: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"
@ -319,7 +324,7 @@ test "tries to use the information in poco fields" do
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"
@ -329,6 +334,38 @@ test "tries to use the information in poco fields" do
assert user == user_again
end
test "find_or_make_user sets all the nessary input fields" do
uri = "https://social.heldscal.la/user/23211"
{:ok, user} = OStatus.find_or_make_user(uri)
assert user.info ==
%Pleroma.User.Info{
id: user.info.id,
ap_enabled: false,
background: %{},
banner: %{},
blocks: [],
deactivated: false,
default_scope: "public",
domain_blocks: [],
follower_count: 0,
is_admin: false,
is_moderator: false,
keys: nil,
locked: false,
no_rich_text: false,
note_count: 0,
settings: nil,
source_data: %{},
hub: "https://social.heldscal.la/main/push/hub",
magic_key:
"RSA.uzg6r1peZU0vXGADWxGJ0PE34WvmhjUmydbX5YYdOiXfODVLwCMi1umGoqUDm-mRu4vNEdFBVJU1CpFA7dKzWgIsqsa501i2XqElmEveXRLvNRWFB6nG03Q5OUY2as8eE54BJm0p20GkMfIJGwP6TSFb-ICp3QjzbatuSPJ6xCE=.AQAB",
salmon: "https://social.heldscal.la/main/salmon/user/23211",
topic: "https://social.heldscal.la/api/statuses/user_timeline/23211.atom",
uri: "https://social.heldscal.la/user/23211"
}
end
test "find_make_or_update_user takes an author element and returns an updated user" do
uri = "https://social.heldscal.la/user/23211"
@ -447,7 +484,7 @@ test "it works for atom notes, too" do
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)

View file

@ -6,7 +6,7 @@ defmodule Pleroma.Web.OStatus.UserRepresenterTest do
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

View file

@ -3,6 +3,7 @@ defmodule Pleroma.Web.Salmon.SalmonTest do
alias Pleroma.Web.Salmon
alias Pleroma.{Repo, Activity, User}
import Pleroma.Factory
import Tesla.Mock
@magickey "RSA.pu0s-halox4tu7wmES1FVSx6u-4wc0YrUFXcqWXZG4-27UmbCOpMQftRCldNRfyA-qLbz-eqiwQhh-1EwUvjsD4cYbAHNGHwTvDOyx5AKthQUP44ykPv7kjKGh3DWKySJvcs9tlUG87hlo7AvnMo9pwRS_Zz2CacQ-MKaXyDepk=.AQAB"
@ -10,6 +11,11 @@ defmodule Pleroma.Web.Salmon.SalmonTest do
@magickey_friendica "RSA.AMwa8FUs2fWEjX0xN7yRQgegQffhBpuKNC6fa5VNSVorFjGZhRrlPMn7TQOeihlc9lBz2OsHlIedbYn2uJ7yCs0.AQAB"
setup do
mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
:ok
end
test "decodes a salmon" do
{:ok, salmon} = File.read("test/fixtures/salmon.xml")
{:ok, doc} = Salmon.decode_and_validate(@magickey, salmon)

View file

@ -58,7 +58,7 @@ test "a like activity" do
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"})

View file

@ -12,6 +12,42 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do
import Pleroma.Factory
describe "POST /api/account/update_profile_banner" do
test "it updates the banner", %{conn: conn} do
user = insert(:user)
new_banner =
"data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7"
response =
conn
|> assign(:user, user)
|> post(authenticated_twitter_api__path(conn, :update_banner), %{"banner" => new_banner})
|> json_response(200)
user = Repo.get(User, user.id)
assert user.info.banner["type"] == "Image"
end
end
describe "POST /api/qvitter/update_background_image" do
test "it updates the background", %{conn: conn} do
user = insert(:user)
new_bg =
"data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7"
response =
conn
|> assign(:user, user)
|> post(authenticated_twitter_api__path(conn, :update_background), %{"img" => new_bg})
|> json_response(200)
user = Repo.get(User, user.id)
assert user.info.background["type"] == "Image"
end
end
describe "POST /api/account/verify_credentials" do
setup [:valid_user]
@ -31,26 +67,6 @@ test "with credentials", %{conn: conn, user: user} do
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]
@ -87,7 +103,7 @@ test "with credentials", %{conn: conn, user: user} do
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
@ -591,7 +607,7 @@ test "with credentials", %{conn: conn, user: current_user} do
|> 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})
@ -939,18 +955,21 @@ test "it returns a user's friends", %{conn: conn} do
describe "POST /api/account/update_profile.json" do
test "it updates a user's profile", %{conn: conn} do
user = insert(:user)
user2 = insert(:user)
conn =
conn
|> assign(:user, user)
|> post("/api/account/update_profile.json", %{
"name" => "new name",
"description" => "new description"
"description" => "hi @#{user2.nickname}"
})
user = Repo.get!(User, user.id)
assert user.name == "new name"
assert user.bio == "new description"
assert user.bio ==
"hi <span><a class='mention' href='#{user2.ap_id}'>@<span>#{user2.nickname}</span></a></span>"
assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
end
@ -966,7 +985,7 @@ test "it locks an account", %{conn: conn} do
})
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
@ -982,7 +1001,7 @@ test "it unlocks an account", %{conn: conn} do
})
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
@ -1153,10 +1172,10 @@ test "with credentials and valid password", %{conn: conn, user: current_user} do
describe "GET /api/pleroma/friend_requests" do
test "it lists friend requests" do
user = insert(:user, %{info: %{"locked" => true}})
user = insert(:user)
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)
@ -1175,10 +1194,10 @@ test "it lists friend requests" do
describe "POST /api/pleroma/friendships/approve" do
test "it approves a friend request" do
user = insert(:user, %{info: %{"locked" => true}})
user = insert(:user)
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)
@ -1198,10 +1217,10 @@ test "it approves a friend request" do
describe "POST /api/pleroma/friendships/deny" do
test "it denies a friend request" do
user = insert(:user, %{info: %{"locked" => true}})
user = insert(:user)
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)

View file

@ -10,7 +10,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
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",
@ -67,7 +67,7 @@ test "create a status" do
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
@ -116,7 +116,7 @@ test "Follow another user using screen_name" 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."
@ -169,7 +169,7 @@ test "Unblock another user using user_id" do
{: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
@ -178,7 +178,7 @@ 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
@ -257,6 +257,35 @@ test "it registers a new user and returns the user." do
UserView.render("show.json", %{user: fetched_user})
end
test "it registers a new user and parses mentions in the bio" do
data1 = %{
"nickname" => "john",
"email" => "john@gmail.com",
"fullname" => "John Doe",
"bio" => "test",
"password" => "bear",
"confirm" => "bear"
}
{:ok, user1} = TwitterAPI.register_user(data1)
data2 = %{
"nickname" => "lain",
"email" => "lain@wired.jp",
"fullname" => "lain iwakura",
"bio" => "@john test",
"password" => "bear",
"confirm" => "bear"
}
{:ok, user2} = TwitterAPI.register_user(data2)
expected_text =
"<span><a class='mention' href='#{user1.ap_id}'>@<span>john</span></a></span> test"
assert user2.bio == expected_text
end
@moduletag skip: "needs 'registrations_open: false' in config"
test "it registers a new user via invite token and returns the user." do
{:ok, token} = UserInviteToken.create_token()

View file

@ -31,10 +31,10 @@ test "A user with emoji in username", %{user: user} 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",
@ -43,10 +43,10 @@ test "A user with emoji in username", %{user: user} do
}
]
}
}
}
},
name: ":karjalanpiirakka: man"
})
user = %{user | name: ":karjalanpiirakka: man"}
represented = UserView.render("show.json", %{user: user})
assert represented["name_html"] == expected
end
@ -103,7 +103,7 @@ test "A user" do
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"
@ -186,7 +186,7 @@ test "A user that follows you", %{user: user} do
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"]
@ -250,7 +250,7 @@ test "a user with mastodon fields" do
user =
insert(:user, %{
info: %{
"source_data" => %{
source_data: %{
"attachment" =>
Enum.map(fields, fn field -> Map.put(field, "type", "PropertyValue") end)
}

View file

@ -2,6 +2,12 @@ defmodule Pleroma.Web.WebFingerTest do
use Pleroma.DataCase
alias Pleroma.Web.WebFinger
import Pleroma.Factory
import Tesla.Mock
setup do
mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
:ok
end
describe "host meta" do
test "returns a link to the xml lrdd" do
@ -99,15 +105,15 @@ test "it gets the xrd endpoint for statusnet" do
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

View file

@ -10,6 +10,12 @@ defmodule Pleroma.Web.WebsubTest do
alias Pleroma.Web.Websub.{WebsubServerSubscription, WebsubClientSubscription}
import Pleroma.Factory
alias Pleroma.Web.Router.Helpers
import Tesla.Mock
setup do
mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
:ok
end
test "a verification of a request that is accepted" do
sub = insert(:websub_subscription)
@ -26,8 +32,8 @@ test "a verification of a request that is accepted" do
assert String.to_integer(seconds) > 0
{:ok,
%HTTPoison.Response{
status_code: 200,
%Tesla.Env{
status: 200,
body: challenge
}}
end
@ -41,8 +47,8 @@ test "a verification of a request that doesn't return 200" do
getter = fn _path, _headers, _options ->
{:ok,
%HTTPoison.Response{
status_code: 500,
%Tesla.Env{
status: 500,
body: ""
}}
end
@ -99,7 +105,7 @@ def accepting_verifier(subscription) do
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]
@ -113,12 +119,7 @@ test "initiate a subscription for a given user and topic" do
test "discovers the hub and canonical url" do
topic = "https://mastodon.social/users/lambadalambda.atom"
getter = fn ^topic ->
doc = File.read!("test/fixtures/lambadalambda.atom")
{:ok, %{status_code: 200, body: doc}}
end
{:ok, discovered} = Websub.gather_feed_data(topic, getter)
{:ok, discovered} = Websub.gather_feed_data(topic)
expected = %{
"hub" => "https://mastodon.social/api/push",
@ -158,7 +159,7 @@ test "calls the hub, requests topic" do
websub.id
)
{:ok, %{status_code: 202}}
{:ok, %{status: 202}}
end
task = Task.async(fn -> Websub.request_subscription(websub, poster) end)
@ -177,7 +178,7 @@ test "rejects the subscription if it can't be accepted" do
websub = insert(:websub_client_subscription, %{hub: hub, topic: topic})
poster = fn ^hub, {:form, _data}, _headers ->
{:ok, %{status_code: 202}}
{:ok, %{status: 202}}
end
{:error, websub} = Websub.request_subscription(websub, poster, 1000)
@ -186,7 +187,7 @@ test "rejects the subscription if it can't be accepted" do
websub = insert(:websub_client_subscription, %{hub: hub, topic: topic})
poster = fn ^hub, {:form, _data}, _headers ->
{:ok, %{status_code: 400}}
{:ok, %{status: 400}}
end
{:error, websub} = Websub.request_subscription(websub, poster, 1000)
@ -209,6 +210,7 @@ test "it renews subscriptions that have less than a day of time left" do
insert(:websub_client_subscription, %{
valid_until: NaiveDateTime.add(now, 2 * day),
topic: "http://example.org/still_good",
hub: "http://example.org/still_good",
state: "accepted"
})
@ -216,6 +218,7 @@ test "it renews subscriptions that have less than a day of time left" do
insert(:websub_client_subscription, %{
valid_until: NaiveDateTime.add(now, day - 100),
topic: "http://example.org/needs_refresh",
hub: "http://example.org/needs_refresh",
state: "accepted"
})