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

@ -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 @@ defmodule Pleroma.Formatter 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 @@ defmodule Pleroma.HTTP 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 @@ defmodule Pleroma.HTTP 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 @@ defmodule Pleroma.Plugs.OAuthPlug 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 @@ defmodule Pleroma.Plugs.UserEnabledPlug 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 @@ defmodule Pleroma.Plugs.UserIsAdminPlug 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 @@ defmodule Pleroma.Uploaders.MDII 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 @@ defmodule Pleroma.Uploaders.Swift.Keystone 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 @@ defmodule Pleroma.Uploaders.Swift.Client 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 @@ defmodule Pleroma.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 @@ defmodule Pleroma.User 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 @@ defmodule Pleroma.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 @@ defmodule Pleroma.User 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 @@ defmodule Pleroma.User 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 @@ defmodule Pleroma.User 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 @@ defmodule Pleroma.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 @@ defmodule Pleroma.User 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 @@ defmodule Pleroma.User 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 @@ defmodule Pleroma.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 @@ defmodule Pleroma.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 @@ defmodule Pleroma.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 @@ defmodule Pleroma.User 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 @@ defmodule Pleroma.User 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 @@ defmodule Pleroma.User 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 @@ defmodule Pleroma.User 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 @@ defmodule Pleroma.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 @@ defmodule Pleroma.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 @@ defmodule Pleroma.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 @@ defmodule Pleroma.User do
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 @@ defmodule Pleroma.User 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 @@ defmodule Pleroma.User 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 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
defp check_actor_is_active(actor) do
if not is_nil(actor) do
with user <- User.get_cached_by_ap_id(actor),
false <- !!user.info["deactivated"] do
false <- user.info.deactivated do
:ok
else
_e -> :reject
@ -509,8 +509,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub 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 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub 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 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub 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 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy 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 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
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 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier 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 @@ defmodule Pleroma.Web.ActivityPub.UserView 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 @@ defmodule Pleroma.Web.ActivityPub.UserView 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 @@ defmodule Pleroma.Web.ActivityPub.UserView 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 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
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 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
user = User.get_by_nickname(nickname)
info =
user.info
%{}
|> Map.put("is_" <> permission_group, false)
cng = User.info_changeset(user, %{info: info})
info_cng = User.Info.admin_api_update(user.info, info)
cng =
Ecto.Changeset.change(user)
|> Ecto.Changeset.put_embed(:info, info_cng)
{:ok, user} = User.update_and_set_cache(cng)
conn
|> json(user.info)
|> json(info)
end
end

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 @@ defmodule Pleroma.Web.CommonAPI 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 @@ defmodule Pleroma.Web.Federator.RetryQueue do
end
def start_link() do
GenServer.start_link(__MODULE__, %{delivered: 0, dropped: 0}, name: __MODULE__)
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 @@ defmodule Pleroma.Web.HTTPSignatures 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 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController 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)
else
params
end
params =
if name = params["display_name"] do
Map.put(params, "name", name)
else
params
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
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
_e -> user
_ -> :error
end
else
user
end
end)
user =
if banner = params["header"] do
with %Plug.Upload{} <- banner,
{:ok, object} <- ActivityPub.upload(banner, type: :banner),
new_info <- Map.put(user.info, "banner", object.data),
change <- User.info_changeset(user, %{info: new_info}),
{:ok, user} <- User.update_and_set_cache(change) do
user
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
_e -> user
_ -> :error
end
else
user
end
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
info_cng = User.Info.mastodon_profile_update(user.info, info_params)
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 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController 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 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController 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 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController 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 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
]
},
settings:
Map.get(user.info, "settings") ||
Map.get(user.info, :settings) ||
%{
onboarded: true,
home: %{
@ -1180,7 +1168,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController 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 @@ defmodule Pleroma.Web.MastodonAPI.AccountView 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 @@ defmodule Pleroma.Web.MastodonAPI.AccountView 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 @@ defmodule Pleroma.Web.OStatus 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 @@ defmodule Pleroma.Web.OStatus 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,
timeout: 10000,
recv_timeout: 20000
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 @@ defmodule Pleroma.Web.Salmon 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"}],
timeout: 10000,
recv_timeout: 20000,
hackney: [pool: :default]
adapter: [
timeout: 10000,
recv_timeout: 20000,
pool: :default
]
) do
Logger.debug(fn -> "Pushed to #{salmon}, code #{code}" end)
else
@ -185,7 +187,7 @@ defmodule Pleroma.Web.Salmon do
]
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 @@ defmodule Pleroma.Web.Streamer 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 || []
parent = Object.normalize(item.data["object"])
@ -206,7 +206,7 @@ defmodule Pleroma.Web.Streamer 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 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI 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 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI 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 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI 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 @@ defmodule Pleroma.Web.TwitterAPI.Controller 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 @@ defmodule Pleroma.Web.TwitterAPI.Controller 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 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
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 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
json(conn, [])
end
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)
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
end
def update_profile(%{assigns: %{user: user}} = conn, params) do
params =
if bio = params["description"] do
mentions = Formatter.parse_mentions(bio)
tags = Formatter.parse_tags(bio)
emoji =
(user.info["source_data"]["tag"] || [])
|> Enum.filter(fn %{"type" => t} -> t == "Emoji" end)
|> Enum.map(fn %{"icon" => %{"url" => url}, "name" => name} ->
{String.trim(name, ":"), url}
end)
bio_html = CommonUtils.format_input(bio, mentions, tags, "text/plain")
Map.put(params, "bio", bio_html |> Formatter.emojify(emoji))
else
params
end
user =
if locked = params["locked"] do
with locked <- locked == "true",
new_info <- Map.put(user.info, "locked", locked),
change <- User.info_changeset(user, %{info: new_info}),
{:ok, user} <- User.update_and_set_cache(change) do
user
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
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 @@ defmodule Pleroma.Web.TwitterAPI.UserView 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 @@ defmodule Pleroma.Web.TwitterAPI.UserView 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 @@ defmodule Pleroma.Web.TwitterAPI.UserView 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 @@ defmodule Pleroma.Web.WebFinger 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 @@ defmodule Pleroma.Web.WebFinger 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 @@ defmodule Pleroma.Web.WebFinger 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 @@ defmodule Pleroma.Web.WebFinger 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 @@ defmodule Pleroma.Web.WebFinger 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 @@ defmodule Pleroma.Web.Websub 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 @@ defmodule Pleroma.Web.Websub 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 @@ defmodule Pleroma.Web.Websub 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 @@ defmodule Pleroma.Web.Websub do
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 @@ defmodule Pleroma.Web.Websub do
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 @@ defmodule Pleroma.Web.Websub do
{"Content-Type", "application/atom+xml"},
{"X-Hub-Signature", "sha1=#{signature}"}
],
timeout: 10000,
recv_timeout: 20000,
hackney: [pool: :default]
adapter: [
timeout: 10000,
recv_timeout: 20000,
pool: :default
]
) do
Logger.info(fn -> "Pushed to #{callback}, code #{code}" end)
{:ok, code}