Merge branch 'develop' of git.pleroma.social:pleroma/pleroma into remake-remodel-dms

This commit is contained in:
lain 2020-05-17 12:14:49 +02:00
commit 9c17109765
59 changed files with 1225 additions and 501 deletions

View file

@ -387,56 +387,47 @@ defp render_timelines(user) do
favourites = ActivityPub.fetch_favourites(user) favourites = ActivityPub.fetch_favourites(user)
output_relationships =
!!Pleroma.Config.get([:extensions, :output_relationships_in_statuses_by_default])
Benchee.run( Benchee.run(
%{ %{
"Rendering home timeline" => fn -> "Rendering home timeline" => fn ->
StatusView.render("index.json", %{ StatusView.render("index.json", %{
activities: home_activities, activities: home_activities,
for: user, for: user,
as: :activity, as: :activity
skip_relationships: !output_relationships
}) })
end, end,
"Rendering direct timeline" => fn -> "Rendering direct timeline" => fn ->
StatusView.render("index.json", %{ StatusView.render("index.json", %{
activities: direct_activities, activities: direct_activities,
for: user, for: user,
as: :activity, as: :activity
skip_relationships: !output_relationships
}) })
end, end,
"Rendering public timeline" => fn -> "Rendering public timeline" => fn ->
StatusView.render("index.json", %{ StatusView.render("index.json", %{
activities: public_activities, activities: public_activities,
for: user, for: user,
as: :activity, as: :activity
skip_relationships: !output_relationships
}) })
end, end,
"Rendering tag timeline" => fn -> "Rendering tag timeline" => fn ->
StatusView.render("index.json", %{ StatusView.render("index.json", %{
activities: tag_activities, activities: tag_activities,
for: user, for: user,
as: :activity, as: :activity
skip_relationships: !output_relationships
}) })
end, end,
"Rendering notifications" => fn -> "Rendering notifications" => fn ->
Pleroma.Web.MastodonAPI.NotificationView.render("index.json", %{ Pleroma.Web.MastodonAPI.NotificationView.render("index.json", %{
notifications: notifications, notifications: notifications,
for: user, for: user
skip_relationships: !output_relationships
}) })
end, end,
"Rendering favourites timeline" => fn -> "Rendering favourites timeline" => fn ->
StatusView.render("index.json", %{ StatusView.render("index.json", %{
activities: favourites, activities: favourites,
for: user, for: user,
as: :activity, as: :activity
skip_relationships: !output_relationships
}) })
end end
}, },

View file

@ -251,8 +251,6 @@
] ]
] ]
config :pleroma, :extensions, output_relationships_in_statuses_by_default: true
config :pleroma, :feed, config :pleroma, :feed,
post_title: %{ post_title: %{
max_length: 100, max_length: 100,

View file

@ -679,15 +679,6 @@
7 7
] ]
}, },
%{
key: :federation_publisher_modules,
type: {:list, :module},
description:
"List of modules for federation publishing. Module names are shortened (removed leading `Pleroma.Web.` part), but on adding custom module you need to use full name.",
suggestions: [
Pleroma.Web.ActivityPub.Publisher
]
},
%{ %{
key: :allow_relay, key: :allow_relay,
type: :boolean, type: :boolean,
@ -1105,32 +1096,97 @@
description: "Settings for Pleroma FE", description: "Settings for Pleroma FE",
suggestions: [ suggestions: [
%{ %{
theme: "pleroma-dark",
logo: "/static/logo.png",
background: "/images/city.jpg",
redirectRootNoLogin: "/main/all",
redirectRootLogin: "/main/friends",
showInstanceSpecificPanel: true,
scopeOptionsEnabled: false,
formattingOptionsEnabled: false,
collapseMessageWithSubject: false,
hidePostStats: false,
hideUserStats: false,
scopeCopy: true,
subjectLineBehavior: "email",
alwaysShowSubjectInput: true, alwaysShowSubjectInput: true,
logoMask: false, background: "/static/aurora_borealis.jpg",
collapseMessageWithSubject: false,
disableChat: false,
greentext: false,
hideFilteredStatuses: false,
hideMutedPosts: false,
hidePostStats: false,
hideSitename: false,
hideUserStats: false,
loginMethod: "password",
logo: "/static/logo.png",
logoMargin: ".1em", logoMargin: ".1em",
stickers: false, logoMask: true,
enableEmojiPicker: false minimalScopesMode: false,
noAttachmentLinks: false,
nsfwCensorImage: "",
postContentType: "text/plain",
redirectRootLogin: "/main/friends",
redirectRootNoLogin: "/main/all",
scopeCopy: true,
showFeaturesPanel: true,
showInstanceSpecificPanel: false,
subjectLineBehavior: "email",
theme: "pleroma-dark",
webPushNotifications: false
} }
], ],
children: [ children: [
%{ %{
key: :theme, key: :alwaysShowSubjectInput,
label: "Always show subject input",
type: :boolean,
description: "When disabled, auto-hide the subject field if it's empty"
},
%{
key: :background,
type: :string, type: :string,
description: "Which theme to use, they are defined in styles.json", description:
suggestions: ["pleroma-dark"] "URL of the background, unless viewing a user profile with a background that is set",
suggestions: ["/images/city.jpg"]
},
%{
key: :collapseMessageWithSubject,
label: "Collapse message with subject",
type: :boolean,
description:
"When a message has a subject (aka Content Warning), collapse it by default"
},
%{
key: :disableChat,
label: "PleromaFE Chat",
type: :boolean,
description: "Disables PleromaFE Chat component"
},
%{
key: :greentext,
label: "Greentext",
type: :boolean,
description: "Enables green text on lines prefixed with the > character."
},
%{
key: :hideFilteredStatuses,
label: "Hide Filtered Statuses",
type: :boolean,
description: "Hides filtered statuses from timelines."
},
%{
key: :hideMutedPosts,
label: "Hide Muted Posts",
type: :boolean,
description: "Hides muted statuses from timelines."
},
%{
key: :hidePostStats,
label: "Hide post stats",
type: :boolean,
description: "Hide notices statistics (repeats, favorites, ...)"
},
%{
key: :hideSitename,
label: "Hide Sitename",
type: :boolean,
description: "Hides instance name from PleromaFE banner."
},
%{
key: :hideUserStats,
label: "Hide user stats",
type: :boolean,
description:
"Hide profile statistics (posts, posts per day, followers, followings, ...)"
}, },
%{ %{
key: :logo, key: :logo,
@ -1139,11 +1195,44 @@
suggestions: ["/static/logo.png"] suggestions: ["/static/logo.png"]
}, },
%{ %{
key: :background, key: :logoMargin,
label: "Logo margin",
type: :string, type: :string,
description: description:
"URL of the background, unless viewing a user profile with a background that is set", "Allows you to adjust vertical margins between logo boundary and navbar borders. " <>
suggestions: ["/images/city.jpg"] "The idea is that to have logo's image without any extra margins and instead adjust them to your need in layout.",
suggestions: [".1em"]
},
%{
key: :logoMask,
label: "Logo mask",
type: :boolean,
description:
"By default it assumes logo used will be monochrome with alpha channel to be compatible with both light and dark themes. " <>
"If you want a colorful logo you must disable logoMask."
},
%{
key: :minimalScopesMode,
label: "Minimal scopes mode",
type: :boolean,
description:
"Limit scope selection to Direct, User default, and Scope of post replying to. " <>
"Also prevents replying to a DM with a public post from PleromaFE."
},
%{
key: :nsfwCensorImage,
label: "NSFW Censor Image",
type: :string,
description:
"URL of the image to use for hiding NSFW media attachments in the timeline.",
suggestions: ["/static/img/nsfw.png"]
},
%{
key: :postContentType,
label: "Post Content Type",
type: {:dropdown, :atom},
description: "Default post formatting option.",
suggestions: ["text/plain", "text/html", "text/markdown", "text/bbcode"]
}, },
%{ %{
key: :redirectRootNoLogin, key: :redirectRootNoLogin,
@ -1161,51 +1250,25 @@
"Relative URL which indicates where to redirect when a user is logged in", "Relative URL which indicates where to redirect when a user is logged in",
suggestions: ["/main/friends"] suggestions: ["/main/friends"]
}, },
%{
key: :showInstanceSpecificPanel,
label: "Show instance specific panel",
type: :boolean,
description: "Whenether to show the instance's specific panel"
},
%{
key: :scopeOptionsEnabled,
label: "Scope options enabled",
type: :boolean,
description: "Enable setting a notice visibility and subject/CW when posting"
},
%{
key: :formattingOptionsEnabled,
label: "Formatting options enabled",
type: :boolean,
description:
"Enable setting a formatting different than plain-text (ie. HTML, Markdown) when posting, relates to `:instance`, `allowed_post_formats`"
},
%{
key: :collapseMessageWithSubject,
label: "Collapse message with subject",
type: :boolean,
description:
"When a message has a subject (aka Content Warning), collapse it by default"
},
%{
key: :hidePostStats,
label: "Hide post stats",
type: :boolean,
description: "Hide notices statistics (repeats, favorites, ...)"
},
%{
key: :hideUserStats,
label: "Hide user stats",
type: :boolean,
description:
"Hide profile statistics (posts, posts per day, followers, followings, ...)"
},
%{ %{
key: :scopeCopy, key: :scopeCopy,
label: "Scope copy", label: "Scope copy",
type: :boolean, type: :boolean,
description: "Copy the scope (private/unlisted/public) in replies to posts by default" description: "Copy the scope (private/unlisted/public) in replies to posts by default"
}, },
%{
key: :showFeaturesPanel,
label: "Show instance features panel",
type: :boolean,
description:
"Enables panel displaying functionality of the instance on the About page."
},
%{
key: :showInstanceSpecificPanel,
label: "Show instance specific panel",
type: :boolean,
description: "Whether to show the instance's custom panel"
},
%{ %{
key: :subjectLineBehavior, key: :subjectLineBehavior,
label: "Subject line behavior", label: "Subject line behavior",
@ -1217,38 +1280,10 @@
suggestions: ["email", "masto", "noop"] suggestions: ["email", "masto", "noop"]
}, },
%{ %{
key: :alwaysShowSubjectInput, key: :theme,
label: "Always show subject input",
type: :boolean,
description: "When disabled, auto-hide the subject field if it's empty"
},
%{
key: :logoMask,
label: "Logo mask",
type: :boolean,
description:
"By default it assumes logo used will be monochrome with alpha channel to be compatible with both light and dark themes. " <>
"If you want a colorful logo you must disable logoMask."
},
%{
key: :logoMargin,
label: "Logo margin",
type: :string, type: :string,
description: description: "Which theme to use. Available themes are defined in styles.json",
"Allows you to adjust vertical margins between logo boundary and navbar borders. " <> suggestions: ["pleroma-dark"]
"The idea is that to have logo's image without any extra margins and instead adjust them to your need in layout.",
suggestions: [".1em"]
},
%{
key: :stickers,
type: :boolean,
description: "Enables stickers."
},
%{
key: :enableEmojiPicker,
label: "Emoji picker",
type: :boolean,
description: "Enables emoji picker."
} }
] ]
}, },
@ -1858,12 +1893,6 @@
(see https://github.com/sorentwo/oban/issues/52). (see https://github.com/sorentwo/oban/issues/52).
""", """,
children: [ children: [
%{
key: :repo,
type: :module,
description: "Application's Ecto repo",
suggestions: [Pleroma.Repo]
},
%{ %{
key: :verbose, key: :verbose,
type: {:dropdown, :atom}, type: {:dropdown, :atom},
@ -2638,18 +2667,6 @@
} }
] ]
}, },
%{
group: :http_signatures,
type: :group,
description: "HTTP Signatures settings",
children: [
%{
key: :adapter,
type: :module,
suggestions: [Pleroma.Signature]
}
]
},
%{ %{
group: :pleroma, group: :pleroma,
key: :http, key: :http,

View file

@ -67,8 +67,7 @@ def run(["render_timeline", nickname | _] = args) do
Pleroma.Web.MastodonAPI.StatusView.render("index.json", %{ Pleroma.Web.MastodonAPI.StatusView.render("index.json", %{
activities: activities, activities: activities,
for: user, for: user,
as: :activity, as: :activity
skip_relationships: true
}) })
end end
}, },

View file

