Merge branch 'develop' of git.pleroma.social:pleroma/pleroma into pleroma-double_mentions
This commit is contained in:
commit
55dd8ef1c7
20
CHANGELOG.md
20
CHANGELOG.md
@ -18,6 +18,26 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||
### Removed
|
||||
- BREAKING: Support for passwords generated with `crypt(3)` (Gnu Social migration artifact)
|
||||
|
||||
## 2.5.2
|
||||
|
||||
### Security
|
||||
- `/proxy` endpoint now sets a Content-Security-Policy (sandbox)
|
||||
- WebSocket endpoint now respects unauthenticated restrictions for streams of public posts
|
||||
- OEmbed HTML tags are now filtered
|
||||
|
||||
### Changed
|
||||
- docs: Be more explicit about the level of compatibility of OTP releases
|
||||
- Set default background worker timeout to 15 minutes
|
||||
|
||||
### Fixed
|
||||
- Atom/RSS formatting (HTML truncation, published, missing summary)
|
||||
- Remove `static_fe` pipeline for `/users/:nickname/feed`
|
||||
- Stop oban from retrying if validating errors occur when processing incoming data
|
||||
- Make sure object refetching as used by already received polls follows MRF rules
|
||||
|
||||
### Removed
|
||||
- BREAKING: Support for passwords generated with `crypt(3)` (Gnu Social migration artifact)
|
||||
|
||||
## 2.5.1
|
||||
|
||||
### Added
|
||||
|
1
changelog.d/3126.fix
Normal file
1
changelog.d/3126.fix
Normal file
@ -0,0 +1 @@
|
||||
MediaProxy responses now return a sandbox CSP header
|
0
changelog.d/3831.skip
Normal file
0
changelog.d/3831.skip
Normal file
1
changelog.d/3880.remove
Normal file
1
changelog.d/3880.remove
Normal file
@ -0,0 +1 @@
|
||||
Cleanup OStatus-era user upgrades and ap_enabled indicator
|
1
changelog.d/3884.fix
Normal file
1
changelog.d/3884.fix
Normal file
@ -0,0 +1 @@
|
||||
Allow non-HTTP(s) URIs in "url" fields for compatibility with "FEP-fffd: Proxy Objects"
|
1
changelog.d/3885.fix
Normal file
1
changelog.d/3885.fix
Normal file
@ -0,0 +1 @@
|
||||
Fix opengraph and twitter card meta tags
|
1
changelog.d/3891.fix
Normal file
1
changelog.d/3891.fix
Normal file
@ -0,0 +1 @@
|
||||
OEmbed HTML tags are now filtered
|
0
changelog.d/3893.skip
Normal file
0
changelog.d/3893.skip
Normal file
1
changelog.d/3896.add
Normal file
1
changelog.d/3896.add
Normal file
@ -0,0 +1 @@
|
||||
Validate Host header for Uploads and return a 302 if the base_url has changed
|
1
changelog.d/3897.add
Normal file
1
changelog.d/3897.add
Normal file
@ -0,0 +1 @@
|
||||
OnlyMedia Upload Filter
|
0
changelog.d/3899.skip
Normal file
0
changelog.d/3899.skip
Normal file
1
changelog.d/3901.security
Normal file
1
changelog.d/3901.security
Normal file
@ -0,0 +1 @@
|
||||
Preload: Make generated JSON html-safe. It already was html safe because it only consists of config data that is base64 encoded, but this will keep it safe it that ever changes.
|
0
changelog.d/3902.skip
Normal file
0
changelog.d/3902.skip
Normal file
0
changelog.d/distro-docs-elixir-1.11.skip
Normal file
0
changelog.d/distro-docs-elixir-1.11.skip
Normal file
@ -671,6 +671,12 @@ This filter reads the ImageDescription and iptc:Caption-Abstract fields with Exi
|
||||
|
||||
No specific configuration.
|
||||
|
||||
#### Pleroma.Upload.Filter.OnlyMedia
|
||||
|
||||
This filter rejects uploads that are not identified with Content-Type matching audio/\*, image/\*, or video/\*
|
||||
|
||||
No specific configuration.
|
||||
|
||||
#### Pleroma.Upload.Filter.Mogrify
|
||||
|
||||
* `args`: List of actions for the `mogrify` command like `"strip"` or `["strip", "auto-orient", {"implode", "1"}]`.
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
## Installation
|
||||
|
||||
This guide will assume you are on Debian 11 (“bullseye”) or later. This guide should also work with Ubuntu 18.04 (“Bionic Beaver”) and later. It also assumes that you have administrative rights, either as root or a user with [sudo permissions](https://www.digitalocean.com/community/tutorials/how-to-add-delete-and-grant-sudo-privileges-to-users-on-a-debian-vps). If you want to run this guide with root, ignore the `sudo` at the beginning of the lines, unless it calls a user like `sudo -Hu pleroma`; in this case, use `su <username> -s $SHELL -c 'command'` instead.
|
||||
This guide will assume you are on Debian 12 (“bookworm”) or later. This guide should also work with Ubuntu 22.04 (“jammy”) and later. It also assumes that you have administrative rights, either as root or a user with [sudo permissions](https://www.digitalocean.com/community/tutorials/how-to-add-delete-and-grant-sudo-privileges-to-users-on-a-debian-vps). If you want to run this guide with root, ignore the `sudo` at the beginning of the lines, unless it calls a user like `sudo -Hu pleroma`; in this case, use `su <username> -s $SHELL -c 'command'` instead.
|
||||
|
||||
{! backend/installation/generic_dependencies.include !}
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
## インストール
|
||||
|
||||
このガイドはDebian Stretchを利用することを想定しています。Ubuntu 16.04や18.04でもおそらく動作します。また、ユーザはrootもしくはsudoにより管理者権限を持っていることを前提とします。もし、以下の操作をrootユーザで行う場合は、 `sudo` を無視してください。ただし、`sudo -Hu pleroma` のようにユーザを指定している場合には `su <username> -s $SHELL -c 'command'` を代わりに使ってください。
|
||||
このガイドはDebian Bookwormを利用することを想定しています。Ubuntu 22.04でもおそらく動作します。また、ユーザはrootもしくはsudoにより管理者権限を持っていることを前提とします。もし、以下の操作をrootユーザで行う場合は、 `sudo` を無視してください。ただし、`sudo -Hu pleroma` のようにユーザを指定している場合には `su <username> -s $SHELL -c 'command'` を代わりに使ってください。
|
||||
|
||||
### 必要なソフトウェア
|
||||
|
||||
|
@ -0,0 +1,23 @@
|
||||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.EctoType.ActivityPub.ObjectValidators.BareUri do
|
||||
use Ecto.Type
|
||||
|
||||
def type, do: :string
|
||||
|
||||
def cast(uri) when is_binary(uri) do
|
||||
case URI.parse(uri) do
|
||||
%URI{scheme: nil} -> :error
|
||||
%URI{} -> {:ok, uri}
|
||||
_ -> :error
|
||||
end
|
||||
end
|
||||
|
||||
def cast(_), do: :error
|
||||
|
||||
def dump(data), do: {:ok, data}
|
||||
|
||||
def load(data), do: {:ok, data}
|
||||
end
|
@ -38,9 +38,9 @@ defmodule Pleroma.Upload.Filter do
|
||||
{:ok, :noop} ->
|
||||
filter(rest, upload)
|
||||
|
||||
error ->
|
||||
Logger.error("#{__MODULE__}: Filter #{filter} failed: #{inspect(error)}")
|
||||
error
|
||||
{:error, e} ->
|
||||
Logger.error("#{__MODULE__}: Filter #{filter} failed: #{inspect(e)}")
|
||||
{:error, e}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
20
lib/pleroma/upload/filter/only_media.ex
Normal file
20
lib/pleroma/upload/filter/only_media.ex
Normal file
@ -0,0 +1,20 @@
|
||||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Upload.Filter.OnlyMedia do
|
||||
@behaviour Pleroma.Upload.Filter
|
||||
alias Pleroma.Upload
|
||||
|
||||
def filter(%Upload{content_type: content_type}) do
|
||||
[type, _subtype] = String.split(content_type, "/")
|
||||
|
||||
if type in ["image", "video", "audio"] do
|
||||
{:ok, :noop}
|
||||
else
|
||||
{:error, "Disallowed content-type: #{content_type}"}
|
||||
end
|
||||
end
|
||||
|
||||
def filter(_), do: {:ok, :noop}
|
||||
end
|
@ -124,7 +124,6 @@ defmodule Pleroma.User do
|
||||
field(:domain_blocks, {:array, :string}, default: [])
|
||||
field(:is_active, :boolean, default: true)
|
||||
field(:no_rich_text, :boolean, default: false)
|
||||
field(:ap_enabled, :boolean, default: false)
|
||||
field(:is_moderator, :boolean, default: false)
|
||||
field(:is_admin, :boolean, default: false)
|
||||
field(:show_role, :boolean, default: true)
|
||||
@ -488,7 +487,6 @@ defmodule Pleroma.User do
|
||||
:nickname,
|
||||
:public_key,
|
||||
:avatar,
|
||||
:ap_enabled,
|
||||
:banner,
|
||||
:is_locked,
|
||||
:last_refreshed_at,
|
||||
@ -1061,11 +1059,7 @@ defmodule Pleroma.User do
|
||||
end
|
||||
|
||||
def maybe_direct_follow(%User{} = follower, %User{} = followed) do
|
||||
if not ap_enabled?(followed) do
|
||||
follow(follower, followed)
|
||||
else
|
||||
{:ok, follower, followed}
|
||||
end
|
||||
{:ok, follower, followed}
|
||||
end
|
||||
|
||||
@doc "A mass follow for local users. Respects blocks in both directions but does not create activities."
|
||||
@ -1898,7 +1892,6 @@ defmodule Pleroma.User do
|
||||
confirmation_token: nil,
|
||||
domain_blocks: [],
|
||||
is_active: false,
|
||||
ap_enabled: false,
|
||||
is_moderator: false,
|
||||
is_admin: false,
|
||||
mascot: nil,
|
||||
@ -2151,10 +2144,6 @@ defmodule Pleroma.User do
|
||||
end
|
||||
end
|
||||
|
||||
def ap_enabled?(%User{local: true}), do: true
|
||||
def ap_enabled?(%User{ap_enabled: ap_enabled}), do: ap_enabled
|
||||
def ap_enabled?(_), do: false
|
||||
|
||||
@doc "Gets or fetch a user by uri or nickname."
|
||||
@spec get_or_fetch(String.t()) :: {:ok, User.t()} | {:error, String.t()}
|
||||
def get_or_fetch("http://" <> _host = uri), do: get_or_fetch_by_ap_id(uri)
|
||||
|
@ -1547,7 +1547,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
||||
%{
|
||||
ap_id: data["id"],
|
||||
uri: get_actor_url(data["url"]),
|
||||
ap_enabled: true,
|
||||
banner: normalize_image(data["image"]),
|
||||
fields: fields,
|
||||
emoji: emojis,
|
||||
@ -1668,7 +1667,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
||||
end
|
||||
end
|
||||
|
||||
def fetch_and_prepare_user_from_ap_id(ap_id, additional \\ []) do
|
||||
defp fetch_and_prepare_user_from_ap_id(ap_id, additional) do
|
||||
with {:ok, data} <- Fetcher.fetch_and_contain_remote_object_from_id(ap_id),
|
||||
{:ok, data} <- user_data_from_user_object(data, additional) do
|
||||
{:ok, maybe_update_follow_information(data)}
|
||||
@ -1751,24 +1750,20 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
||||
def make_user_from_ap_id(ap_id, additional \\ []) do
|
||||
user = User.get_cached_by_ap_id(ap_id)
|
||||
|
||||
if user && !User.ap_enabled?(user) do
|
||||
Transmogrifier.upgrade_user_from_ap_id(ap_id)
|
||||
else
|
||||
with {:ok, data} <- fetch_and_prepare_user_from_ap_id(ap_id, additional) do
|
||||
{:ok, _pid} = Task.start(fn -> pinned_fetch_task(data) end)
|
||||
with {:ok, data} <- fetch_and_prepare_user_from_ap_id(ap_id, additional) do
|
||||
{:ok, _pid} = Task.start(fn -> pinned_fetch_task(data) end)
|
||||
|
||||
if user do
|
||||
user
|
||||
|> User.remote_user_changeset(data)
|
||||
|> User.update_and_set_cache()
|
||||
else
|
||||
maybe_handle_clashing_nickname(data)
|
||||
if user do
|
||||
user
|
||||
|> User.remote_user_changeset(data)
|
||||
|> User.update_and_set_cache()
|
||||
else
|
||||
maybe_handle_clashing_nickname(data)
|
||||
|
||||
data
|
||||
|> User.remote_user_changeset()
|
||||
|> Repo.insert()
|
||||
|> User.set_cache()
|
||||
end
|
||||
data
|
||||
|> User.remote_user_changeset()
|
||||
|> Repo.insert()
|
||||
|> User.set_cache()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -73,6 +73,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AddRemoveValidator do
|
||||
end
|
||||
|
||||
defp maybe_refetch_user(%User{ap_id: ap_id}) do
|
||||
Pleroma.Web.ActivityPub.Transmogrifier.upgrade_user_from_ap_id(ap_id)
|
||||
# Maybe it could use User.get_or_fetch_by_ap_id to avoid refreshing too often
|
||||
User.fetch_by_ap_id(ap_id)
|
||||
end
|
||||
end
|
||||
|
@ -58,7 +58,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonFields do
|
||||
field(:like_count, :integer, default: 0)
|
||||
field(:announcement_count, :integer, default: 0)
|
||||
field(:inReplyTo, ObjectValidators.ObjectID)
|
||||
field(:url, ObjectValidators.Uri)
|
||||
field(:url, ObjectValidators.BareUri)
|
||||
|
||||
field(:likes, {:array, ObjectValidators.ObjectID}, default: [])
|
||||
field(:announcements, {:array, ObjectValidators.ObjectID}, default: [])
|
||||
|
@ -199,7 +199,6 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
|
||||
|
||||
inboxes =
|
||||
recipients
|
||||
|> Enum.filter(&User.ap_enabled?/1)
|
||||
|> Enum.map(fn actor -> actor.inbox end)
|
||||
|> Enum.filter(fn inbox -> should_federate?(inbox, public) end)
|
||||
|> Instances.filter_reachable()
|
||||
@ -241,7 +240,6 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
|
||||
json = Jason.encode!(data)
|
||||
|
||||
recipients(actor, activity)
|
||||
|> Enum.filter(fn user -> User.ap_enabled?(user) end)
|
||||
|> Enum.map(fn %User{} = user ->
|
||||
determine_inbox(activity, user)
|
||||
end)
|
||||
|
@ -20,7 +20,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
||||
alias Pleroma.Web.ActivityPub.Utils
|
||||
alias Pleroma.Web.ActivityPub.Visibility
|
||||
alias Pleroma.Web.Federator
|
||||
alias Pleroma.Workers.TransmogrifierWorker
|
||||
|
||||
import Ecto.Query
|
||||
|
||||
@ -946,47 +945,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
||||
|
||||
defp strip_internal_tags(object), do: object
|
||||
|
||||
def perform(:user_upgrade, user) do
|
||||
# we pass a fake user so that the followers collection is stripped away
|
||||
old_follower_address = User.ap_followers(%User{nickname: user.nickname})
|
||||
|
||||
from(
|
||||
a in Activity,
|
||||
where: ^old_follower_address in a.recipients,
|
||||
update: [
|
||||
set: [
|
||||
recipients:
|
||||
fragment(
|
||||
"array_replace(?,?,?)",
|
||||
a.recipients,
|
||||
^old_follower_address,
|
||||
^user.follower_address
|
||||
)
|
||||
]
|
||||
]
|
||||
)
|
||||
|> Repo.update_all([])
|
||||
end
|
||||
|
||||
def upgrade_user_from_ap_id(ap_id) do
|
||||
with %User{local: false} = user <- User.get_cached_by_ap_id(ap_id),
|
||||
{:ok, data} <- ActivityPub.fetch_and_prepare_user_from_ap_id(ap_id),
|
||||
{:ok, user} <- update_user(user, data) do
|
||||
{:ok, _pid} = Task.start(fn -> ActivityPub.pinned_fetch_task(user) end)
|
||||
TransmogrifierWorker.enqueue("user_upgrade", %{"user_id" => user.id})
|
||||
{:ok, user}
|
||||
else
|
||||
%User{} = user -> {:ok, user}
|
||||
e -> e
|
||||
end
|
||||
end
|
||||
|
||||
defp update_user(user, data) do
|
||||
user
|
||||
|> User.remote_user_changeset(data)
|
||||
|> User.update_and_set_cache()
|
||||
end
|
||||
|
||||
def maybe_fix_user_url(%{"url" => url} = data) when is_map(url) do
|
||||
Map.put(data, "url", url["href"])
|
||||
end
|
||||
|
@ -6,7 +6,6 @@ defmodule Pleroma.Web.Federator do
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Object.Containment
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.ActivityPub.Transmogrifier
|
||||
alias Pleroma.Web.ActivityPub.Utils
|
||||
alias Pleroma.Web.Federator.Publisher
|
||||
@ -80,7 +79,7 @@ defmodule Pleroma.Web.Federator do
|
||||
|
||||
# NOTE: we use the actor ID to do the containment, this is fine because an
|
||||
# actor shouldn't be acting on objects outside their own AP server.
|
||||
with {_, {:ok, _user}} <- {:actor, ap_enabled_actor(actor)},
|
||||
with {_, {:ok, _user}} <- {:actor, User.get_or_fetch_by_ap_id(actor)},
|
||||
nil <- Activity.normalize(params["id"]),
|
||||
{_, :ok} <-
|
||||
{:correct_origin?, Containment.contain_origin_from_id(actor, params)},
|
||||
@ -110,14 +109,4 @@ defmodule Pleroma.Web.Federator do
|
||||
{:error, e}
|
||||
end
|
||||
end
|
||||
|
||||
def ap_enabled_actor(id) do
|
||||
user = User.get_cached_by_ap_id(id)
|
||||
|
||||
if User.ap_enabled?(user) do
|
||||
{:ok, user}
|
||||
else
|
||||
ActivityPub.make_user_from_ap_id(id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -12,6 +12,8 @@ defmodule Pleroma.Web.MediaProxy.MediaProxyController do
|
||||
alias Pleroma.Web.MediaProxy
|
||||
alias Plug.Conn
|
||||
|
||||
plug(:sandbox)
|
||||
|
||||
def remote(conn, %{"sig" => sig64, "url" => url64}) do
|
||||
with {_, true} <- {:enabled, MediaProxy.enabled?()},
|
||||
{:ok, url} <- MediaProxy.decode_url(sig64, url64),
|
||||
@ -202,4 +204,9 @@ defmodule Pleroma.Web.MediaProxy.MediaProxyController do
|
||||
defp media_proxy_opts do
|
||||
Config.get([:media_proxy, :proxy_opts], [])
|
||||
end
|
||||
|
||||
defp sandbox(conn, _params) do
|
||||
conn
|
||||
|> merge_resp_headers([{"content-security-policy", "sandbox;"}])
|
||||
end
|
||||
end
|
||||
|
@ -76,9 +76,10 @@ defmodule Pleroma.Web.Metadata.Providers.TwitterCard do
|
||||
{:meta, [name: "twitter:card", content: "summary_large_image"], []},
|
||||
{:meta,
|
||||
[
|
||||
name: "twitter:player",
|
||||
name: "twitter:image",
|
||||
content: MediaProxy.url(url["href"])
|
||||
], []}
|
||||
], []},
|
||||
{:meta, [name: "twitter:image:alt", content: truncate(attachment["name"])], []}
|
||||
| acc
|
||||
]
|
||||
|> maybe_add_dimensions(url)
|
||||
@ -130,4 +131,12 @@ defmodule Pleroma.Web.Metadata.Providers.TwitterCard do
|
||||
metadata
|
||||
end
|
||||
end
|
||||
|
||||
defp truncate(nil), do: ""
|
||||
|
||||
defp truncate(text) do
|
||||
# truncate to 420 characters
|
||||
# see https://developer.twitter.com/en/docs/twitter-for-websites/cards/overview/markup
|
||||
Pleroma.Formatter.truncate(text, 420)
|
||||
end
|
||||
end
|
||||
|
@ -46,12 +46,32 @@ defmodule Pleroma.Web.Plugs.UploadedMedia do
|
||||
|
||||
config = Pleroma.Config.get(Pleroma.Upload)
|
||||
|
||||
with uploader <- Keyword.fetch!(config, :uploader),
|
||||
%{scheme: media_scheme, host: media_host, port: media_port} =
|
||||
Pleroma.Upload.base_url() |> URI.parse()
|
||||
|
||||
with {:valid_host, true} <- {:valid_host, match?(^media_host, conn.host)},
|
||||
uploader <- Keyword.fetch!(config, :uploader),
|
||||
proxy_remote = Keyword.get(config, :proxy_remote, false),
|
||||
{:ok, get_method} <- uploader.get_file(file),
|
||||
false <- media_is_banned(conn, get_method) do
|
||||
get_media(conn, get_method, proxy_remote, opts)
|
||||
else
|
||||
{:valid_host, false} ->
|
||||
redirect_url =
|
||||
%URI{
|
||||
scheme: media_scheme,
|
||||
host: media_host,
|
||||
port: media_port,
|
||||
path: conn.request_path,
|
||||
query: conn.query_string
|
||||
}
|
||||
|> URI.to_string()
|
||||
|> String.trim_trailing("?")
|
||||
|
||||
conn
|
||||
|> Phoenix.Controller.redirect(external: redirect_url)
|
||||
|> halt()
|
||||
|
||||
_ ->
|
||||
conn
|
||||
|> send_resp(:internal_server_error, dgettext("errors", "Failed"))
|
||||
|
@ -11,7 +11,7 @@ defmodule Pleroma.Web.Preload do
|
||||
terms =
|
||||
params
|
||||
|> parser.generate_terms()
|
||||
|> Enum.map(fn {k, v} -> {k, Base.encode64(Jason.encode!(v))} end)
|
||||
|> Enum.map(fn {k, v} -> {k, Base.encode64(Jason.encode!(v, escape: :html_safe))} end)
|
||||
|> Enum.into(%{})
|
||||
|
||||
Map.merge(acc, terms)
|
||||
@ -19,7 +19,7 @@ defmodule Pleroma.Web.Preload do
|
||||
|
||||
rendered_html =
|
||||
preload_data
|
||||
|> Jason.encode!()
|
||||
|> Jason.encode!(escape: :html_safe)
|
||||
|> build_script_tag()
|
||||
|> HTML.safe_to_string()
|
||||
|
||||
|
@ -6,8 +6,8 @@ defmodule Pleroma.Web.RichMedia.Parsers.OEmbed do
|
||||
def parse(html, _data) do
|
||||
with elements = [_ | _] <- get_discovery_data(html),
|
||||
oembed_url when is_binary(oembed_url) <- get_oembed_url(elements),
|
||||
{:ok, oembed_data} <- get_oembed_data(oembed_url) do
|
||||
oembed_data
|
||||
{:ok, oembed_data = %{"html" => html}} <- get_oembed_data(oembed_url) do
|
||||
%{oembed_data | "html" => Pleroma.HTML.filter_tags(html)}
|
||||
else
|
||||
_e -> %{}
|
||||
end
|
||||
|
@ -25,7 +25,15 @@ defmodule Pleroma.Web.StaticFE.StaticFEController do
|
||||
true <- Visibility.is_public?(activity.object),
|
||||
{_, true} <- {:visible?, Visibility.visible_for_user?(activity, _reading_user = nil)},
|
||||
%User{} = user <- User.get_by_ap_id(activity.object.data["actor"]) do
|
||||
meta = Metadata.build_tags(%{activity_id: notice_id, object: activity.object, user: user})
|
||||
url = Helpers.url(conn) <> conn.request_path
|
||||
|
||||
meta =
|
||||
Metadata.build_tags(%{
|
||||
activity_id: notice_id,
|
||||
object: activity.object,
|
||||
user: user,
|
||||
url: url
|
||||
})
|
||||
|
||||
timeline =
|
||||
activity.object.data["context"]
|
||||
|
@ -25,6 +25,7 @@ defmodule Pleroma.Web.Streamer do
|
||||
def registry, do: @registry
|
||||
|
||||
@public_streams ["public", "public:local", "public:media", "public:local:media"]
|
||||
@local_streams ["public:local", "public:local:media"]
|
||||
@user_streams ["user", "user:notification", "direct", "user:pleroma_chat"]
|
||||
|
||||
@doc "Expands and authorizes a stream, and registers the process for streaming."
|
||||
@ -41,14 +42,37 @@ defmodule Pleroma.Web.Streamer do
|
||||
end
|
||||
end
|
||||
|
||||
defp can_access_stream(user, oauth_token, kind) do
|
||||
with {_, true} <- {:restrict?, Config.restrict_unauthenticated_access?(:timelines, kind)},
|
||||
{_, %User{id: user_id}, %Token{user_id: user_id}} <- {:user, user, oauth_token},
|
||||
{_, true} <-
|
||||
{:scopes,
|
||||
OAuthScopesPlug.filter_descendants(["read:statuses"], oauth_token.scopes) != []} do
|
||||
true
|
||||
else
|
||||
{:restrict?, _} ->
|
||||
true
|
||||
|
||||
_ ->
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
@doc "Expand and authorizes a stream"
|
||||
@spec get_topic(stream :: String.t(), User.t() | nil, Token.t() | nil, Map.t()) ::
|
||||
{:ok, topic :: String.t()} | {:error, :bad_topic}
|
||||
def get_topic(stream, user, oauth_token, params \\ %{})
|
||||
|
||||
# Allow all public steams.
|
||||
def get_topic(stream, _user, _oauth_token, _params) when stream in @public_streams do
|
||||
{:ok, stream}
|
||||
# Allow all public steams if the instance allows unauthenticated access.
|
||||
# Otherwise, only allow users with valid oauth tokens.
|
||||
def get_topic(stream, user, oauth_token, _params) when stream in @public_streams do
|
||||
kind = if stream in @local_streams, do: :local, else: :federated
|
||||
|
||||
if can_access_stream(user, oauth_token, kind) do
|
||||
{:ok, stream}
|
||||
else
|
||||
{:error, :unauthorized}
|
||||
end
|
||||
end
|
||||
|
||||
# Allow all hashtags streams.
|
||||
@ -57,12 +81,20 @@ defmodule Pleroma.Web.Streamer do
|
||||
end
|
||||
|
||||
# Allow remote instance streams.
|
||||
def get_topic("public:remote", _user, _oauth_token, %{"instance" => instance} = _params) do
|
||||
{:ok, "public:remote:" <> instance}
|
||||
def get_topic("public:remote", user, oauth_token, %{"instance" => instance} = _params) do
|
||||
if can_access_stream(user, oauth_token, :federated) do
|
||||
{:ok, "public:remote:" <> instance}
|
||||
else
|
||||
{:error, :unauthorized}
|
||||
end
|
||||
end
|
||||
|
||||
def get_topic("public:remote:media", _user, _oauth_token, %{"instance" => instance} = _params) do
|
||||
{:ok, "public:remote:media:" <> instance}
|
||||
def get_topic("public:remote:media", user, oauth_token, %{"instance" => instance} = _params) do
|
||||
if can_access_stream(user, oauth_token, :federated) do
|
||||
{:ok, "public:remote:media:" <> instance}
|
||||
else
|
||||
{:error, :unauthorized}
|
||||
end
|
||||
end
|
||||
|
||||
# Expand user streams.
|
||||
|
@ -1,18 +0,0 @@
|
||||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Workers.TransmogrifierWorker do
|
||||
alias Pleroma.User
|
||||
|
||||
use Pleroma.Workers.WorkerHelper, queue: "transmogrifier"
|
||||
|
||||
@impl Oban.Worker
|
||||
def perform(%Job{args: %{"op" => "user_upgrade", "user_id" => user_id}}) do
|
||||
user = User.get_cached_by_id(user_id)
|
||||
Pleroma.Web.ActivityPub.Transmogrifier.perform(:user_upgrade, user)
|
||||
end
|
||||
|
||||
@impl Oban.Worker
|
||||
def timeout(_job), do: :timer.seconds(5)
|
||||
end
|
9
mix.exs
9
mix.exs
@ -4,10 +4,10 @@ defmodule Pleroma.Mixfile do
|
||||
def project do
|
||||
[
|
||||
app: :pleroma,
|
||||
version: version("2.5.51"),
|
||||
version: version("2.5.52"),
|
||||
elixir: "~> 1.11",
|
||||
elixirc_paths: elixirc_paths(Mix.env()),
|
||||
compilers: [:phoenix, :gettext] ++ Mix.compilers(),
|
||||
compilers: [:phoenix] ++ Mix.compilers(),
|
||||
elixirc_options: [warnings_as_errors: warnings_as_errors()],
|
||||
xref: [exclude: [:eldap]],
|
||||
start_permanent: Mix.env() == :prod,
|
||||
@ -127,10 +127,7 @@ defmodule Pleroma.Mixfile do
|
||||
{:plug_cowboy, "~> 2.3"},
|
||||
# oban 2.14 requires Elixir 1.12+
|
||||
{:oban, "~> 2.13.4"},
|
||||
{:gettext,
|
||||
git: "https://github.com/tusooa/gettext.git",
|
||||
ref: "72fb2496b6c5280ed911bdc3756890e7f38a4808",
|
||||
override: true},
|
||||
{:gettext, "~> 0.20"},
|
||||
{:bcrypt_elixir, "~> 2.2"},
|
||||
{:trailing_format_plug, "~> 0.0.7"},
|
||||
{:fast_sanitize, "~> 0.2.0"},
|
||||
|
3
mix.lock
3
mix.lock
@ -42,6 +42,7 @@
|
||||
"ex_doc": {:hex, :ex_doc, "0.29.4", "6257ecbb20c7396b1fe5accd55b7b0d23f44b6aa18017b415cb4c2b91d997729", [:mix], [{:earmark_parser, "~> 1.4.31", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "2c6699a737ae46cb61e4ed012af931b57b699643b24dabe2400a8168414bc4f5"},
|
||||
"ex_machina": {:hex, :ex_machina, "2.7.0", "b792cc3127fd0680fecdb6299235b4727a4944a09ff0fa904cc639272cd92dc7", [:mix], [{:ecto, "~> 2.2 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_sql, "~> 3.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}], "hexpm", "419aa7a39bde11894c87a615c4ecaa52d8f107bbdd81d810465186f783245bf8"},
|
||||
"ex_syslogger": {:hex, :ex_syslogger, "1.5.2", "72b6aa2d47a236e999171f2e1ec18698740f40af0bd02c8c650bf5f1fd1bac79", [:mix], [{:poison, ">= 1.5.0", [hex: :poison, repo: "hexpm", optional: true]}, {:syslog, "~> 1.1.0", [hex: :syslog, repo: "hexpm", optional: false]}], "hexpm", "ab9fab4136dbc62651ec6f16fa4842f10cf02ab4433fa3d0976c01be99398399"},
|
||||
"expo": {:hex, :expo, "0.4.1", "1c61d18a5df197dfda38861673d392e642649a9cef7694d2f97a587b2cfb319b", [:mix], [], "hexpm", "2ff7ba7a798c8c543c12550fa0e2cbc81b95d4974c65855d8d15ba7b37a1ce47"},
|
||||
"fast_html": {:hex, :fast_html, "2.0.5", "c61760340606c1077ff1f196f17834056cb1dd3d5cb92a9f2cabf28bc6221c3c", [:make, :mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}], "hexpm", "605f4f4829443c14127694ebabb681778712ceecb4470ec32aa31012330e6506"},
|
||||
"fast_sanitize": {:hex, :fast_sanitize, "0.2.3", "67b93dfb34e302bef49fec3aaab74951e0f0602fd9fa99085987af05bd91c7a5", [:mix], [{:fast_html, "~> 2.0", [hex: :fast_html, repo: "hexpm", optional: false]}, {:plug, "~> 1.8", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "e8ad286d10d0386e15d67d0ee125245ebcfbc7d7290b08712ba9013c8c5e56e2"},
|
||||
"file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
|
||||
@ -49,7 +50,7 @@
|
||||
"flake_id": {:hex, :flake_id, "0.1.0", "7716b086d2e405d09b647121a166498a0d93d1a623bead243e1f74216079ccb3", [:mix], [{:base62, "~> 1.2", [hex: :base62, repo: "hexpm", optional: false]}, {:ecto, ">= 2.0.0", [hex: :ecto, repo: "hexpm", optional: true]}], "hexpm", "31fc8090fde1acd267c07c36ea7365b8604055f897d3a53dd967658c691bd827"},
|
||||
"floki": {:hex, :floki, "0.34.2", "5fad07ef153b3b8ec110b6b155ec3780c4b2c4906297d0b4be1a7162d04a7e02", [:mix], [], "hexpm", "26b9d50f0f01796bc6be611ca815c5e0de034d2128e39cc9702eee6b66a4d1c8"},
|
||||
"gen_smtp": {:hex, :gen_smtp, "0.15.0", "9f51960c17769b26833b50df0b96123605a8024738b62db747fece14eb2fbfcc", [:rebar3], [], "hexpm", "29bd14a88030980849c7ed2447b8db6d6c9278a28b11a44cafe41b791205440f"},
|
||||
"gettext": {:git, "https://github.com/tusooa/gettext.git", "72fb2496b6c5280ed911bdc3756890e7f38a4808", [ref: "72fb2496b6c5280ed911bdc3756890e7f38a4808"]},
|
||||
"gettext": {:hex, :gettext, "0.22.2", "6bfca374de34ecc913a28ba391ca184d88d77810a3e427afa8454a71a51341ac", [:mix], [{:expo, "~> 0.4.0", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "8a2d389673aea82d7eae387e6a2ccc12660610080ae7beb19452cfdc1ec30f60"},
|
||||
"gun": {:hex, :gun, "2.0.0", "2326bc0fd6d9cf628419708270d6fe8b02b8d002cf992e4165a77d997b1defd0", [:make, :rebar3], [{:cowlib, "2.12.0", [hex: :cowlib, repo: "hexpm", optional: false]}], "hexpm", "6613cb7c62930dc8d58263c44dda72f8556346ba88358fc929dcbc5f76d04569"},
|
||||
"hackney": {:hex, :hackney, "1.18.1", "f48bf88f521f2a229fc7bae88cf4f85adc9cd9bcf23b5dc8eb6a1788c662c4f6", [:rebar3], [{:certifi, "~>2.9.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~>6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~>1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.3.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~>1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "a4ecdaff44297e9b5894ae499e9a070ea1888c84afdd1fd9b7b2bc384950128e"},
|
||||
"hpax": {:hex, :hpax, "0.1.2", "09a75600d9d8bbd064cdd741f21fc06fc1f4cf3d0fcc335e5aa19be1a7235c84", [:mix], [], "hexpm", "2c87843d5a23f5f16748ebe77969880e29809580efdaccd615cd3bed628a8c13"},
|
||||
|
@ -9,7 +9,6 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Language: en_test\n"
|
||||
"Plural-Forms: nplurals=2\n"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:122
|
||||
|
@ -9,7 +9,6 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Language: en_test\n"
|
||||
"Plural-Forms: nplurals=2\n"
|
||||
|
||||
msgid "can't be blank"
|
||||
msgstr ""
|
||||
|
@ -9,7 +9,6 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Language: en_test\n"
|
||||
"Plural-Forms: nplurals=2\n"
|
||||
|
||||
msgid "eperm"
|
||||
msgstr ""
|
||||
|
@ -21,10 +21,6 @@ msgstr ""
|
||||
#~ ##
|
||||
#~ ## Use "mix gettext.extract --merge" or "mix gettext.merge"
|
||||
#~ ## to merge POT files into PO files.
|
||||
#~ msgid ""
|
||||
#~ msgstr ""
|
||||
#~ "Language: en_test\n"
|
||||
#~ "Plural-Forms: nplurals=2\n"
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/templates/twitter_api/remote_follow/follow.html.eex:9
|
||||
|
@ -9,7 +9,6 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Language: ru\n"
|
||||
"Plural-Forms: nplurals=3\n"
|
||||
|
||||
msgid "can't be blank"
|
||||
msgstr "не может быть пустым"
|
||||
|
@ -24,10 +24,6 @@ msgstr ""
|
||||
##
|
||||
## Use "mix gettext.extract --merge" or "mix gettext.merge"
|
||||
## to merge POT files into PO files.
|
||||
#~ msgid ""
|
||||
#~ msgstr ""
|
||||
#~ "Language: zh_Hans\n"
|
||||
#~ "Plural-Forms: nplurals=1\n"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/remote_follow/follow.html.eex:9
|
||||
#, elixir-format
|
||||
|
@ -0,0 +1,13 @@
|
||||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Repo.Migrations.RemoveUserApEnabled do
|
||||
use Ecto.Migration
|
||||
|
||||
def change do
|
||||
alter table(:users) do
|
||||
remove(:ap_enabled, :boolean, default: false, null: false)
|
||||
end
|
||||
end
|
||||
end
|
@ -0,0 +1,25 @@
|
||||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.EctoType.ActivityPub.ObjectValidators.BareUriTest do
|
||||
use Pleroma.DataCase, async: true
|
||||
|
||||
alias Pleroma.EctoType.ActivityPub.ObjectValidators.BareUri
|
||||
|
||||
test "diaspora://" do
|
||||
text = "diaspora://alice@fediverse.example/post/deadbeefdeadbeefdeadbeefdeadbeef"
|
||||
assert {:ok, text} = BareUri.cast(text)
|
||||
end
|
||||
|
||||
test "nostr:" do
|
||||
text = "nostr:note1gwdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"
|
||||
assert {:ok, text} = BareUri.cast(text)
|
||||
end
|
||||
|
||||
test "errors for non-URIs" do
|
||||
assert :error == SafeText.cast(1)
|
||||
assert :error == SafeText.cast("foo")
|
||||
assert :error == SafeText.cast("foo bar")
|
||||
end
|
||||
end
|
32
test/pleroma/upload/filter/only_media_test.exs
Normal file
32
test/pleroma/upload/filter/only_media_test.exs
Normal file
@ -0,0 +1,32 @@
|
||||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Upload.Filter.OnlyMediaTest do
|
||||
use Pleroma.DataCase, async: true
|
||||
|
||||
alias Pleroma.Upload
|
||||
alias Pleroma.Upload.Filter.OnlyMedia
|
||||
|
||||
test "Allows media Content-Type" do
|
||||
["audio/mpeg", "image/jpeg", "video/mp4"]
|
||||
|> Enum.each(fn type ->
|
||||
upload = %Upload{
|
||||
content_type: type
|
||||
}
|
||||
|
||||
assert {:ok, :noop} = OnlyMedia.filter(upload)
|
||||
end)
|
||||
end
|
||||
|
||||
test "Disallows non-media Content-Type" do
|
||||
["application/javascript", "application/pdf", "text/html"]
|
||||
|> Enum.each(fn type ->
|
||||
upload = %Upload{
|
||||
content_type: type
|
||||
}
|
||||
|
||||
assert {:error, _} = OnlyMedia.filter(upload)
|
||||
end)
|
||||
end
|
||||
end
|
@ -1844,7 +1844,6 @@ defmodule Pleroma.UserTest do
|
||||
confirmation_token: "qqqq",
|
||||
domain_blocks: ["lain.com"],
|
||||
is_active: false,
|
||||
ap_enabled: true,
|
||||
is_moderator: true,
|
||||
is_admin: true,
|
||||
mascot: %{"a" => "b"},
|
||||
@ -1885,7 +1884,6 @@ defmodule Pleroma.UserTest do
|
||||
confirmation_token: nil,
|
||||
domain_blocks: [],
|
||||
is_active: false,
|
||||
ap_enabled: false,
|
||||
is_moderator: false,
|
||||
is_admin: false,
|
||||
mascot: nil,
|
||||
@ -2473,8 +2471,7 @@ defmodule Pleroma.UserTest do
|
||||
insert(:user,
|
||||
local: false,
|
||||
follower_address: "http://localhost:4001/users/masto_closed/followers",
|
||||
following_address: "http://localhost:4001/users/masto_closed/following",
|
||||
ap_enabled: true
|
||||
following_address: "http://localhost:4001/users/masto_closed/following"
|
||||
)
|
||||
|
||||
assert other_user.following_count == 0
|
||||
@ -2495,8 +2492,7 @@ defmodule Pleroma.UserTest do
|
||||
insert(:user,
|
||||
local: false,
|
||||
follower_address: "http://localhost:4001/users/masto_closed/followers",
|
||||
following_address: "http://localhost:4001/users/masto_closed/following",
|
||||
ap_enabled: true
|
||||
following_address: "http://localhost:4001/users/masto_closed/following"
|
||||
)
|
||||
|
||||
assert other_user.following_count == 0
|
||||
@ -2517,8 +2513,7 @@ defmodule Pleroma.UserTest do
|
||||
insert(:user,
|
||||
local: false,
|
||||
follower_address: "http://localhost:4001/users/masto_closed/followers",
|
||||
following_address: "http://localhost:4001/users/masto_closed/following",
|
||||
ap_enabled: true
|
||||
following_address: "http://localhost:4001/users/masto_closed/following"
|
||||
)
|
||||
|
||||
assert other_user.following_count == 0
|
||||
|
@ -575,7 +575,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|
||||
user =
|
||||
insert(:user,
|
||||
ap_id: "https://mastodon.example.org/users/raymoo",
|
||||
ap_enabled: true,
|
||||
local: false,
|
||||
last_refreshed_at: nil
|
||||
)
|
||||
|
@ -174,7 +174,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
||||
{:ok, user} = ActivityPub.make_user_from_ap_id(user_id)
|
||||
assert user.ap_id == user_id
|
||||
assert user.nickname == "admin@mastodon.example.org"
|
||||
assert user.ap_enabled
|
||||
assert user.follower_address == "http://mastodon.example.org/users/admin/followers"
|
||||
end
|
||||
|
||||
|
@ -276,8 +276,7 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do
|
||||
follower =
|
||||
insert(:user, %{
|
||||
local: false,
|
||||
inbox: "https://domain.com/users/nick1/inbox",
|
||||
ap_enabled: true
|
||||
inbox: "https://domain.com/users/nick1/inbox"
|
||||
})
|
||||
|
||||
actor = insert(:user, follower_address: follower.ap_id)
|
||||
@ -313,8 +312,7 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do
|
||||
follower =
|
||||
insert(:user, %{
|
||||
local: false,
|
||||
inbox: "https://domain.com/users/nick1/inbox",
|
||||
ap_enabled: true
|
||||
inbox: "https://domain.com/users/nick1/inbox"
|
||||
})
|
||||
|
||||
actor = insert(:user, follower_address: follower.ap_id)
|
||||
@ -348,8 +346,7 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do
|
||||
follower =
|
||||
insert(:user, %{
|
||||
local: false,
|
||||
inbox: "https://domain.com/users/nick1/inbox",
|
||||
ap_enabled: true
|
||||
inbox: "https://domain.com/users/nick1/inbox"
|
||||
})
|
||||
|
||||
actor = insert(:user, follower_address: follower.ap_id)
|
||||
@ -382,15 +379,13 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do
|
||||
fetcher =
|
||||
insert(:user,
|
||||
local: false,
|
||||
inbox: "https://domain.com/users/nick1/inbox",
|
||||
ap_enabled: true
|
||||
inbox: "https://domain.com/users/nick1/inbox"
|
||||
)
|
||||
|
||||
another_fetcher =
|
||||
insert(:user,
|
||||
local: false,
|
||||
inbox: "https://domain2.com/users/nick1/inbox",
|
||||
ap_enabled: true
|
||||
inbox: "https://domain2.com/users/nick1/inbox"
|
||||
)
|
||||
|
||||
actor = insert(:user)
|
||||
|
@ -8,7 +8,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Tests.ObanHelpers
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.Transmogrifier
|
||||
alias Pleroma.Web.ActivityPub.Utils
|
||||
@ -353,69 +352,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
||||
end
|
||||
end
|
||||
|
||||
describe "user upgrade" do
|
||||
test "it upgrades a user to activitypub" do
|
||||
user =
|
||||
insert(:user, %{
|
||||
nickname: "rye@niu.moe",
|
||||
local: false,
|
||||
ap_id: "https://niu.moe/users/rye",
|
||||
follower_address: User.ap_followers(%User{nickname: "rye@niu.moe"})
|
||||
})
|
||||
|
||||
user_two = insert(:user)
|
||||
Pleroma.FollowingRelationship.follow(user_two, user, :follow_accept)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "test"})
|
||||
{:ok, unrelated_activity} = CommonAPI.post(user_two, %{status: "test"})
|
||||
assert "http://localhost:4001/users/rye@niu.moe/followers" in activity.recipients
|
||||
|
||||
user = User.get_cached_by_id(user.id)
|
||||
assert user.note_count == 1
|
||||
|
||||
{:ok, user} = Transmogrifier.upgrade_user_from_ap_id("https://niu.moe/users/rye")
|
||||
ObanHelpers.perform_all()
|
||||
|
||||
assert user.ap_enabled
|
||||
assert user.note_count == 1
|
||||
assert user.follower_address == "https://niu.moe/users/rye/followers"
|
||||
assert user.following_address == "https://niu.moe/users/rye/following"
|
||||
|
||||
user = User.get_cached_by_id(user.id)
|
||||
assert user.note_count == 1
|
||||
|
||||
activity = Activity.get_by_id(activity.id)
|
||||
assert user.follower_address in activity.recipients
|
||||
|
||||
assert %{
|
||||
"url" => [
|
||||
%{
|
||||
"href" =>
|
||||
"https://cdn.niu.moe/accounts/avatars/000/033/323/original/fd7f8ae0b3ffedc9.jpeg"
|
||||
}
|
||||
]
|
||||
} = user.avatar
|
||||
|
||||
assert %{
|
||||
"url" => [
|
||||
%{
|
||||
"href" =>
|
||||
"https://cdn.niu.moe/accounts/headers/000/033/323/original/850b3448fa5fd477.png"
|
||||
}
|
||||
]
|
||||
} = user.banner
|
||||
|
||||
refute "..." in activity.recipients
|
||||
|
||||
unrelated_activity = Activity.get_by_id(unrelated_activity.id)
|
||||
refute user.follower_address in unrelated_activity.recipients
|
||||
|
||||
user_two = User.get_cached_by_id(user_two.id)
|
||||
assert User.following?(user_two, user)
|
||||
refute "..." in User.following(user_two)
|
||||
end
|
||||
end
|
||||
|
||||
describe "actor rewriting" do
|
||||
test "it fixes the actor URL property to be a proper URI" do
|
||||
data = %{
|
||||
|
@ -1339,7 +1339,7 @@ defmodule Pleroma.Web.CommonAPITest do
|
||||
|
||||
test "cancels a pending follow for a remote user" do
|
||||
follower = insert(:user)
|
||||
followed = insert(:user, is_locked: true, local: false, ap_enabled: true)
|
||||
followed = insert(:user, is_locked: true, local: false)
|
||||
|
||||
assert {:ok, follower, followed, %{id: activity_id, data: %{"state" => "pending"}}} =
|
||||
CommonAPI.follow(follower, followed)
|
||||
|
@ -78,16 +78,14 @@ defmodule Pleroma.Web.FederatorTest do
|
||||
local: false,
|
||||
nickname: "nick1@domain.com",
|
||||
ap_id: "https://domain.com/users/nick1",
|
||||
inbox: inbox1,
|
||||
ap_enabled: true
|
||||
inbox: inbox1
|
||||
})
|
||||
|
||||
insert(:user, %{
|
||||
local: false,
|
||||
nickname: "nick2@domain2.com",
|
||||
ap_id: "https://domain2.com/users/nick2",
|
||||
inbox: inbox2,
|
||||
ap_enabled: true
|
||||
inbox: inbox2
|
||||
})
|
||||
|
||||
dt = NaiveDateTime.utc_now()
|
||||
|
@ -6,7 +6,9 @@ defmodule Pleroma.Web.MediaProxy.MediaProxyControllerTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
import Mock
|
||||
import Mox
|
||||
|
||||
alias Pleroma.ReverseProxy.ClientMock
|
||||
alias Pleroma.Web.MediaProxy
|
||||
alias Plug.Conn
|
||||
|
||||
@ -74,6 +76,20 @@ defmodule Pleroma.Web.MediaProxy.MediaProxyControllerTest do
|
||||
assert %Conn{status: 404, resp_body: "Not Found"} = get(conn, url)
|
||||
end
|
||||
end
|
||||
|
||||
test "it applies sandbox CSP to MediaProxy requests", %{conn: conn} do
|
||||
media_url = "https://lain.com/image.png"
|
||||
media_proxy_url = MediaProxy.encode_url(media_url)
|
||||
|
||||
ClientMock
|
||||
|> expect(:request, fn :get, ^media_url, _, _, _ ->
|
||||
{:ok, 200, [{"content-type", "image/png"}]}
|
||||
end)
|
||||
|
||||
%Conn{resp_headers: headers} = get(conn, media_proxy_url)
|
||||
|
||||
assert {"content-security-policy", "sandbox;"} in headers
|
||||
end
|
||||
end
|
||||
|
||||
describe "Media Preview Proxy" do
|
||||
|
@ -182,7 +182,8 @@ defmodule Pleroma.Web.Metadata.Providers.TwitterCardTest do
|
||||
{:meta, [name: "twitter:title", content: Utils.user_name_string(user)], []},
|
||||
{:meta, [name: "twitter:description", content: "pleroma in a nutshell"], []},
|
||||
{:meta, [name: "twitter:card", content: "summary_large_image"], []},
|
||||
{:meta, [name: "twitter:player", content: "https://pleroma.gov/tenshi.png"], []},
|
||||
{:meta, [name: "twitter:image", content: "https://pleroma.gov/tenshi.png"], []},
|
||||
{:meta, [name: "twitter:image:alt", content: ""], []},
|
||||
{:meta, [name: "twitter:player:width", content: "1280"], []},
|
||||
{:meta, [name: "twitter:player:height", content: "1024"], []},
|
||||
{:meta, [name: "twitter:card", content: "player"], []},
|
||||
|
@ -40,4 +40,30 @@ defmodule Pleroma.Web.Plugs.UploadedMediaPlugTest do
|
||||
&(&1 == {"content-disposition", ~s[inline; filename="\\"cofe\\".gif"]})
|
||||
)
|
||||
end
|
||||
|
||||
test "denies access to media if wrong Host", %{
|
||||
attachment_url: attachment_url
|
||||
} do
|
||||
conn = get(build_conn(), attachment_url)
|
||||
|
||||
assert conn.status == 200
|
||||
|
||||
new_media_base = "http://media.localhost:8080"
|
||||
|
||||
%{scheme: new_media_scheme, host: new_media_host, port: new_media_port} =
|
||||
URI.parse(new_media_base)
|
||||
|
||||
clear_config([Pleroma.Upload, :base_url], new_media_base)
|
||||
|
||||
conn = get(build_conn(), attachment_url)
|
||||
|
||||
expected_url =
|
||||
URI.parse(attachment_url)
|
||||
|> Map.put(:host, new_media_host)
|
||||
|> Map.put(:port, new_media_port)
|
||||
|> Map.put(:scheme, new_media_scheme)
|
||||
|> URI.to_string()
|
||||
|
||||
assert redirected_to(conn, 302) == expected_url
|
||||
end
|
||||
end
|
||||
|
@ -129,7 +129,7 @@ defmodule Pleroma.Web.RichMedia.ParserTest do
|
||||
}}
|
||||
end
|
||||
|
||||
test "parses OEmbed" do
|
||||
test "parses OEmbed and filters HTML tags" do
|
||||
assert Parser.parse("http://example.com/oembed") ==
|
||||
{:ok,
|
||||
%{
|
||||
@ -139,7 +139,7 @@ defmodule Pleroma.Web.RichMedia.ParserTest do
|
||||
"flickr_type" => "photo",
|
||||
"height" => "768",
|
||||
"html" =>
|
||||
"<a data-flickr-embed=\"true\" href=\"https://www.flickr.com/photos/bees/2362225867/\" title=\"Bacon Lollys by \u202E\u202D\u202Cbees\u202C, on Flickr\"><img src=\"https://farm4.staticflickr.com/3040/2362225867_4a87ab8baf_b.jpg\" width=\"1024\" height=\"768\" alt=\"Bacon Lollys\"></a><script async src=\"https://embedr.flickr.com/assets/client-code.js\" charset=\"utf-8\"></script>",
|
||||
"<a href=\"https://www.flickr.com/photos/bees/2362225867/\" title=\"Bacon Lollys by \u202E\u202D\u202Cbees\u202C, on Flickr\"><img src=\"https://farm4.staticflickr.com/3040/2362225867_4a87ab8baf_b.jpg\" width=\"1024\" height=\"768\" alt=\"Bacon Lollys\"/></a>",
|
||||
"license" => "All Rights Reserved",
|
||||
"license_id" => 0,
|
||||
"provider_name" => "Flickr",
|
||||
|
@ -29,6 +29,26 @@ defmodule Pleroma.Web.StreamerTest do
|
||||
assert {:ok, "public:local:media"} = Streamer.get_topic("public:local:media", nil, nil)
|
||||
end
|
||||
|
||||
test "rejects local public streams if restricted_unauthenticated is on" do
|
||||
clear_config([:restrict_unauthenticated, :timelines, :local], true)
|
||||
|
||||
assert {:error, :unauthorized} = Streamer.get_topic("public:local", nil, nil)
|
||||
assert {:error, :unauthorized} = Streamer.get_topic("public:local:media", nil, nil)
|
||||
end
|
||||
|
||||
test "rejects remote public streams if restricted_unauthenticated is on" do
|
||||
clear_config([:restrict_unauthenticated, :timelines, :federated], true)
|
||||
|
||||
assert {:error, :unauthorized} = Streamer.get_topic("public", nil, nil)
|
||||
assert {:error, :unauthorized} = Streamer.get_topic("public:media", nil, nil)
|
||||
|
||||
assert {:error, :unauthorized} =
|
||||
Streamer.get_topic("public:remote", nil, nil, %{"instance" => "lain.com"})
|
||||
|
||||
assert {:error, :unauthorized} =
|
||||
Streamer.get_topic("public:remote:media", nil, nil, %{"instance" => "lain.com"})
|
||||
end
|
||||
|
||||
test "allows instance streams" do
|
||||
assert {:ok, "public:remote:lain.com"} =
|
||||
Streamer.get_topic("public:remote", nil, nil, %{"instance" => "lain.com"})
|
||||
@ -69,6 +89,63 @@ defmodule Pleroma.Web.StreamerTest do
|
||||
end
|
||||
end
|
||||
|
||||
test "allows local public streams if restricted_unauthenticated is on", %{
|
||||
user: user,
|
||||
token: oauth_token
|
||||
} do
|
||||
clear_config([:restrict_unauthenticated, :timelines, :local], true)
|
||||
|
||||
%{token: read_notifications_token} = oauth_access(["read:notifications"], user: user)
|
||||
%{token: badly_scoped_token} = oauth_access(["irrelevant:scope"], user: user)
|
||||
|
||||
assert {:ok, "public:local"} = Streamer.get_topic("public:local", user, oauth_token)
|
||||
|
||||
assert {:ok, "public:local:media"} =
|
||||
Streamer.get_topic("public:local:media", user, oauth_token)
|
||||
|
||||
for token <- [read_notifications_token, badly_scoped_token] do
|
||||
assert {:error, :unauthorized} = Streamer.get_topic("public:local", user, token)
|
||||
|
||||
assert {:error, :unauthorized} = Streamer.get_topic("public:local:media", user, token)
|
||||
end
|
||||
end
|
||||
|
||||
test "allows remote public streams if restricted_unauthenticated is on", %{
|
||||
user: user,
|
||||
token: oauth_token
|
||||
} do
|
||||
clear_config([:restrict_unauthenticated, :timelines, :federated], true)
|
||||
|
||||
%{token: read_notifications_token} = oauth_access(["read:notifications"], user: user)
|
||||
%{token: badly_scoped_token} = oauth_access(["irrelevant:scope"], user: user)
|
||||
|
||||
assert {:ok, "public"} = Streamer.get_topic("public", user, oauth_token)
|
||||
assert {:ok, "public:media"} = Streamer.get_topic("public:media", user, oauth_token)
|
||||
|
||||
assert {:ok, "public:remote:lain.com"} =
|
||||
Streamer.get_topic("public:remote", user, oauth_token, %{"instance" => "lain.com"})
|
||||
|
||||
assert {:ok, "public:remote:media:lain.com"} =
|
||||
Streamer.get_topic("public:remote:media", user, oauth_token, %{
|
||||
"instance" => "lain.com"
|
||||
})
|
||||
|
||||
for token <- [read_notifications_token, badly_scoped_token] do
|
||||
assert {:error, :unauthorized} = Streamer.get_topic("public", user, token)
|
||||
assert {:error, :unauthorized} = Streamer.get_topic("public:media", user, token)
|
||||
|
||||
assert {:error, :unauthorized} =
|
||||
Streamer.get_topic("public:remote", user, token, %{
|
||||
"instance" => "lain.com"
|
||||
})
|
||||
|
||||
assert {:error, :unauthorized} =
|
||||
Streamer.get_topic("public:remote:media", user, token, %{
|
||||
"instance" => "lain.com"
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
test "allows user streams (with proper OAuth token scopes)", %{
|
||||
user: user,
|
||||
token: read_oauth_token
|
||||
|
@ -50,7 +50,6 @@ defmodule Pleroma.Factory do
|
||||
last_refreshed_at: NaiveDateTime.utc_now(),
|
||||
notification_settings: %Pleroma.User.NotificationSetting{},
|
||||
multi_factor_authentication_settings: %Pleroma.MFA.Settings{},
|
||||
ap_enabled: true,
|
||||
keys: pem
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user