@ -1,5 +1,6 @@
defmodule Mix.Tasks.Pleroma.Digest do defmodule Mix.Tasks.Pleroma.Digest do
use Mix.Task use Mix.Task
import Mix.Pleroma
@shortdoc "Manages digest emails" @shortdoc "Manages digest emails"
@moduledoc File.read!("docs/administration/CLI_tasks/digest.md") @moduledoc File.read!("docs/administration/CLI_tasks/digest.md")
@ -22,12 +23,10 @@ def run(["test", nickname | opts]) do
with %Swoosh.Email{} = email <- Pleroma.Emails.UserEmail.digest_email(patched_user) do with %Swoosh.Email{} = email <- Pleroma.Emails.UserEmail.digest_email(patched_user) do
{:ok, _} = Pleroma.Emails.Mailer.deliver(email) {:ok, _} = Pleroma.Emails.Mailer.deliver(email)
Mix.shell().info("Digest email have been sent to #{nickname} (#{user.email})") shell_info("Digest email have been sent to #{nickname} (#{user.email})")
else else
_ -> _ ->
Mix.shell().info( shell_info("Cound't find any mentions for #{nickname} since #{last_digest_emailed_at}")
"Cound't find any mentions for #{nickname} since #{last_digest_emailed_at}"
)
end end
end end
end end

View file

@ -278,6 +278,8 @@ defp do_convert({:proxy_url, {type, host, port}}) do
} }
end end
defp do_convert({:partial_chain, entity}), do: %{"tuple" => [":partial_chain", inspect(entity)]}
defp do_convert(entity) when is_tuple(entity) do defp do_convert(entity) when is_tuple(entity) do
value = value =
entity entity
@ -321,6 +323,15 @@ defp do_transform(%{"tuple" => [":proxy_url", %{"tuple" => [type, host, port]}]}
{:proxy_url, {do_transform_string(type), parse_host(host), port}} {:proxy_url, {do_transform_string(type), parse_host(host), port}}
end end
defp do_transform(%{"tuple" => [":partial_chain", entity]}) do
{partial_chain, []} =
entity
|> String.replace(~r/[^\w|^{:,[|^,|^[|^\]^}|^\/|^\.|^"]^\s/, "")
|> Code.eval_string()
{:partial_chain, partial_chain}
end
defp do_transform(%{"tuple" => entity}) do defp do_transform(%{"tuple" => entity}) do
Enum.reduce(entity, {}, fn val, acc -> Tuple.append(acc, do_transform(val)) end) Enum.reduce(entity, {}, fn val, acc -> Tuple.append(acc, do_transform(val)) end)
end end

View file

@ -87,6 +87,22 @@ def dictionary(
source_to_target_rel_types \\ nil, source_to_target_rel_types \\ nil,
target_to_source_rel_types \\ nil target_to_source_rel_types \\ nil
) )
def dictionary(
_source_users,
_target_users,
[] = _source_to_target_rel_types,
[] = _target_to_source_rel_types
) do
[]
end
def dictionary(
source_users,
target_users,
source_to_target_rel_types,
target_to_source_rel_types
)
when is_list(source_users) and is_list(target_users) do when is_list(source_users) and is_list(target_users) do
source_user_ids = User.binary_id(source_users) source_user_ids = User.binary_id(source_users)
target_user_ids = User.binary_id(target_users) target_user_ids = User.binary_id(target_users)
@ -138,11 +154,16 @@ def view_relationships_option(nil = _reading_user, _actors, _opts) do
def view_relationships_option(%User{} = reading_user, actors, opts) do def view_relationships_option(%User{} = reading_user, actors, opts) do
{source_to_target_rel_types, target_to_source_rel_types} = {source_to_target_rel_types, target_to_source_rel_types} =
if opts[:source_mutes_only] do case opts[:subset] do
# This option is used for rendering statuses (FE needs `muted` flag for each one anyways) :source_mutes ->
{[:mute], []} # Used for statuses rendering (FE needs `muted` flag for each status when statuses load)
else {[:mute], []}
{[:block, :mute, :notification_mute, :reblog_mute], [:block, :inverse_subscription]}
nil ->
{[:block, :mute, :notification_mute, :reblog_mute], [:block, :inverse_subscription]}
unknown ->
raise "Unsupported :subset option value: #{inspect(unknown)}"
end end
user_relationships = user_relationships =
@ -153,7 +174,17 @@ def view_relationships_option(%User{} = reading_user, actors, opts) do
target_to_source_rel_types target_to_source_rel_types
) )
following_relationships = FollowingRelationship.all_between_user_sets([reading_user], actors) following_relationships =
case opts[:subset] do
:source_mutes ->
[]
nil ->
FollowingRelationship.all_between_user_sets([reading_user], actors)
unknown ->
raise "Unsupported :subset option value: #{inspect(unknown)}"
end
%{user_relationships: user_relationships, following_relationships: following_relationships} %{user_relationships: user_relationships, following_relationships: following_relationships}
end end

View file

@ -22,6 +22,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
alias Pleroma.Web.ActivityPub.Pipeline alias Pleroma.Web.ActivityPub.Pipeline
alias Pleroma.Web.ActivityPub.Relay alias Pleroma.Web.ActivityPub.Relay
alias Pleroma.Web.ActivityPub.Utils alias Pleroma.Web.ActivityPub.Utils
alias Pleroma.Web.AdminAPI
alias Pleroma.Web.AdminAPI.AccountView alias Pleroma.Web.AdminAPI.AccountView
alias Pleroma.Web.AdminAPI.ConfigView alias Pleroma.Web.AdminAPI.ConfigView
alias Pleroma.Web.AdminAPI.ModerationLogView alias Pleroma.Web.AdminAPI.ModerationLogView
@ -30,8 +31,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
alias Pleroma.Web.AdminAPI.Search alias Pleroma.Web.AdminAPI.Search
alias Pleroma.Web.CommonAPI alias Pleroma.Web.CommonAPI
alias Pleroma.Web.Endpoint alias Pleroma.Web.Endpoint
alias Pleroma.Web.MastodonAPI
alias Pleroma.Web.MastodonAPI.AppView alias Pleroma.Web.MastodonAPI.AppView
alias Pleroma.Web.MastodonAPI.StatusView
alias Pleroma.Web.OAuth.App alias Pleroma.Web.OAuth.App
alias Pleroma.Web.Router alias Pleroma.Web.Router
@ -280,8 +281,8 @@ def list_instance_statuses(conn, %{"instance" => instance} = params) do
}) })
conn conn
|> put_view(Pleroma.Web.AdminAPI.StatusView) |> put_view(AdminAPI.StatusView)
|> render("index.json", %{activities: activities, as: :activity, skip_relationships: false}) |> render("index.json", %{activities: activities, as: :activity})
end end
def list_user_statuses(conn, %{"nickname" => nickname} = params) do def list_user_statuses(conn, %{"nickname" => nickname} = params) do
@ -299,8 +300,8 @@ def list_user_statuses(conn, %{"nickname" => nickname} = params) do
}) })
conn conn
|> put_view(StatusView) |> put_view(MastodonAPI.StatusView)
|> render("index.json", %{activities: activities, as: :activity, skip_relationships: false}) |> render("index.json", %{activities: activities, as: :activity})
else else
_ -> {:error, :not_found} _ -> {:error, :not_found}
end end
@ -829,14 +830,14 @@ def list_statuses(%{assigns: %{user: _admin}} = conn, params) do
}) })
conn conn
|> put_view(Pleroma.Web.AdminAPI.StatusView) |> put_view(AdminAPI.StatusView)
|> render("index.json", %{activities: activities, as: :activity, skip_relationships: false}) |> render("index.json", %{activities: activities, as: :activity})
end end
def status_show(conn, %{"id" => id}) do def status_show(conn, %{"id" => id}) do
with %Activity{} = activity <- Activity.get_by_id(id) do with %Activity{} = activity <- Activity.get_by_id(id) do
conn conn
|> put_view(StatusView) |> put_view(MastodonAPI.StatusView)
|> render("show.json", %{activity: activity}) |> render("show.json", %{activity: activity})
else else
_ -> errors(conn, {:error, :not_found}) _ -> errors(conn, {:error, :not_found})
@ -861,7 +862,7 @@ def status_update(%{assigns: %{user: admin}} = conn, %{"id" => id} = params) do
}) })
conn conn
|> put_view(StatusView) |> put_view(MastodonAPI.StatusView)
|> render("show.json", %{activity: activity}) |> render("show.json", %{activity: activity})
end end
end end

View file

@ -6,7 +6,9 @@ defmodule Pleroma.Web.AdminAPI.AccountView do
use Pleroma.Web, :view use Pleroma.Web, :view
alias Pleroma.User alias Pleroma.User
alias Pleroma.Web.AdminAPI
alias Pleroma.Web.AdminAPI.AccountView alias Pleroma.Web.AdminAPI.AccountView
alias Pleroma.Web.MastodonAPI
alias Pleroma.Web.MediaProxy alias Pleroma.Web.MediaProxy
def render("index.json", %{users: users, count: count, page_size: page_size}) do def render("index.json", %{users: users, count: count, page_size: page_size}) do
@ -119,6 +121,13 @@ def render("create-error.json", %{changeset: %Ecto.Changeset{changes: changes, e
} }
end end
def merge_account_views(%User{} = user) do
MastodonAPI.AccountView.render("show.json", %{user: user})
|> Map.merge(AdminAPI.AccountView.render("show.json", %{user: user}))
end
def merge_account_views(_), do: %{}
defp parse_error([]), do: "" defp parse_error([]), do: ""
defp parse_error(errors) do defp parse_error(errors) do

View file

@ -7,10 +7,13 @@ defmodule Pleroma.Web.AdminAPI.ReportView do
alias Pleroma.HTML alias Pleroma.HTML
alias Pleroma.User alias Pleroma.User
alias Pleroma.Web.AdminAPI
alias Pleroma.Web.AdminAPI.Report alias Pleroma.Web.AdminAPI.Report
alias Pleroma.Web.CommonAPI.Utils alias Pleroma.Web.CommonAPI.Utils
alias Pleroma.Web.MastodonAPI.StatusView alias Pleroma.Web.MastodonAPI.StatusView
defdelegate merge_account_views(user), to: AdminAPI.AccountView
def render("index.json", %{reports: reports}) do def render("index.json", %{reports: reports}) do
%{ %{
reports: reports:
@ -41,8 +44,7 @@ def render("show.json", %{report: report, user: user, account: account, statuses
statuses: statuses:
StatusView.render("index.json", %{ StatusView.render("index.json", %{
activities: statuses, activities: statuses,
as: :activity, as: :activity
skip_relationships: false
}), }),
state: report.data["state"], state: report.data["state"],
notes: render(__MODULE__, "index_notes.json", %{notes: report.report_notes}) notes: render(__MODULE__, "index_notes.json", %{notes: report.report_notes})
@ -70,11 +72,4 @@ def render("show_note.json", %{
created_at: Utils.to_masto_date(inserted_at) created_at: Utils.to_masto_date(inserted_at)
} }
end end
defp merge_account_views(%User{} = user) do
Pleroma.Web.MastodonAPI.AccountView.render("show.json", %{user: user})
|> Map.merge(Pleroma.Web.AdminAPI.AccountView.render("show.json", %{user: user}))
end
defp merge_account_views(_), do: %{}
end end

View file

@ -7,24 +7,19 @@ defmodule Pleroma.Web.AdminAPI.StatusView do
require Pleroma.Constants require Pleroma.Constants
alias Pleroma.User alias Pleroma.Web.AdminAPI
alias Pleroma.Web.MastodonAPI.StatusView alias Pleroma.Web.MastodonAPI
defdelegate merge_account_views(user), to: AdminAPI.AccountView
def render("index.json", opts) do def render("index.json", opts) do
safe_render_many(opts.activities, __MODULE__, "show.json", opts) safe_render_many(opts.activities, __MODULE__, "show.json", opts)
end end
def render("show.json", %{activity: %{data: %{"object" => _object}} = activity} = opts) do def render("show.json", %{activity: %{data: %{"object" => _object}} = activity} = opts) do
user = StatusView.get_user(activity.data["actor"]) user = MastodonAPI.StatusView.get_user(activity.data["actor"])
StatusView.render("show.json", opts) MastodonAPI.StatusView.render("show.json", opts)
|> Map.merge(%{account: merge_account_views(user)}) |> Map.merge(%{account: merge_account_views(user)})
end end
defp merge_account_views(%User{} = user) do
Pleroma.Web.MastodonAPI.AccountView.render("show.json", %{user: user})
|> Map.merge(Pleroma.Web.AdminAPI.AccountView.render("show.json", %{user: user}))
end
defp merge_account_views(_), do: %{}
end end

View file

@ -5,6 +5,7 @@
defmodule Pleroma.Web.ApiSpec.Helpers do defmodule Pleroma.Web.ApiSpec.Helpers do
alias OpenApiSpex.Operation alias OpenApiSpex.Operation
alias OpenApiSpex.Schema alias OpenApiSpex.Schema
alias Pleroma.Web.ApiSpec.Schemas.BooleanLike
def request_body(description, schema_ref, opts \\ []) do def request_body(description, schema_ref, opts \\ []) do
media_types = ["application/json", "multipart/form-data", "application/x-www-form-urlencoded"] media_types = ["application/json", "multipart/form-data", "application/x-www-form-urlencoded"]
@ -47,6 +48,15 @@ def pagination_params do
] ]
end end
def with_relationships_param do
Operation.parameter(
:with_relationships,
:query,
BooleanLike,
"Embed relationships into accounts."
)
end
def empty_object_response do def empty_object_response do
Operation.response("Empty object", "application/json", %Schema{type: :object, example: %{}}) Operation.response("Empty object", "application/json", %Schema{type: :object, example: %{}})
end end

View file

@ -155,8 +155,10 @@ def followers_operation do
security: [%{"oAuth" => ["read:accounts"]}], security: [%{"oAuth" => ["read:accounts"]}],
description: description:
"Accounts which follow the given account, if network is not hidden by the account owner.", "Accounts which follow the given account, if network is not hidden by the account owner.",
parameters: parameters: [
[%Reference{"$ref": "#/components/parameters/accountIdOrNickname"}] ++ pagination_params(), %Reference{"$ref": "#/components/parameters/accountIdOrNickname"},
with_relationships_param() | pagination_params()
],
responses: %{ responses: %{
200 => Operation.response("Accounts", "application/json", array_of_accounts()) 200 => Operation.response("Accounts", "application/json", array_of_accounts())
} }
@ -171,8 +173,10 @@ def following_operation do
security: [%{"oAuth" => ["read:accounts"]}], security: [%{"oAuth" => ["read:accounts"]}],
description: description:
"Accounts which the given account is following, if network is not hidden by the account owner.", "Accounts which the given account is following, if network is not hidden by the account owner.",
parameters: parameters: [
[%Reference{"$ref": "#/components/parameters/accountIdOrNickname"}] ++ pagination_params(), %Reference{"$ref": "#/components/parameters/accountIdOrNickname"},
with_relationships_param() | pagination_params()
],
responses: %{200 => Operation.response("Accounts", "application/json", array_of_accounts())} responses: %{200 => Operation.response("Accounts", "application/json", array_of_accounts())}
} }
end end

View file

@ -0,0 +1,132 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ApiSpec.MediaOperation do
alias OpenApiSpex.Operation
alias OpenApiSpex.Schema
alias Pleroma.Web.ApiSpec.Helpers
alias Pleroma.Web.ApiSpec.Schemas.ApiError
alias Pleroma.Web.ApiSpec.Schemas.Attachment
def open_api_operation(action) do
operation = String.to_existing_atom("#{action}_operation")
apply(__MODULE__, operation, [])
end
def create_operation do
%Operation{
tags: ["media"],
summary: "Upload media as attachment",
description: "Creates an attachment to be used with a new status.",
operationId: "MediaController.create",
security: [%{"oAuth" => ["write:media"]}],
requestBody: Helpers.request_body("Parameters", create_request()),
responses: %{
200 => Operation.response("Media", "application/json", Attachment),
401 => Operation.response("Media", "application/json", ApiError),
422 => Operation.response("Media", "application/json", ApiError)
}
}
end
defp create_request do
%Schema{
title: "MediaCreateRequest",
description: "POST body for creating an attachment",
type: :object,
required: [:file],
properties: %{
file: %Schema{
type: :string,
format: :binary,
description: "The file to be attached, using multipart form data."
},
description: %Schema{
type: :string,
description: "A plain-text description of the media, for accessibility purposes."
},
focus: %Schema{
type: :string,
description: "Two floating points (x,y), comma-delimited, ranging from -1.0 to 1.0."
}
}
}
end
def update_operation do
%Operation{
tags: ["media"],
summary: "Upload media as attachment",
description: "Creates an attachment to be used with a new status.",
operationId: "MediaController.update",
security: [%{"oAuth" => ["write:media"]}],
parameters: [id_param()],
requestBody: Helpers.request_body("Parameters", update_request()),
responses: %{
200 => Operation.response("Media", "application/json", Attachment),
400 => Operation.response("Media", "application/json", ApiError),
401 => Operation.response("Media", "application/json", ApiError),
422 => Operation.response("Media", "application/json", ApiError)
}
}
end
defp update_request do
%Schema{
title: "MediaUpdateRequest",
description: "POST body for updating an attachment",
type: :object,
properties: %{
file: %Schema{
type: :string,
format: :binary,
description: "The file to be attached, using multipart form data."
},
description: %Schema{
type: :string,
description: "A plain-text description of the media, for accessibility purposes."
},
focus: %Schema{
type: :string,
description: "Two floating points (x,y), comma-delimited, ranging from -1.0 to 1.0."
}
}
}
end
def show_operation do
%Operation{
tags: ["media"],
summary: "Show Uploaded media attachment",
operationId: "MediaController.show",
parameters: [id_param()],
security: [%{"oAuth" => ["read:media"]}],
responses: %{
200 => Operation.response("Media", "application/json", Attachment),
401 => Operation.response("Media", "application/json", ApiError),
422 => Operation.response("Media", "application/json", ApiError)
}
}
end
def create2_operation do
%Operation{
tags: ["media"],
summary: "Upload media as attachment",
description: "Creates an attachment to be used with a new status.",
operationId: "MediaController.create2",
security: [%{"oAuth" => ["write:media"]}],
requestBody: Helpers.request_body("Parameters", create_request()),
responses: %{
202 => Operation.response("Media", "application/json", Attachment),
422 => Operation.response("Media", "application/json", ApiError),
500 => Operation.response("Media", "application/json", ApiError)
}
}
end
defp id_param do
Operation.parameter(:id, :path, :string, "The ID of the Attachment entity")
end
end

View file

@ -19,6 +19,7 @@ def open_api_operation(action) do
apply(__MODULE__, operation, []) apply(__MODULE__, operation, [])
end end
# Note: `with_relationships` param is not supported (PleromaFE uses this op for autocomplete)
def account_search_operation do def account_search_operation do
%Operation{ %Operation{
tags: ["Search"], tags: ["Search"],
@ -96,8 +97,8 @@ def search_operation do
:query, :query,
%Schema{type: :integer}, %Schema{type: :integer},
"Offset" "Offset"
) ),
| pagination_params() with_relationships_param() | pagination_params()
], ],
responses: %{ responses: %{
200 => Operation.response("Results", "application/json", results()) 200 => Operation.response("Results", "application/json", results())
@ -138,8 +139,8 @@ def search2_operation do
:query, :query,
%Schema{allOf: [BooleanLike], default: false}, %Schema{allOf: [BooleanLike], default: false},
"Only include accounts that the user is following" "Only include accounts that the user is following"
) ),
| pagination_params() with_relationships_param() | pagination_params()
], ],
responses: %{ responses: %{
200 => Operation.response("Results", "application/json", results2()) 200 => Operation.response("Results", "application/json", results2())

View file

@ -7,7 +7,6 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
alias OpenApiSpex.Schema alias OpenApiSpex.Schema
alias Pleroma.Web.ApiSpec.AccountOperation alias Pleroma.Web.ApiSpec.AccountOperation
alias Pleroma.Web.ApiSpec.Schemas.ApiError alias Pleroma.Web.ApiSpec.Schemas.ApiError
alias Pleroma.Web.ApiSpec.Schemas.BooleanLike
alias Pleroma.Web.ApiSpec.Schemas.FlakeID alias Pleroma.Web.ApiSpec.Schemas.FlakeID
alias Pleroma.Web.ApiSpec.Schemas.ScheduledStatus alias Pleroma.Web.ApiSpec.Schemas.ScheduledStatus
alias Pleroma.Web.ApiSpec.Schemas.Status alias Pleroma.Web.ApiSpec.Schemas.Status
@ -349,10 +348,7 @@ def bookmarks_operation do
summary: "Bookmarked statuses", summary: "Bookmarked statuses",
description: "Statuses the user has bookmarked", description: "Statuses the user has bookmarked",
operationId: "StatusController.bookmarks", operationId: "StatusController.bookmarks",
parameters: [ parameters: pagination_params(),
Operation.parameter(:with_relationships, :query, BooleanLike, "Include relationships")
| pagination_params()
],
security: [%{"oAuth" => ["read:bookmarks"]}], security: [%{"oAuth" => ["read:bookmarks"]}],
responses: %{ responses: %{
200 => Operation.response("Array of Statuses", "application/json", array_of_statuses()) 200 => Operation.response("Array of Statuses", "application/json", array_of_statuses())

View file

@ -27,8 +27,7 @@ def home_operation do
local_param(), local_param(),
with_muted_param(), with_muted_param(),
exclude_visibilities_param(), exclude_visibilities_param(),
reply_visibility_param(), reply_visibility_param() | pagination_params()
with_relationships_param() | pagination_params()
], ],
operationId: "TimelineController.home", operationId: "TimelineController.home",
responses: %{ responses: %{
@ -63,8 +62,7 @@ def public_operation do
only_media_param(), only_media_param(),
with_muted_param(), with_muted_param(),
exclude_visibilities_param(), exclude_visibilities_param(),
reply_visibility_param(), reply_visibility_param() | pagination_params()
with_relationships_param() | pagination_params()
], ],
operationId: "TimelineController.public", operationId: "TimelineController.public",
responses: %{ responses: %{
@ -109,8 +107,7 @@ def hashtag_operation do
local_param(), local_param(),
only_media_param(), only_media_param(),
with_muted_param(), with_muted_param(),
exclude_visibilities_param(), exclude_visibilities_param() | pagination_params()
with_relationships_param() | pagination_params()
], ],
operationId: "TimelineController.hashtag", operationId: "TimelineController.hashtag",
responses: %{ responses: %{
@ -134,8 +131,7 @@ def list_operation do
required: true required: true
), ),
with_muted_param(), with_muted_param(),
exclude_visibilities_param(), exclude_visibilities_param() | pagination_params()
with_relationships_param() | pagination_params()
], ],
operationId: "TimelineController.list", operationId: "TimelineController.list",
responses: %{ responses: %{
@ -153,10 +149,6 @@ defp array_of_statuses do
} }
end end
defp with_relationships_param do
Operation.parameter(:with_relationships, :query, BooleanLike, "Include relationships")
end
defp local_param do defp local_param do
Operation.parameter( Operation.parameter(
:local, :local,

View file

@ -13,7 +13,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Attachment do
type: :object, type: :object,
requried: [:id, :url, :preview_url], requried: [:id, :url, :preview_url],
properties: %{ properties: %{
id: %Schema{type: :string}, id: %Schema{type: :string, description: "The ID of the attachment in the database."},
url: %Schema{ url: %Schema{
type: :string, type: :string,
format: :uri, format: :uri,

View file

@ -23,6 +23,7 @@ def handle_in("new_msg", %{"text" => text}, %{assigns: %{user_name: user_name}}
if String.length(text) in 1..Pleroma.Config.get([:instance, :chat_limit]) do if String.length(text) in 1..Pleroma.Config.get([:instance, :chat_limit]) do
author = User.get_cached_by_nickname(user_name) author = User.get_cached_by_nickname(user_name)
author = Pleroma.Web.MastodonAPI.AccountView.render("show.json", user: author) author = Pleroma.Web.MastodonAPI.AccountView.render("show.json", user: author)
message = ChatChannelState.add_message(%{text: text, author: author}) message = ChatChannelState.add_message(%{text: text, author: author})
broadcast!(socket, "new_msg", message) broadcast!(socket, "new_msg", message)

View file

@ -65,10 +65,21 @@ defp validate_chat_content_length(content, _) do
end end
def unblock(blocker, blocked) do def unblock(blocker, blocked) do
with %Activity{} = block <- Utils.fetch_latest_block(blocker, blocked), with {_, %Activity{} = block} <- {:fetch_block, Utils.fetch_latest_block(blocker, blocked)},
{:ok, unblock_data, _} <- Builder.undo(blocker, block), {:ok, unblock_data, _} <- Builder.undo(blocker, block),
{:ok, unblock, _} <- Pipeline.common_pipeline(unblock_data, local: true) do {:ok, unblock, _} <- Pipeline.common_pipeline(unblock_data, local: true) do
{:ok, unblock} {:ok, unblock}
else
{:fetch_block, nil} ->
if User.blocks?(blocker, blocked) do
User.unblock(blocker, blocked)
{:ok, :no_activity}
else
{:error, :not_blocking}
end
e ->
e
end end
end end

View file

@ -5,8 +5,6 @@
defmodule Pleroma.Web.ControllerHelper do defmodule Pleroma.Web.ControllerHelper do
use Pleroma.Web, :controller use Pleroma.Web, :controller
alias Pleroma.Config
# As in Mastodon API, per https://api.rubyonrails.org/classes/ActiveModel/Type/Boolean.html # As in Mastodon API, per https://api.rubyonrails.org/classes/ActiveModel/Type/Boolean.html
@falsy_param_values [false, 0, "0", "f", "F", "false", "False", "FALSE", "off", "OFF"] @falsy_param_values [false, 0, "0", "f", "F", "false", "False", "FALSE", "off", "OFF"]
@ -106,13 +104,16 @@ def put_if_exist(map, _key, nil), do: map
def put_if_exist(map, key, value), do: Map.put(map, key, value) def put_if_exist(map, key, value), do: Map.put(map, key, value)
@doc "Whether to skip rendering `[:account][:pleroma][:relationship]`for statuses/notifications" @doc """
def skip_relationships?(params) do Returns true if request specifies to include embedded relationships in account objects.
if Config.get([:extensions, :output_relationships_in_statuses_by_default]) do May only be used in selected account-related endpoints; has no effect for status- or
false notification-related endpoints.
else """
# BREAKING: older PleromaFE versions do not send this param but _do_ expect relationships. # Intended for PleromaFE: https://git.pleroma.social/pleroma/pleroma-fe/-/issues/838
not truthy_param?(params["with_relationships"]) def embed_relationships?(params) do
end # To do once OpenAPI transition mess is over: just `truthy_param?(params[:with_relationships])`
params
|> Map.get(:with_relationships, params["with_relationships"])
|> truthy_param?()
end end
end end

View file

@ -10,8 +10,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
add_link_headers: 2, add_link_headers: 2,
truthy_param?: 1, truthy_param?: 1,
assign_account_by_id: 2, assign_account_by_id: 2,
json_response: 3, embed_relationships?: 1,
skip_relationships?: 1 json_response: 3
] ]
alias Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug alias Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug
@ -247,8 +247,7 @@ def statuses(%{assigns: %{user: reading_user}} = conn, params) do
|> render("index.json", |> render("index.json",
activities: activities, activities: activities,
for: reading_user, for: reading_user,
as: :activity, as: :activity
skip_relationships: skip_relationships?(params)
) )
else else
_e -> render_error(conn, :not_found, "Can't find user") _e -> render_error(conn, :not_found, "Can't find user")
@ -271,7 +270,13 @@ def followers(%{assigns: %{user: for_user, account: user}} = conn, params) do
conn conn
|> add_link_headers(followers) |> add_link_headers(followers)
|> render("index.json", for: for_user, users: followers, as: :user) # https://git.pleroma.social/pleroma/pleroma-fe/-/issues/838#note_59223
|> render("index.json",
for: for_user,
users: followers,
as: :user,
embed_relationships: embed_relationships?(params)
)
end end
@doc "GET /api/v1/accounts/:id/following" @doc "GET /api/v1/accounts/:id/following"
@ -290,7 +295,13 @@ def following(%{assigns: %{user: for_user, account: user}} = conn, params) do
conn conn
|> add_link_headers(followers) |> add_link_headers(followers)
|> render("index.json", for: for_user, users: followers, as: :user) # https://git.pleroma.social/pleroma/pleroma-fe/-/issues/838#note_59223
|> render("index.json",
for: for_user,
users: followers,
as: :user,
embed_relationships: embed_relationships?(params)
)
end end
@doc "GET /api/v1/accounts/:id/lists" @doc "GET /api/v1/accounts/:id/lists"

View file

@ -11,17 +11,20 @@ defmodule Pleroma.Web.MastodonAPI.MediaController do
alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.ActivityPub
action_fallback(Pleroma.Web.MastodonAPI.FallbackController) action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
plug(Pleroma.Web.ApiSpec.CastAndValidate)
plug(:put_view, Pleroma.Web.MastodonAPI.StatusView) plug(:put_view, Pleroma.Web.MastodonAPI.StatusView)
plug(OAuthScopesPlug, %{scopes: ["write:media"]}) plug(OAuthScopesPlug, %{scopes: ["write:media"]})
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.MediaOperation
@doc "POST /api/v1/media" @doc "POST /api/v1/media"
def create(%{assigns: %{user: user}} = conn, %{"file" => file} = data) do def create(%{assigns: %{user: user}, body_params: %{file: file} = data} = conn, _) do
with {:ok, object} <- with {:ok, object} <-
ActivityPub.upload( ActivityPub.upload(
file, file,
actor: User.ap_id(user), actor: User.ap_id(user),
description: Map.get(data, "description") description: Map.get(data, :description)
) do ) do
attachment_data = Map.put(object.data, "id", object.id) attachment_data = Map.put(object.data, "id", object.id)
@ -29,9 +32,28 @@ def create(%{assigns: %{user: user}} = conn, %{"file" => file} = data) do
end end
end end
def create(_conn, _data), do: {:error, :bad_request}
@doc "POST /api/v2/media"
def create2(%{assigns: %{user: user}, body_params: %{file: file} = data} = conn, _) do
with {:ok, object} <-
ActivityPub.upload(
file,
actor: User.ap_id(user),
description: Map.get(data, :description)
) do
attachment_data = Map.put(object.data, "id", object.id)
conn
|> put_status(202)
|> render("attachment.json", %{attachment: attachment_data})
end
end
def create2(_conn, _data), do: {:error, :bad_request}
@doc "PUT /api/v1/media/:id" @doc "PUT /api/v1/media/:id"
def update(%{assigns: %{user: user}} = conn, %{"id" => id, "description" => description}) def update(%{assigns: %{user: user}, body_params: %{description: description}} = conn, %{id: id}) do
when is_binary(description) do
with %Object{} = object <- Object.get_by_id(id), with %Object{} = object <- Object.get_by_id(id),
true <- Object.authorize_mutation(object, user), true <- Object.authorize_mutation(object, user),
{:ok, %Object{data: data}} <- Object.update_data(object, %{"name" => description}) do {:ok, %Object{data: data}} <- Object.update_data(object, %{"name" => description}) do
@ -41,5 +63,16 @@ def update(%{assigns: %{user: user}} = conn, %{"id" => id, "description" => desc
end end
end end
def update(_conn, _data), do: {:error, :bad_request} def update(conn, data), do: show(conn, data)
@doc "GET /api/v1/media/:id"
def show(conn, %{id: id}) do
with %Object{data: data, id: object_id} <- Object.get_by_id(id) do
attachment_data = Map.put(data, "id", object_id)
render(conn, "attachment.json", %{attachment: attachment_data})
end
end
def get_media(_conn, _data), do: {:error, :bad_request}
end end

View file

@ -5,7 +5,7 @@
defmodule Pleroma.Web.MastodonAPI.NotificationController do defmodule Pleroma.Web.MastodonAPI.NotificationController do
use Pleroma.Web, :controller use Pleroma.Web, :controller
import Pleroma.Web.ControllerHelper, only: [add_link_headers: 2, skip_relationships?: 1] import Pleroma.Web.ControllerHelper, only: [add_link_headers: 2]
alias Pleroma.Notification alias Pleroma.Notification
alias Pleroma.Plugs.OAuthScopesPlug alias Pleroma.Plugs.OAuthScopesPlug
@ -50,8 +50,7 @@ def index(%{assigns: %{user: user}} = conn, params) do
|> add_link_headers(notifications) |> add_link_headers(notifications)
|> render("index.json", |> render("index.json",
notifications: notifications, notifications: notifications,
for: user, for: user
skip_relationships: skip_relationships?(params)
) )
end end

View file

@ -5,14 +5,13 @@
defmodule Pleroma.Web.MastodonAPI.SearchController do defmodule Pleroma.Web.MastodonAPI.SearchController do
use Pleroma.Web, :controller use Pleroma.Web, :controller
import Pleroma.Web.ControllerHelper, only: [skip_relationships?: 1]
alias Pleroma.Activity alias Pleroma.Activity
alias Pleroma.Plugs.OAuthScopesPlug alias Pleroma.Plugs.OAuthScopesPlug
alias Pleroma.Plugs.RateLimiter alias Pleroma.Plugs.RateLimiter
alias Pleroma.Repo alias Pleroma.Repo
alias Pleroma.User alias Pleroma.User
alias Pleroma.Web alias Pleroma.Web
alias Pleroma.Web.ControllerHelper
alias Pleroma.Web.MastodonAPI.AccountView alias Pleroma.Web.MastodonAPI.AccountView
alias Pleroma.Web.MastodonAPI.StatusView alias Pleroma.Web.MastodonAPI.StatusView
@ -34,7 +33,11 @@ def account_search(%{assigns: %{user: user}} = conn, %{q: query} = params) do
conn conn
|> put_view(AccountView) |> put_view(AccountView)
|> render("index.json", users: accounts, for: user, as: :user) |> render("index.json",
users: accounts,
for: user,
as: :user
)
end end
def search2(conn, params), do: do_search(:v2, conn, params) def search2(conn, params), do: do_search(:v2, conn, params)
@ -71,13 +74,13 @@ defp do_search(version, %{assigns: %{user: user}} = conn, %{q: query} = params)
defp search_options(params, user) do defp search_options(params, user) do
[ [
skip_relationships: skip_relationships?(params),
resolve: params[:resolve], resolve: params[:resolve],
following: params[:following], following: params[:following],
limit: params[:limit], limit: params[:limit],
offset: params[:offset], offset: params[:offset],
type: params[:type], type: params[:type],
author: get_author(params), author: get_author(params),
embed_relationships: ControllerHelper.embed_relationships?(params),
for_user: user for_user: user
] ]
|> Enum.filter(&elem(&1, 1)) |> Enum.filter(&elem(&1, 1))
@ -90,7 +93,7 @@ defp resource_search(_, "accounts", query, options) do
users: accounts, users: accounts,
for: options[:for_user], for: options[:for_user],
as: :user, as: :user,
skip_relationships: false embed_relationships: options[:embed_relationships]
) )
end end
@ -100,8 +103,7 @@ defp resource_search(_, "statuses", query, options) do
StatusView.render("index.json", StatusView.render("index.json",
activities: statuses, activities: statuses,
for: options[:for_user], for: options[:for_user],
as: :activity, as: :activity
skip_relationships: options[:skip_relationships]
) )
end end

View file

@ -6,7 +6,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
use Pleroma.Web, :controller use Pleroma.Web, :controller
import Pleroma.Web.ControllerHelper, import Pleroma.Web.ControllerHelper,
only: [try_render: 3, add_link_headers: 2, skip_relationships?: 1] only: [try_render: 3, add_link_headers: 2]
require Ecto.Query require Ecto.Query
@ -105,7 +105,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
`ids` query param is required `ids` query param is required
""" """
def index(%{assigns: %{user: user}} = conn, %{ids: ids} = params) do def index(%{assigns: %{user: user}} = conn, %{ids: ids} = _params) do
limit = 100 limit = 100
activities = activities =
@ -117,8 +117,7 @@ def index(%{assigns: %{user: user}} = conn, %{ids: ids} = params) do
render(conn, "index.json", render(conn, "index.json",
activities: activities, activities: activities,
for: user, for: user,
as: :activity, as: :activity
skip_relationships: skip_relationships?(params)
) )
end end
@ -383,8 +382,7 @@ def favourites(%{assigns: %{user: %User{} = user}} = conn, params) do
|> render("index.json", |> render("index.json",
activities: activities, activities: activities,
for: user, for: user,
as: :activity, as: :activity
skip_relationships: skip_relationships?(params)
) )
end end
@ -406,8 +404,7 @@ def bookmarks(%{assigns: %{user: user}} = conn, params) do
|> render("index.json", |> render("index.json",
activities: activities, activities: activities,
for: user, for: user,
as: :activity, as: :activity
skip_relationships: skip_relationships?(params)
) )
end end
end end

View file

@ -6,7 +6,7 @@ defmodule Pleroma.Web.MastodonAPI.TimelineController do
use Pleroma.Web, :controller use Pleroma.Web, :controller
import Pleroma.Web.ControllerHelper, import Pleroma.Web.ControllerHelper,
only: [add_link_headers: 2, add_link_headers: 3, skip_relationships?: 1] only: [add_link_headers: 2, add_link_headers: 3]
alias Pleroma.Pagination alias Pleroma.Pagination
alias Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug alias Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug
@ -63,8 +63,7 @@ def home(%{assigns: %{user: user}} = conn, params) do
|> render("index.json", |> render("index.json",
activities: activities, activities: activities,
for: user, for: user,
as: :activity, as: :activity
skip_relationships: skip_relationships?(params)
) )
end end
@ -88,8 +87,7 @@ def direct(%{assigns: %{user: user}} = conn, params) do
|> render("index.json", |> render("index.json",
activities: activities, activities: activities,
for: user, for: user,
as: :activity, as: :activity
skip_relationships: skip_relationships?(params)
) )
end end
@ -125,8 +123,7 @@ def public(%{assigns: %{user: user}} = conn, params) do
|> render("index.json", |> render("index.json",
activities: activities, activities: activities,
for: user, for: user,
as: :activity, as: :activity
skip_relationships: skip_relationships?(params)
) )
end end
end end
@ -173,8 +170,7 @@ def hashtag(%{assigns: %{user: user}} = conn, params) do
|> render("index.json", |> render("index.json",
activities: activities, activities: activities,
for: user, for: user,
as: :activity, as: :activity
skip_relationships: skip_relationships?(params)
) )
end end
@ -203,8 +199,7 @@ def list(%{assigns: %{user: user}} = conn, %{list_id: id} = params) do
render(conn, "index.json", render(conn, "index.json",
activities: activities, activities: activities,
for: user, for: user,
as: :activity, as: :activity
skip_relationships: skip_relationships?(params)
) )
else else
_e -> render_error(conn, :forbidden, "Error.") _e -> render_error(conn, :forbidden, "Error.")

View file

@ -15,13 +15,12 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
def render("index.json", %{users: users} = opts) do def render("index.json", %{users: users} = opts) do
reading_user = opts[:for] reading_user = opts[:for]
# Note: :skip_relationships option is currently intentionally not supported for accounts
relationships_opt = relationships_opt =
cond do cond do
Map.has_key?(opts, :relationships) -> Map.has_key?(opts, :relationships) ->
opts[:relationships] opts[:relationships]
is_nil(reading_user) -> is_nil(reading_user) || !opts[:embed_relationships] ->
UserRelationship.view_relationships_option(nil, []) UserRelationship.view_relationships_option(nil, [])
true -> true ->
@ -193,14 +192,14 @@ defp do_render("show.json", %{user: user} = opts) do
end) end)
relationship = relationship =
if opts[:skip_relationships] do if opts[:embed_relationships] do
%{}
else
render("relationship.json", %{ render("relationship.json", %{
user: opts[:for], user: opts[:for],
target: user, target: user,
relationships: opts[:relationships] relationships: opts[:relationships]
}) })
else
%{}
end end
%{ %{

View file

@ -53,9 +53,7 @@ def render("index.json", %{notifications: notifications, for: reading_user} = op
|> Enum.filter(& &1) |> Enum.filter(& &1)
|> Kernel.++(move_activities_targets) |> Kernel.++(move_activities_targets)
UserRelationship.view_relationships_option(reading_user, actors, UserRelationship.view_relationships_option(reading_user, actors, subset: :source_mutes)
source_mutes_only: opts[:skip_relationships]
)
end end
opts = opts =
@ -99,15 +97,13 @@ def render(
type type
end end
render_opts = %{ # Note: :relationships contain user mutes (needed for :muted flag in :status)
relationships: opts[:relationships], status_render_opts = %{relationships: opts[:relationships]}
skip_relationships: opts[:skip_relationships]
}
with %{id: _} = account <- with %{id: _} = account <-
AccountView.render( AccountView.render(
"show.json", "show.json",
Map.merge(render_opts, %{user: actor, for: reading_user}) %{user: actor, for: reading_user}
) do ) do
response = %{ response = %{
id: to_string(notification.id), id: to_string(notification.id),
@ -121,25 +117,24 @@ def render(
case mastodon_type do case mastodon_type do
"mention" -> "mention" ->
put_status(response, activity, reading_user, render_opts) put_status(response, activity, reading_user, status_render_opts)
"favourite" -> "favourite" ->
put_status(response, parent_activity_fn.(), reading_user, render_opts) put_status(response, parent_activity_fn.(), reading_user, status_render_opts)
"reblog" -> "reblog" ->
put_status(response, parent_activity_fn.(), reading_user, render_opts) put_status(response, parent_activity_fn.(), reading_user, status_render_opts)
"move" -> "move" ->
# Note: :skip_relationships option being applied to _account_ rendering (here) put_target(response, activity, reading_user, %{})
put_target(response, activity, reading_user, render_opts)
"pleroma:emoji_reaction" -> "pleroma:emoji_reaction" ->
response response
|> put_status(parent_activity_fn.(), reading_user, render_opts) |> put_status(parent_activity_fn.(), reading_user, status_render_opts)
|> put_emoji(activity) |> put_emoji(activity)
"pleroma:chat_mention" -> "pleroma:chat_mention" ->
put_chat_message(response, activity, reading_user, render_opts) put_chat_message(response, activity, reading_user, status_render_opts)
type when type in ["follow", "follow_request"] -> type when type in ["follow", "follow_request"] ->
response response

View file

@ -107,9 +107,7 @@ def render("index.json", opts) do
|> Enum.map(&get_user(&1.data["actor"], false)) |> Enum.map(&get_user(&1.data["actor"], false))
|> Enum.filter(& &1) |> Enum.filter(& &1)
UserRelationship.view_relationships_option(reading_user, actors, UserRelationship.view_relationships_option(reading_user, actors, subset: :source_mutes)
source_mutes_only: opts[:skip_relationships]
)
end end
opts = opts =
@ -162,9 +160,7 @@ def render(
account: account:
AccountView.render("show.json", %{ AccountView.render("show.json", %{
user: user, user: user,
for: opts[:for], for: opts[:for]
relationships: opts[:relationships],
skip_relationships: opts[:skip_relationships]
}), }),
in_reply_to_id: nil, in_reply_to_id: nil,
in_reply_to_account_id: nil, in_reply_to_account_id: nil,
@ -330,9 +326,7 @@ def render("show.json", %{activity: %{data: %{"object" => _object}} = activity}
account: account:
AccountView.render("show.json", %{ AccountView.render("show.json", %{
user: user, user: user,
for: opts[:for], for: opts[:for]
relationships: opts[:relationships],
skip_relationships: opts[:skip_relationships]
}), }),
in_reply_to_id: reply_to && to_string(reply_to.id), in_reply_to_id: reply_to && to_string(reply_to.id),
in_reply_to_account_id: reply_to_user && to_string(reply_to_user.id), in_reply_to_account_id: reply_to_user && to_string(reply_to_user.id),

View file

@ -6,7 +6,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountController do
use Pleroma.Web, :controller use Pleroma.Web, :controller
import Pleroma.Web.ControllerHelper, import Pleroma.Web.ControllerHelper,
only: [json_response: 3, add_link_headers: 2, assign_account_by_id: 2, skip_relationships?: 1] only: [json_response: 3, add_link_headers: 2, assign_account_by_id: 2]
alias Ecto.Changeset alias Ecto.Changeset
alias Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug alias Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug
@ -149,8 +149,7 @@ def favourites(%{assigns: %{user: for_user, account: user}} = conn, params) do
|> render("index.json", |> render("index.json",
activities: activities, activities: activities,
for: for_user, for: for_user,
as: :activity, as: :activity
skip_relationships: skip_relationships?(params)
) )
end end

View file

@ -5,7 +5,7 @@
defmodule Pleroma.Web.PleromaAPI.PleromaAPIController do defmodule Pleroma.Web.PleromaAPI.PleromaAPIController do
use Pleroma.Web, :controller use Pleroma.Web, :controller
import Pleroma.Web.ControllerHelper, only: [add_link_headers: 2, skip_relationships?: 1] import Pleroma.Web.ControllerHelper, only: [add_link_headers: 2]
alias Pleroma.Activity alias Pleroma.Activity
alias Pleroma.Conversation.Participation alias Pleroma.Conversation.Participation
@ -69,7 +69,12 @@ def emoji_reactions_by(%{assigns: %{user: user}} = conn, %{"id" => activity_id}
%{ %{
name: emoji, name: emoji,
count: length(users), count: length(users),
accounts: AccountView.render("index.json", %{users: users, for: user, as: :user}), accounts:
AccountView.render("index.json", %{
users: users,
for: user,
as: :user
}),
me: !!(user && user.ap_id in user_ap_ids) me: !!(user && user.ap_id in user_ap_ids)
} }
end end
@ -145,8 +150,7 @@ def conversation_statuses(
|> render("index.json", |> render("index.json",
activities: activities, activities: activities,
for: user, for: user,
as: :activity, as: :activity
skip_relationships: skip_relationships?(params)
) )
else else
_error -> _error ->
@ -201,7 +205,7 @@ def mark_notifications_as_read(%{assigns: %{user: user}} = conn, %{"id" => notif
end end
end end
def mark_notifications_as_read(%{assigns: %{user: user}} = conn, %{"max_id" => max_id} = params) do def mark_notifications_as_read(%{assigns: %{user: user}} = conn, %{"max_id" => max_id}) do
with notifications <- Notification.set_read_up_to(user, max_id) do with notifications <- Notification.set_read_up_to(user, max_id) do
notifications = Enum.take(notifications, 80) notifications = Enum.take(notifications, 80)
@ -209,8 +213,7 @@ def mark_notifications_as_read(%{assigns: %{user: user}} = conn, %{"max_id" => m
|> put_view(NotificationView) |> put_view(NotificationView)
|> render("index.json", |> render("index.json",
notifications: notifications, notifications: notifications,
for: user, for: user
skip_relationships: skip_relationships?(params)
) )
end end
end end

View file

@ -415,6 +415,7 @@ defmodule Pleroma.Web.Router do
post("/markers", MarkerController, :upsert) post("/markers", MarkerController, :upsert)
post("/media", MediaController, :create) post("/media", MediaController, :create)
get("/media/:id", MediaController, :show)
put("/media/:id", MediaController, :update) put("/media/:id", MediaController, :update)
get("/notifications", NotificationController, :index) get("/notifications", NotificationController, :index)
@ -509,6 +510,8 @@ defmodule Pleroma.Web.Router do
scope "/api/v2", Pleroma.Web.MastodonAPI do scope "/api/v2", Pleroma.Web.MastodonAPI do
pipe_through(:api) pipe_through(:api)
get("/search", SearchController, :search2) get("/search", SearchController, :search2)
post("/media", MediaController, :create2)
end end
scope "/api", Pleroma.Web do scope "/api", Pleroma.Web do

View file

@ -0,0 +1,578 @@
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-05-15 09:37+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Automatically generated\n"
"Language-Team: none\n"
"Language: nl\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Translate Toolkit 2.5.1\n"
## This file is a PO Template file.
##
## `msgid`s here are often extracted from source code.
## Add new translations manually only if they're dynamic
## translations that can't be statically extracted.
##
## Run `mix gettext.extract` to bring this file up to
## date. Leave `msgstr`s empty as changing them here as no
## effect: edit them in PO (`.po`) files instead.
## From Ecto.Changeset.cast/4
msgid "can't be blank"
msgstr ""
## From Ecto.Changeset.unique_constraint/3
msgid "has already been taken"
msgstr ""
## From Ecto.Changeset.put_change/3
msgid "is invalid"
msgstr ""
## From Ecto.Changeset.validate_format/3
msgid "has invalid format"
msgstr ""
## From Ecto.Changeset.validate_subset/3
msgid "has an invalid entry"
msgstr ""
## From Ecto.Changeset.validate_exclusion/3
msgid "is reserved"
msgstr ""
## From Ecto.Changeset.validate_confirmation/3
msgid "does not match confirmation"
msgstr ""
## From Ecto.Changeset.no_assoc_constraint/3
msgid "is still associated with this entry"
msgstr ""
msgid "are still associated with this entry"
msgstr ""
## From Ecto.Changeset.validate_length/3
msgid "should be %{count} character(s)"
msgid_plural "should be %{count} character(s)"
msgstr[0] ""
msgstr[1] ""
msgid "should have %{count} item(s)"
msgid_plural "should have %{count} item(s)"
msgstr[0] ""
msgstr[1] ""
msgid "should be at least %{count} character(s)"
msgid_plural "should be at least %{count} character(s)"
msgstr[0] ""
msgstr[1] ""
msgid "should have at least %{count} item(s)"
msgid_plural "should have at least %{count} item(s)"
msgstr[0] ""
msgstr[1] ""
msgid "should be at most %{count} character(s)"
msgid_plural "should be at most %{count} character(s)"
msgstr[0] ""
msgstr[1] ""
msgid "should have at most %{count} item(s)"
msgid_plural "should have at most %{count} item(s)"
msgstr[0] ""
msgstr[1] ""
## From Ecto.Changeset.validate_number/3
msgid "must be less than %{number}"
msgstr ""
msgid "must be greater than %{number}"
msgstr ""
msgid "must be less than or equal to %{number}"
msgstr ""
msgid "must be greater than or equal to %{number}"
msgstr ""
msgid "must be equal to %{number}"
msgstr ""
#: lib/pleroma/web/common_api/common_api.ex:421
#, elixir-format
msgid "Account not found"
msgstr ""
#: lib/pleroma/web/common_api/common_api.ex:249
#, elixir-format
msgid "Already voted"
msgstr ""
#: lib/pleroma/web/oauth/oauth_controller.ex:360
#, elixir-format
msgid "Bad request"
msgstr ""
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:425
#, elixir-format
msgid "Can't delete object"
msgstr ""
#: lib/pleroma/web/mastodon_api/controllers/status_controller.ex:196
#, elixir-format
msgid "Can't delete this post"
msgstr ""
#: lib/pleroma/web/controller_helper.ex:95
#: lib/pleroma/web/controller_helper.ex:101
#, elixir-format
msgid "Can't display this activity"
msgstr ""
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:227
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:254
#, elixir-format
msgid "Can't find user"
msgstr ""
#: lib/pleroma/web/pleroma_api/controllers/account_controller.ex:114
#, elixir-format
msgid "Can't get favorites"
msgstr ""
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:437
#, elixir-format
msgid "Can't like object"
msgstr ""
#: lib/pleroma/web/common_api/utils.ex:556
#, elixir-format
msgid "Cannot post an empty status without attachments"
msgstr ""
#: lib/pleroma/web/common_api/utils.ex:504
#, elixir-format
msgid "Comment must be up to %{max_size} characters"
msgstr ""
#: lib/pleroma/config/config_db.ex:222
#, elixir-format
msgid "Config with params %{params} not found"
msgstr ""
#: lib/pleroma/web/common_api/common_api.ex:95
#, elixir-format
msgid "Could not delete"
msgstr ""
#: lib/pleroma/web/common_api/common_api.ex:141
#, elixir-format
msgid "Could not favorite"
msgstr ""
#: lib/pleroma/web/common_api/common_api.ex:370
#, elixir-format
msgid "Could not pin"
msgstr ""
#: lib/pleroma/web/common_api/common_api.ex:112
#, elixir-format
msgid "Could not repeat"
msgstr ""
#: lib/pleroma/web/common_api/common_api.ex:188
#, elixir-format
msgid "Could not unfavorite"
msgstr ""
#: lib/pleroma/web/common_api/common_api.ex:380
#, elixir-format
msgid "Could not unpin"
msgstr ""
#: lib/pleroma/web/common_api/common_api.ex:126
#, elixir-format
msgid "Could not unrepeat"
msgstr ""
#: lib/pleroma/web/common_api/common_api.ex:428
#: lib/pleroma/web/common_api/common_api.ex:437
#, elixir-format
msgid "Could not update state"
msgstr ""
#: lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:202
#, elixir-format
msgid "Error."
msgstr ""
#: lib/pleroma/web/twitter_api/twitter_api.ex:106
#, elixir-format
msgid "Invalid CAPTCHA"
msgstr ""
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:117
#: lib/pleroma/web/oauth/oauth_controller.ex:569
#, elixir-format
msgid "Invalid credentials"
msgstr ""
#: lib/pleroma/plugs/ensure_authenticated_plug.ex:38
#, elixir-format
msgid "Invalid credentials."
msgstr ""
#: lib/pleroma/web/common_api/common_api.ex:265
#, elixir-format
msgid "Invalid indices"
msgstr ""
#: lib/pleroma/web/admin_api/admin_api_controller.ex:1147
#, elixir-format
msgid "Invalid parameters"
msgstr ""
#: lib/pleroma/web/common_api/utils.ex:411
#, elixir-format
msgid "Invalid password."
msgstr ""
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:187
#, elixir-format
msgid "Invalid request"
msgstr ""
#: lib/pleroma/web/twitter_api/twitter_api.ex:109
#, elixir-format
msgid "Kocaptcha service unavailable"
msgstr ""
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:113
#, elixir-format
msgid "Missing parameters"
msgstr ""
#: lib/pleroma/web/common_api/utils.ex:540
#, elixir-format
msgid "No such conversation"
msgstr ""
#: lib/pleroma/web/admin_api/admin_api_controller.ex:439
#: lib/pleroma/web/admin_api/admin_api_controller.ex:465 lib/pleroma/web/admin_api/admin_api_controller.ex:507
#, elixir-format
msgid "No such permission_group"
msgstr ""
#: lib/pleroma/plugs/uploaded_media.ex:74
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:485 lib/pleroma/web/admin_api/admin_api_controller.ex:1135
#: lib/pleroma/web/feed/user_controller.ex:73 lib/pleroma/web/ostatus/ostatus_controller.ex:143
#, elixir-format
msgid "Not found"
msgstr ""
#: lib/pleroma/web/common_api/common_api.ex:241
#, elixir-format
msgid "Poll's author can't vote"
msgstr ""
#: lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:20
#: lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:37 lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:49
#: lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:50 lib/pleroma/web/mastodon_api/controllers/status_controller.ex:290
#: lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex:71
#, elixir-format
msgid "Record not found"
msgstr ""
#: lib/pleroma/web/admin_api/admin_api_controller.ex:1153
#: lib/pleroma/web/feed/user_controller.ex:79 lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:32
#: lib/pleroma/web/ostatus/ostatus_controller.ex:149
#, elixir-format
msgid "Something went wrong"
msgstr ""
#: lib/pleroma/web/common_api/activity_draft.ex:107
#, elixir-format
msgid "The message visibility must be direct"
msgstr ""
#: lib/pleroma/web/common_api/utils.ex:566
#, elixir-format
msgid "The status is over the character limit"
msgstr ""
#: lib/pleroma/plugs/ensure_public_or_authenticated_plug.ex:31
#, elixir-format
msgid "This resource requires authentication."
msgstr ""
#: lib/pleroma/plugs/rate_limiter/rate_limiter.ex:206
#, elixir-format
msgid "Throttled"
msgstr ""
#: lib/pleroma/web/common_api/common_api.ex:266
#, elixir-format
msgid "Too many choices"
msgstr ""
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:442
#, elixir-format
msgid "Unhandled activity type"
msgstr ""
#: lib/pleroma/web/admin_api/admin_api_controller.ex:536
#, elixir-format
msgid "You can't revoke your own admin status."
msgstr ""
#: lib/pleroma/web/oauth/oauth_controller.ex:218
#: lib/pleroma/web/oauth/oauth_controller.ex:309
#, elixir-format
msgid "Your account is currently disabled"
msgstr ""
#: lib/pleroma/web/oauth/oauth_controller.ex:180
#: lib/pleroma/web/oauth/oauth_controller.ex:332
#, elixir-format
msgid "Your login is missing a confirmed e-mail address"
msgstr ""
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:389
#, elixir-format
msgid "can't read inbox of %{nickname} as %{as_nickname}"
msgstr ""
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:472
#, elixir-format
msgid "can't update outbox of %{nickname} as %{as_nickname}"
msgstr ""
#: lib/pleroma/web/common_api/common_api.ex:388
#, elixir-format
msgid "conversation is already muted"
msgstr ""
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:316
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:491
#, elixir-format
msgid "error"
msgstr ""
#: lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex:29
#, elixir-format
msgid "mascots can only be images"
msgstr ""
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:60
#, elixir-format
msgid "not found"
msgstr ""
#: lib/pleroma/web/oauth/oauth_controller.ex:395
#, elixir-format
msgid "Bad OAuth request."
msgstr ""
#: lib/pleroma/web/twitter_api/twitter_api.ex:115
#, elixir-format
msgid "CAPTCHA already used"
msgstr ""
#: lib/pleroma/web/twitter_api/twitter_api.ex:112
#, elixir-format
msgid "CAPTCHA expired"
msgstr ""
#: lib/pleroma/plugs/uploaded_media.ex:55
#, elixir-format
msgid "Failed"
msgstr ""
#: lib/pleroma/web/oauth/oauth_controller.ex:411
#, elixir-format
msgid "Failed to authenticate: %{message}."
msgstr ""
#: lib/pleroma/web/oauth/oauth_controller.ex:442
#, elixir-format
msgid "Failed to set up user account."
msgstr ""
#: lib/pleroma/plugs/oauth_scopes_plug.ex:38
#, elixir-format
msgid "Insufficient permissions: %{permissions}."
msgstr ""
#: lib/pleroma/plugs/uploaded_media.ex:94
#, elixir-format
msgid "Internal Error"
msgstr ""
#: lib/pleroma/web/oauth/fallback_controller.ex:22
#: lib/pleroma/web/oauth/fallback_controller.ex:29
#, elixir-format
msgid "Invalid Username/Password"
msgstr ""
#: lib/pleroma/web/twitter_api/twitter_api.ex:118
#, elixir-format
msgid "Invalid answer data"
msgstr ""
#: lib/pleroma/web/nodeinfo/nodeinfo_controller.ex:128
#, elixir-format
msgid "Nodeinfo schema version not handled"
msgstr ""
#: lib/pleroma/web/oauth/oauth_controller.ex:169
#, elixir-format
msgid "This action is outside the authorized scopes"
msgstr ""
#: lib/pleroma/web/oauth/fallback_controller.ex:14
#, elixir-format
msgid "Unknown error, please check the details and try again."
msgstr ""
#: lib/pleroma/web/oauth/oauth_controller.ex:116
#: lib/pleroma/web/oauth/oauth_controller.ex:155
#, elixir-format
msgid "Unlisted redirect_uri."
msgstr ""
#: lib/pleroma/web/oauth/oauth_controller.ex:391
#, elixir-format
msgid "Unsupported OAuth provider: %{provider}."
msgstr ""
#: lib/pleroma/uploaders/uploader.ex:72
#, elixir-format
msgid "Uploader callback timeout"
msgstr ""
#: lib/pleroma/web/uploader_controller.ex:23
#, elixir-format
msgid "bad request"
msgstr ""
#: lib/pleroma/web/twitter_api/twitter_api.ex:103
#, elixir-format
msgid "CAPTCHA Error"
msgstr ""
#: lib/pleroma/web/common_api/common_api.ex:200
#, elixir-format
msgid "Could not add reaction emoji"
msgstr ""
#: lib/pleroma/web/common_api/common_api.ex:211
#, elixir-format
msgid "Could not remove reaction emoji"
msgstr ""
#: lib/pleroma/web/twitter_api/twitter_api.ex:129
#, elixir-format
msgid "Invalid CAPTCHA (Missing parameter: %{name})"
msgstr ""
#: lib/pleroma/web/mastodon_api/controllers/list_controller.ex:92
#, elixir-format
msgid "List not found"
msgstr ""
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:124
#, elixir-format
msgid "Missing parameter: %{name}"
msgstr ""
#: lib/pleroma/web/oauth/oauth_controller.ex:207
#: lib/pleroma/web/oauth/oauth_controller.ex:322
#, elixir-format
msgid "Password reset is required"
msgstr ""
#: lib/pleroma/tests/auth_test_controller.ex:9
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:6 lib/pleroma/web/admin_api/admin_api_controller.ex:6
#: lib/pleroma/web/controller_helper.ex:6 lib/pleroma/web/fallback_redirect_controller.ex:6
#: lib/pleroma/web/feed/tag_controller.ex:6 lib/pleroma/web/feed/user_controller.ex:6
#: lib/pleroma/web/mailer/subscription_controller.ex:2 lib/pleroma/web/masto_fe_controller.ex:6
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/app_controller.ex:6
#: lib/pleroma/web/mastodon_api/controllers/auth_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/conversation_controller.ex:6
#: lib/pleroma/web/mastodon_api/controllers/custom_emoji_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/domain_block_controller.ex:6
#: lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/filter_controller.ex:6
#: lib/pleroma/web/mastodon_api/controllers/follow_request_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/instance_controller.ex:6
#: lib/pleroma/web/mastodon_api/controllers/list_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/marker_controller.ex:6
#: lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex:14 lib/pleroma/web/mastodon_api/controllers/media_controller.ex:6
#: lib/pleroma/web/mastodon_api/controllers/notification_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:6
#: lib/pleroma/web/mastodon_api/controllers/report_controller.ex:8 lib/pleroma/web/mastodon_api/controllers/scheduled_activity_controller.ex:6
#: lib/pleroma/web/mastodon_api/controllers/search_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/status_controller.ex:6
#: lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex:7 lib/pleroma/web/mastodon_api/controllers/suggestion_controller.ex:6
#: lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:6 lib/pleroma/web/media_proxy/media_proxy_controller.ex:6
#: lib/pleroma/web/mongooseim/mongoose_im_controller.ex:6 lib/pleroma/web/nodeinfo/nodeinfo_controller.ex:6
#: lib/pleroma/web/oauth/fallback_controller.ex:6 lib/pleroma/web/oauth/mfa_controller.ex:10
#: lib/pleroma/web/oauth/oauth_controller.ex:6 lib/pleroma/web/ostatus/ostatus_controller.ex:6
#: lib/pleroma/web/pleroma_api/controllers/account_controller.ex:6 lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex:2
#: lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex:6 lib/pleroma/web/pleroma_api/controllers/pleroma_api_controller.ex:6
#: lib/pleroma/web/pleroma_api/controllers/scrobble_controller.ex:6
#: lib/pleroma/web/pleroma_api/controllers/two_factor_authentication_controller.ex:7 lib/pleroma/web/static_fe/static_fe_controller.ex:6
#: lib/pleroma/web/twitter_api/controllers/password_controller.ex:10 lib/pleroma/web/twitter_api/controllers/remote_follow_controller.ex:6
#: lib/pleroma/web/twitter_api/controllers/util_controller.ex:6 lib/pleroma/web/twitter_api/twitter_api_controller.ex:6
#: lib/pleroma/web/uploader_controller.ex:6 lib/pleroma/web/web_finger/web_finger_controller.ex:6
#, elixir-format
msgid "Security violation: OAuth scopes check was neither handled nor explicitly skipped."
msgstr ""
#: lib/pleroma/plugs/ensure_authenticated_plug.ex:28
#, elixir-format
msgid "Two-factor authentication enabled, you must use a access token."
msgstr ""
#: lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex:210
#, elixir-format
msgid "Unexpected error occurred while adding file to pack."
msgstr ""
#: lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex:138
#, elixir-format
msgid "Unexpected error occurred while creating pack."
msgstr ""
#: lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex:278
#, elixir-format
msgid "Unexpected error occurred while removing file from pack."
msgstr ""
#: lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex:250
#, elixir-format
msgid "Unexpected error occurred while updating file in pack."
msgstr ""
#: lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex:179
#, elixir-format
msgid "Unexpected error occurred while updating pack metadata."
msgstr ""
#: lib/pleroma/plugs/user_is_admin_plug.ex:40
#, elixir-format
msgid "User is not an admin or OAuth admin scope is not granted."
msgstr ""
#: lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex:61
#, elixir-format
msgid "Web push subscription is disabled on this Pleroma instance"
msgstr ""
#: lib/pleroma/web/admin_api/admin_api_controller.ex:502
#, elixir-format
msgid "You can't revoke your own admin/moderator status."
msgstr ""
#: lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:105
#, elixir-format
msgid "authorization required for timeline view"
msgstr ""

View file

@ -3,8 +3,8 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-05-13 16:37+0000\n" "POT-Creation-Date: 2020-05-13 16:37+0000\n"
"PO-Revision-Date: 2020-05-14 14:37+0000\n" "PO-Revision-Date: 2020-05-16 17:13+0000\n"
"Last-Translator: Michał Sidor <pleromeme@meekchopp.es>\n" "Last-Translator: Jędrzej Tomaszewski <jederow@hotmail.com>\n"
"Language-Team: Polish <https://translate.pleroma.social/projects/pleroma/" "Language-Team: Polish <https://translate.pleroma.social/projects/pleroma/"
"pleroma/pl/>\n" "pleroma/pl/>\n"
"Language: pl\n" "Language: pl\n"
@ -46,7 +46,7 @@ msgstr "ma niepoprawny wpis"
## From Ecto.Changeset.validate_exclusion/3 ## From Ecto.Changeset.validate_exclusion/3
msgid "is reserved" msgid "is reserved"
msgstr "" msgstr "jest zarezerwowany"
## From Ecto.Changeset.validate_confirmation/3 ## From Ecto.Changeset.validate_confirmation/3
msgid "does not match confirmation" msgid "does not match confirmation"
@ -54,17 +54,17 @@ msgstr ""
## From Ecto.Changeset.no_assoc_constraint/3 ## From Ecto.Changeset.no_assoc_constraint/3
msgid "is still associated with this entry" msgid "is still associated with this entry"
msgstr "" msgstr "jest wciąż powiązane z tym wpisem"
msgid "are still associated with this entry" msgid "are still associated with this entry"
msgstr "" msgstr "są wciąż powiązane z tym wpisem"
## From Ecto.Changeset.validate_length/3 ## From Ecto.Changeset.validate_length/3
msgid "should be %{count} character(s)" msgid "should be %{count} character(s)"
msgid_plural "should be %{count} character(s)" msgid_plural "should be %{count} character(s)"
msgstr[0] "" msgstr[0] "powinno mieć %{count} znak"
msgstr[1] "" msgstr[1] "powinno mieć %{count} znaki"
msgstr[2] "" msgstr[2] "powinno mieć %{count} znaków"
msgid "should have %{count} item(s)" msgid "should have %{count} item(s)"
msgid_plural "should have %{count} item(s)" msgid_plural "should have %{count} item(s)"

View file

@ -1 +1 @@
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1,user-scalable=no"><title>Pleroma</title><!--server-generated-meta--><link rel=icon type=image/png href=/favicon.png><link href=/static/css/vendors~app.18fea621d430000acc27.css rel=stylesheet><link href=/static/css/app.613cef07981cd95ccceb.css rel=stylesheet><link href=/static/fontello.1588947937982.css rel=stylesheet></head><body class=hidden><noscript>To use Pleroma, please enable JavaScript.</noscript><div id=app></div><script type=text/javascript src=/static/js/vendors~app.561a1c605d1dfb0e6f74.js></script><script type=text/javascript src=/static/js/app.996428ccaaaa7f28cb8d.js></script></body></html> <!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1,user-scalable=no"><title>Pleroma</title><!--server-generated-meta--><link rel=icon type=image/png href=/favicon.png><link href=/static/css/vendors~app.18fea621d430000acc27.css rel=stylesheet><link href=/static/css/app.613cef07981cd95ccceb.css rel=stylesheet><link href=/static/fontello.1589385935077.css rel=stylesheet></head><body class=hidden><noscript>To use Pleroma, please enable JavaScript.</noscript><div id=app></div><script type=text/javascript src=/static/js/vendors~app.561a1c605d1dfb0e6f74.js></script><script type=text/javascript src=/static/js/app.838ffa9aecf210c7d744.js></script></body></html>

View file

@ -1,23 +1,28 @@
{ {
"theme": "pleroma-dark",
"background": "/static/aurora_borealis.jpg",
"logo": "/static/logo.png",
"logoMask": true,
"logoMargin": ".1em",
"redirectRootNoLogin": "/main/all",
"redirectRootLogin": "/main/friends",
"showInstanceSpecificPanel": false,
"collapseMessageWithSubject": false,
"scopeCopy": true,
"subjectLineBehavior": "email",
"postContentType": "text/plain",
"alwaysShowSubjectInput": true, "alwaysShowSubjectInput": true,
"background": "/static/aurora_borealis.jpg",
"collapseMessageWithSubject": false,
"disableChat": false,
"greentext": false,
"hideFilteredStatuses": false,
"hideMutedPosts": false,
"hidePostStats": false, "hidePostStats": false,
"hideSitename": false,
"hideUserStats": false, "hideUserStats": false,
"loginMethod": "password", "loginMethod": "password",
"webPushNotifications": false, "logo": "/static/logo.png",
"logoMargin": ".1em",
"logoMask": true,
"minimalScopesMode": false,
"noAttachmentLinks": false, "noAttachmentLinks": false,
"nsfwCensorImage": "", "nsfwCensorImage": "",
"postContentType": "text/plain",
"redirectRootLogin": "/main/friends",
"redirectRootNoLogin": "/main/all",
"scopeCopy": true,
"showFeaturesPanel": true, "showFeaturesPanel": true,
"minimalScopesMode": false "showInstanceSpecificPanel": false,
"subjectLineBehavior": "email",
"theme": "pleroma-dark",
"webPushNotifications": false
} }

View file

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

View file

@ -1,11 +1,11 @@
@font-face { @font-face {
font-family: "Icons"; font-family: "Icons";
src: url("./font/fontello.1588947937982.eot"); src: url("./font/fontello.1589385935077.eot");
src: url("./font/fontello.1588947937982.eot") format("embedded-opentype"), src: url("./font/fontello.1589385935077.eot") format("embedded-opentype"),
url("./font/fontello.1588947937982.woff2") format("woff2"), url("./font/fontello.1589385935077.woff2") format("woff2"),
url("./font/fontello.1588947937982.woff") format("woff"), url("./font/fontello.1589385935077.woff") format("woff"),
url("./font/fontello.1588947937982.ttf") format("truetype"), url("./font/fontello.1589385935077.ttf") format("truetype"),
url("./font/fontello.1588947937982.svg") format("svg"); url("./font/fontello.1589385935077.svg") format("svg");
font-weight: normal; font-weight: normal;
font-style: normal; font-style: normal;
} }

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

@ -1,4 +1,4 @@
var serviceWorkerOption = {"assets":["/static/fontello.1588947937982.css","/static/font/fontello.1588947937982.eot","/static/font/fontello.1588947937982.svg","/static/font/fontello.1588947937982.ttf","/static/font/fontello.1588947937982.woff","/static/font/fontello.1588947937982.woff2","/static/img/nsfw.74818f9.png","/static/css/app.613cef07981cd95ccceb.css","/static/js/app.996428ccaaaa7f28cb8d.js","/static/css/vendors~app.18fea621d430000acc27.css","/static/js/vendors~app.561a1c605d1dfb0e6f74.js","/static/js/2.18e4adec273c4ce867a8.js"]}; var serviceWorkerOption = {"assets":["/static/fontello.1589385935077.css","/static/font/fontello.1589385935077.eot","/static/font/fontello.1589385935077.svg","/static/font/fontello.1589385935077.ttf","/static/font/fontello.1589385935077.woff","/static/font/fontello.1589385935077.woff2","/static/img/nsfw.74818f9.png","/static/css/app.613cef07981cd95ccceb.css","/static/js/app.838ffa9aecf210c7d744.js","/static/css/vendors~app.18fea621d430000acc27.css","/static/js/vendors~app.561a1c605d1dfb0e6f74.js","/static/js/2.18e4adec273c4ce867a8.js"]};
!function(e){var n={};function t(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}t.m=e,t.c=n,t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{enumerable:!0,get:r})},t.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.t=function(e,n){if(1&n&&(e=t(e)),8&n)return e;if(4&n&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(t.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&n&&"string"!=typeof e)for(var o in e)t.d(r,o,function(n){return e[n]}.bind(null,o));return r},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},t.p="/",t(t.s=1)}([function(e,n){ !function(e){var n={};function t(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}t.m=e,t.c=n,t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{enumerable:!0,get:r})},t.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.t=function(e,n){if(1&n&&(e=t(e)),8&n)return e;if(4&n&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(t.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&n&&"string"!=typeof e)for(var o in e)t.d(r,o,function(n){return e[n]}.bind(null,o));return r},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},t.p="/",t(t.s=1)}([function(e,n){
/*! /*!

View file

@ -476,6 +476,14 @@ test "simple keyword" do
assert ConfigDB.from_binary(binary) == [key: "value"] assert ConfigDB.from_binary(binary) == [key: "value"]
end end
test "keyword with partial_chain key" do
binary =
ConfigDB.transform([%{"tuple" => [":partial_chain", "&:hackney_connect.partial_chain/1"]}])
assert binary == :erlang.term_to_binary(partial_chain: &:hackney_connect.partial_chain/1)
assert ConfigDB.from_binary(binary) == [partial_chain: &:hackney_connect.partial_chain/1]
end
test "keyword" do test "keyword" do
binary = binary =
ConfigDB.transform([ ConfigDB.transform([

View file

@ -2509,6 +2509,7 @@ test "common config example", %{conn: conn} do
%{"tuple" => [":seconds_valid", 60]}, %{"tuple" => [":seconds_valid", 60]},
%{"tuple" => [":path", ""]}, %{"tuple" => [":path", ""]},
%{"tuple" => [":key1", nil]}, %{"tuple" => [":key1", nil]},
%{"tuple" => [":partial_chain", "&:hackney_connect.partial_chain/1"]},
%{"tuple" => [":regex1", "~r/https:\/\/example.com/"]}, %{"tuple" => [":regex1", "~r/https:\/\/example.com/"]},
%{"tuple" => [":regex2", "~r/https:\/\/example.com/u"]}, %{"tuple" => [":regex2", "~r/https:\/\/example.com/u"]},
%{"tuple" => [":regex3", "~r/https:\/\/example.com/i"]}, %{"tuple" => [":regex3", "~r/https:\/\/example.com/i"]},
@ -2532,6 +2533,7 @@ test "common config example", %{conn: conn} do
%{"tuple" => [":seconds_valid", 60]}, %{"tuple" => [":seconds_valid", 60]},
%{"tuple" => [":path", ""]}, %{"tuple" => [":path", ""]},
%{"tuple" => [":key1", nil]}, %{"tuple" => [":key1", nil]},
%{"tuple" => [":partial_chain", "&:hackney_connect.partial_chain/1"]},
%{"tuple" => [":regex1", "~r/https:\\/\\/example.com/"]}, %{"tuple" => [":regex1", "~r/https:\\/\\/example.com/"]},
%{"tuple" => [":regex2", "~r/https:\\/\\/example.com/u"]}, %{"tuple" => [":regex2", "~r/https:\\/\\/example.com/u"]},
%{"tuple" => [":regex3", "~r/https:\\/\\/example.com/i"]}, %{"tuple" => [":regex3", "~r/https:\\/\\/example.com/i"]},
@ -2544,6 +2546,7 @@ test "common config example", %{conn: conn} do
":seconds_valid", ":seconds_valid",
":path", ":path",
":key1", ":key1",
":partial_chain",
":regex1", ":regex1",
":regex2", ":regex2",
":regex3", ":regex3",

View file

@ -98,6 +98,18 @@ test "it reject messages over the local limit" do
end end
end end
describe "unblocking" do
test "it works even without an existing block activity" do
blocked = insert(:user)
blocker = insert(:user)
User.block(blocker, blocked)
assert User.blocks?(blocker, blocked)
assert {:ok, :no_activity} == CommonAPI.unblock(blocker, blocked)
refute User.blocks?(blocker, blocked)
end
end
describe "deletion" do describe "deletion" do
test "it works with pruned objects" do test "it works with pruned objects" do
user = insert(:user) user = insert(:user)

View file

@ -11,7 +11,7 @@ defmodule Pleroma.Web.MastodonAPI.MediaControllerTest do
setup do: oauth_access(["write:media"]) setup do: oauth_access(["write:media"])
describe "media upload" do describe "Upload media" do
setup do setup do
image = %Plug.Upload{ image = %Plug.Upload{
content_type: "image/jpg", content_type: "image/jpg",
@ -25,13 +25,14 @@ defmodule Pleroma.Web.MastodonAPI.MediaControllerTest do
setup do: clear_config([:media_proxy]) setup do: clear_config([:media_proxy])
setup do: clear_config([Pleroma.Upload]) setup do: clear_config([Pleroma.Upload])
test "returns uploaded image", %{conn: conn, image: image} do test "/api/v1/media", %{conn: conn, image: image} do
desc = "Description of the image" desc = "Description of the image"
media = media =
conn conn
|> put_req_header("content-type", "multipart/form-data")
|> post("/api/v1/media", %{"file" => image, "description" => desc}) |> post("/api/v1/media", %{"file" => image, "description" => desc})
|> json_response(:ok) |> json_response_and_validate_schema(:ok)
assert media["type"] == "image" assert media["type"] == "image"
assert media["description"] == desc assert media["description"] == desc
@ -40,9 +41,32 @@ test "returns uploaded image", %{conn: conn, image: image} do
object = Object.get_by_id(media["id"]) object = Object.get_by_id(media["id"])
assert object.data["actor"] == User.ap_id(conn.assigns[:user]) assert object.data["actor"] == User.ap_id(conn.assigns[:user])
end end
test "/api/v2/media", %{conn: conn, image: image} do
desc = "Description of the image"
response =
conn
|> put_req_header("content-type", "multipart/form-data")
|> post("/api/v2/media", %{"file" => image, "description" => desc})
|> json_response_and_validate_schema(202)
assert media_id = response["id"]
media =
conn
|> get("/api/v1/media/#{media_id}")
|> json_response_and_validate_schema(200)
assert media["type"] == "image"
assert media["description"] == desc
assert media["id"]
object = Object.get_by_id(media["id"])
assert object.data["actor"] == User.ap_id(conn.assigns[:user])
end
end end
describe "PUT /api/v1/media/:id" do describe "Update media description" do
setup %{user: actor} do setup %{user: actor} do
file = %Plug.Upload{ file = %Plug.Upload{
content_type: "image/jpg", content_type: "image/jpg",
@ -60,23 +84,45 @@ test "returns uploaded image", %{conn: conn, image: image} do
[object: object] [object: object]
end end
test "updates name of media", %{conn: conn, object: object} do test "/api/v1/media/:id good request", %{conn: conn, object: object} do
media = media =
conn conn
|> put_req_header("content-type", "multipart/form-data")
|> put("/api/v1/media/#{object.id}", %{"description" => "test-media"}) |> put("/api/v1/media/#{object.id}", %{"description" => "test-media"})
|> json_response(:ok) |> json_response_and_validate_schema(:ok)
assert media["description"] == "test-media" assert media["description"] == "test-media"
assert refresh_record(object).data["name"] == "test-media" assert refresh_record(object).data["name"] == "test-media"
end end
end
test "returns error when request is bad", %{conn: conn, object: object} do describe "Get media by id" do
setup %{user: actor} do
file = %Plug.Upload{
content_type: "image/jpg",
path: Path.absname("test/fixtures/image.jpg"),
filename: "an_image.jpg"
}
{:ok, %Object{} = object} =
ActivityPub.upload(
file,
actor: User.ap_id(actor),
description: "test-media"
)
[object: object]
end
test "/api/v1/media/:id", %{conn: conn, object: object} do
media = media =
conn conn
|> put("/api/v1/media/#{object.id}", %{}) |> get("/api/v1/media/#{object.id}")
|> json_response(400) |> json_response_and_validate_schema(:ok)
assert media == %{"error" => "bad_request"} assert media["description"] == "test-media"
assert media["type"] == "image"
assert media["id"]
end end
end end
end end

View file

@ -12,9 +12,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
import Pleroma.Factory import Pleroma.Factory
test "does NOT render account/pleroma/relationship if this is disabled by default" do test "does NOT render account/pleroma/relationship by default" do
clear_config([:extensions, :output_relationships_in_statuses_by_default], false)
%{user: user, conn: conn} = oauth_access(["read:notifications"]) %{user: user, conn: conn} = oauth_access(["read:notifications"])
other_user = insert(:user) other_user = insert(:user)

View file

@ -1176,7 +1176,7 @@ test "replaces missing description with an empty string", %{conn: conn, user: us
end end
test "bookmarks" do test "bookmarks" do
bookmarks_uri = "/api/v1/bookmarks?with_relationships=true" bookmarks_uri = "/api/v1/bookmarks"
%{conn: conn} = oauth_access(["write:bookmarks", "read:bookmarks"]) %{conn: conn} = oauth_access(["write:bookmarks", "read:bookmarks"])
author = insert(:user) author = insert(:user)

View file

@ -20,12 +20,10 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
describe "home" do describe "home" do
setup do: oauth_access(["read:statuses"]) setup do: oauth_access(["read:statuses"])
test "does NOT render account/pleroma/relationship if this is disabled by default", %{ test "does NOT embed account/pleroma/relationship in statuses", %{
user: user, user: user,
conn: conn conn: conn
} do } do
clear_config([:extensions, :output_relationships_in_statuses_by_default], false)
other_user = insert(:user) other_user = insert(:user)
{:ok, _} = CommonAPI.post(other_user, %{status: "hi @#{user.nickname}"}) {:ok, _} = CommonAPI.post(other_user, %{status: "hi @#{user.nickname}"})
@ -41,75 +39,6 @@ test "does NOT render account/pleroma/relationship if this is disabled by defaul
end) end)
end end
test "the home timeline", %{user: user, conn: conn} do
uri = "/api/v1/timelines/home?with_relationships=1"
following = insert(:user, nickname: "followed")
third_user = insert(:user, nickname: "repeated")
{:ok, _activity} = CommonAPI.post(following, %{status: "post"})
{:ok, activity} = CommonAPI.post(third_user, %{status: "repeated post"})
{:ok, _, _} = CommonAPI.repeat(activity.id, following)
# This one should not show up in the TL
{:ok, _activity} = CommonAPI.post_chat_message(third_user, user, ":gun:")
ret_conn = get(conn, uri)
assert Enum.empty?(json_response_and_validate_schema(ret_conn, :ok))
{:ok, _user} = User.follow(user, following)
ret_conn = get(conn, uri)
assert [
%{
"reblog" => %{
"content" => "repeated post",
"account" => %{
"pleroma" => %{
"relationship" => %{"following" => false, "followed_by" => false}
}
}
},
"account" => %{"pleroma" => %{"relationship" => %{"following" => true}}}
},
%{
"content" => "post",
"account" => %{
"acct" => "followed",
"pleroma" => %{"relationship" => %{"following" => true}}
}
}
] = json_response_and_validate_schema(ret_conn, :ok)
{:ok, _user} = User.follow(third_user, user)
ret_conn = get(conn, uri)
assert [
%{
"reblog" => %{
"content" => "repeated post",
"account" => %{
"acct" => "repeated",
"pleroma" => %{
"relationship" => %{"following" => false, "followed_by" => true}
}
}
},
"account" => %{"pleroma" => %{"relationship" => %{"following" => true}}}
},
%{
"content" => "post",
"account" => %{
"acct" => "followed",
"pleroma" => %{"relationship" => %{"following" => true}}
}
}
] = json_response_and_validate_schema(ret_conn, :ok)
end
test "the home timeline when the direct messages are excluded", %{user: user, conn: conn} do test "the home timeline when the direct messages are excluded", %{user: user, conn: conn} do
{:ok, public_activity} = CommonAPI.post(user, %{status: ".", visibility: "public"}) {:ok, public_activity} = CommonAPI.post(user, %{status: ".", visibility: "public"})
{:ok, direct_activity} = CommonAPI.post(user, %{status: ".", visibility: "direct"}) {:ok, direct_activity} = CommonAPI.post(user, %{status: ".", visibility: "direct"})

View file

@ -304,83 +304,6 @@ test "represent a relationship for the user with a pending follow request" do
end end
end end
test "represent an embedded relationship" do
user =
insert(:user, %{
follower_count: 0,
note_count: 5,
actor_type: "Service",
nickname: "shp@shitposter.club",
inserted_at: ~N[2017-08-15 15:47:06.597036]
})
other_user = insert(:user)
{:ok, other_user} = User.follow(other_user, user)
{:ok, _user_relationship} = User.block(other_user, user)
{:ok, _} = User.follow(insert(:user), user)
expected = %{
id: to_string(user.id),
username: "shp",
acct: user.nickname,
display_name: user.name,
locked: false,
created_at: "2017-08-15T15:47:06.000Z",
followers_count: 1,
following_count: 0,
statuses_count: 5,
note: user.bio,
url: user.ap_id,
avatar: "http://localhost:4001/images/avi.png",
avatar_static: "http://localhost:4001/images/avi.png",
header: "http://localhost:4001/images/banner.png",
header_static: "http://localhost:4001/images/banner.png",
emojis: [],
fields: [],
bot: true,
source: %{
note: user.bio,
sensitive: false,
pleroma: %{
actor_type: "Service",
discoverable: false
},
fields: []
},
pleroma: %{
ap_id: user.ap_id,
background_image: nil,
confirmation_pending: false,
tags: [],
is_admin: false,
is_moderator: false,
hide_favorites: true,
hide_followers: false,
hide_follows: false,
hide_followers_count: false,
hide_follows_count: false,
relationship: %{
id: to_string(user.id),
following: false,
followed_by: false,
blocking: true,
blocked_by: false,
subscribing: false,
muting: false,
muting_notifications: false,
requested: false,
domain_blocking: false,
showing_reblogs: true,
endorsed: false
},
skip_thread_containment: false
}
}
assert expected ==
AccountView.render("show.json", %{user: refresh_record(user), for: other_user})
end
test "returns the settings store if the requesting user is the represented user and it's requested specifically" do test "returns the settings store if the requesting user is the represented user and it's requested specifically" do
user = insert(:user, pleroma_settings_store: %{fe: "test"}) user = insert(:user, pleroma_settings_store: %{fe: "test"})

View file

@ -68,7 +68,11 @@ test "Mention notification" do
id: to_string(notification.id), id: to_string(notification.id),
pleroma: %{is_seen: false}, pleroma: %{is_seen: false},
type: "mention", type: "mention",
account: AccountView.render("show.json", %{user: user, for: mentioned_user}), account:
AccountView.render("show.json", %{
user: user,
for: mentioned_user
}),
status: StatusView.render("show.json", %{activity: activity, for: mentioned_user}), status: StatusView.render("show.json", %{activity: activity, for: mentioned_user}),
created_at: Utils.to_masto_date(notification.inserted_at) created_at: Utils.to_masto_date(notification.inserted_at)
} }

View file

@ -576,7 +576,7 @@ test "a rich media card with all relevant data renders correctly" do
end end
end end
test "embeds a relationship in the account" do test "does not embed a relationship in the account" do
user = insert(:user) user = insert(:user)
other_user = insert(:user) other_user = insert(:user)
@ -587,13 +587,11 @@ test "embeds a relationship in the account" do
result = StatusView.render("show.json", %{activity: activity, for: other_user}) result = StatusView.render("show.json", %{activity: activity, for: other_user})
assert result[:account][:pleroma][:relationship] == assert result[:account][:pleroma][:relationship] == %{}
AccountView.render("relationship.json", %{user: other_user, target: user})
assert_schema(result, "Status", Pleroma.Web.ApiSpec.spec()) assert_schema(result, "Status", Pleroma.Web.ApiSpec.spec())
end end
test "embeds a relationship in the account in reposts" do test "does not embed a relationship in the account in reposts" do
user = insert(:user) user = insert(:user)
other_user = insert(:user) other_user = insert(:user)
@ -606,12 +604,8 @@ test "embeds a relationship in the account in reposts" do
result = StatusView.render("show.json", %{activity: activity, for: user}) result = StatusView.render("show.json", %{activity: activity, for: user})
assert result[:account][:pleroma][:relationship] == assert result[:account][:pleroma][:relationship] == %{}
AccountView.render("relationship.json", %{user: user, target: other_user}) assert result[:reblog][:account][:pleroma][:relationship] == %{}
assert result[:reblog][:account][:pleroma][:relationship] ==
AccountView.render("relationship.json", %{user: user, target: user})
assert_schema(result, "Status", Pleroma.Web.ApiSpec.spec()) assert_schema(result, "Status", Pleroma.Web.ApiSpec.spec())
end end