Compare commits

...

11 commits

Author SHA1 Message Date
e3c8c4f24f Merge pull request 'mrf/object_age: fix handling of non-public objects' (#851) from Oneric/akkoma:mrf-fix-oage into develop
Reviewed-on: AkkomaGang/akkoma#851
2025-01-03 15:26:11 +00:00
67cdc38296 Merge pull request 'Only proxy HTTP and HTTP urls via Media Proxy' (#860) from nopjmp/akkoma:media-proxy-only-http into develop
Reviewed-on: AkkomaGang/akkoma#860
2025-01-03 15:25:14 +00:00
89d209f486 Merge pull request 'Fix NodeInfo content-type' (#853) from Oneric/akkoma:nodeinfo-contenttype into develop
Reviewed-on: AkkomaGang/akkoma#853
2025-01-03 15:24:25 +00:00
087ada3b2e Merge pull request 'Update supported OTP version to 27 in docs' (#849) from norm/akkoma:docs/otp-27 into develop
Reviewed-on: AkkomaGang/akkoma#849
2025-01-03 15:23:59 +00:00
91bedcfa68 Merge pull request 'Completely omit id for anonymous objects' (#850) from Oneric/akkoma:ap-anonymous-errata into develop
Reviewed-on: AkkomaGang/akkoma#850
2025-01-03 15:23:03 +00:00
ff5d197341 Update CHANGELOG.md 2024-12-16 20:35:12 -06:00
7632765b43 Only proxy HTTP and HTTP urls via Media Proxy
We make an assumption that we are only proxying HTTP/HTTPS hosted
media through the media proxy endpoint.

Fixes: #859
2024-12-16 20:35:12 -06:00
416aebb76a Fix NodeInfo content-type
Fixes: AkkomaGang/akkoma#852
2024-11-19 19:25:31 +01:00
932810c35e mrf/object_age: fix handling of non-public objects
Current logic unconditionally adds public adressing to "cc"
and follower adressing to "to" after attempting to strip it
from the other one. This creates serious problems:

First the bug prompting this investigation and fix,
unconditional addition creates duplicates when adressing
URIs already were in their intended final field; e.g.
this is prominently the case for all "unlisted" posts.
Since List.delete only removes the first occurence,
this then broke follower-adress stripping later on
making the policy ineffective.

It’s also just not safe in general wrt to non-public adressing:
e.g. pre-existing duplicates didn’t get fully stripped,
bespoke adressing modes with only one of public addressing
or follower addressing are mangled — and most importantly:
any belatedly received DM or follower-only post
also got public adressing added!
Shockingly this last point was actually asserted as "correct" in tests;
it appears to be a mistake from mindless match adjustments
while fixing crashes on nil adressing in
10c792110e.

Clean up this sloppy logic up, making sure no more duplicates are
added by us, all instances of relevant adresses are purged and only
readded when they actually existed to begin with.
2024-11-17 00:44:51 +01:00
4c7ef1e027 Update supported OTP version to 27 in docs
The minor incompatibility should have been fixed with commit
bee10eab5e and PRs #839 and #841.
2024-11-09 18:24:53 -05:00
0f9c9aac38 Completely omit id for anonymous objects
Current AP spec demands anonymous objects to have an id value,
but explicitly set it to JSON null. Howeveras it turns out this is
incompatible with JSON-LD requiring `@id` to be a string and thus AP
spec is incompatible iwth the Ativity Streams spec it is based on.
This is an issue for (the few) AP implementers actually performing
JSON-LD processing, like IceShrimp.NET.
This was uncovered by IceShrimp.NET’s zotan due to our adoption of
anonymous objects for emoj in f101886709.

The issues is being discussed by W3C, and will most likely be resolved
via an errata redefining anonymous objects to completely omit the id
field just like transient objects already do. See:
https://github.com/w3c/activitypub/issues/476

Fixes: AkkomaGang/akkoma#848
2024-11-09 19:29:29 +01:00
10 changed files with 45 additions and 17 deletions

View file

@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## UNRELEASED
## Fixed
- Media proxy no longer attempts to proxy embedded images
## 3.13.3
## BREAKING
@ -23,6 +28,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- AP objects with additional JSON-LD profiles beyond ActivityStreams can now be fetched
- Single-selection polls no longer expose the voter_count; MastoAPI demands it be null
and this confused some clients leading to vote distributions >100%
- ObjectAge policy no longer lets unlisted posts slip through
- ObjectAge policy no longer leaks belated DMs and follower-only posts
## Changed
- Refactored Rich Media to cache the content in the database. Fetching operations that could block status rendering have been eliminated.

View file

@ -2,7 +2,7 @@
* PostgreSQL 12+
* Elixir 1.14+ (currently tested up to 1.16)
* Erlang OTP 25+ (currently tested up to OTP26)
* Erlang OTP 25+ (currently tested up to OTP27)
* git
* file / libmagic
* gcc (clang might also work)

View file

@ -34,16 +34,34 @@ defp check_reject(message, actions) do
end
end
@spec delete_and_count(list(), term()) :: {integer(), list()}
defp delete_and_count(list, element), do: delete_and_count(list, element, {0, [], list})
defp delete_and_count([], _element, {0, _nlist, olist}), do: {0, olist}
defp delete_and_count([], _element, {count, nlist, _olist}), do: {count, Enum.reverse(nlist)}
defp delete_and_count([h | r], h, {count, nlist, olist}),
do: delete_and_count(r, h, {count + 1, nlist, olist})
defp delete_and_count([h | r], element, {count, nlist, olist}),
do: delete_and_count(r, element, {count, [h | nlist], olist})
defp insert_if_needed(list, oldcount, element) do
if oldcount <= 0 || Enum.member?(list, element) do
list
else
[element | list]
end
end
defp check_delist(message, actions) do
if :delist in actions do
with %User{} = user <- User.get_cached_by_ap_id(message["actor"]) do
to =
List.delete(message["to"] || [], Pleroma.Constants.as_public()) ++
[user.follower_address]
{pubcnt, to} = delete_and_count(message["to"] || [], Pleroma.Constants.as_public())
{flwcnt, cc} = delete_and_count(message["cc"] || [], user.follower_address)
cc =
List.delete(message["cc"] || [], user.follower_address) ++
[Pleroma.Constants.as_public()]
cc = insert_if_needed(cc, pubcnt, Pleroma.Constants.as_public())
to = insert_if_needed(to, flwcnt, user.follower_address)
message =
message
@ -65,8 +83,8 @@ defp check_delist(message, actions) do
defp check_strip_followers(message, actions) do
if :strip_followers in actions do
with %User{} = user <- User.get_cached_by_ap_id(message["actor"]) do
to = List.delete(message["to"] || [], user.follower_address)
cc = List.delete(message["cc"] || [], user.follower_address)
{_, to} = delete_and_count(message["to"] || [], user.follower_address)
{_, cc} = delete_and_count(message["cc"] || [], user.follower_address)
message =
message

View file

@ -950,8 +950,7 @@ defp build_emoji_tag({name, url}) do
"icon" => %{"url" => "#{URI.encode(url)}", "type" => "Image"},
"name" => ":" <> name <> ":",
"type" => "Emoji",
"updated" => "1970-01-01T00:00:00Z",
"id" => nil
"updated" => "1970-01-01T00:00:00Z"
}
end

View file

@ -52,11 +52,11 @@ def url(url) do
@spec url_proxiable?(String.t()) :: boolean()
def url_proxiable?(url) do
not local?(url) and not whitelisted?(url) and not blocked?(url)
not local?(url) and not whitelisted?(url) and not blocked?(url) and http_scheme?(url)
end
def preview_url(url, preview_params \\ []) do
if preview_enabled?() do
if preview_enabled?() and url_proxiable?(url) do
encode_preview_url(url, preview_params)
else
url(url)
@ -71,6 +71,8 @@ def preview_enabled?, do: enabled?() and !!Config.get([:media_preview_proxy, :en
def local?(url), do: String.starts_with?(url, Endpoint.url())
def http_scheme?(url), do: String.starts_with?(url, ["http:", "https:"])
def whitelisted?(url) do
%{host: domain} = URI.parse(url)

View file

@ -31,7 +31,7 @@ def nodeinfo(conn, %{"version" => version}) when version in ["2.0", "2.1"] do
conn
|> put_resp_header(
"content-type",
"application/json; profile=http://nodeinfo.diaspora.software/ns/schema/2.0#; charset=utf-8"
"application/json; profile=\"http://nodeinfo.diaspora.software/ns/schema/#{version}#\"; charset=utf-8"
)
|> json(Nodeinfo.get_nodeinfo(version))
end

View file

@ -79,7 +79,7 @@ test "works with objects with empty to or cc fields" do
{:ok, data} = ObjectAgePolicy.filter(data)
assert Visibility.get_visibility(%{data: data}) == "unlisted"
assert Visibility.get_visibility(%{data: data}) == "direct"
end
test "it delists an old post" do

View file

@ -698,7 +698,6 @@ test "take_emoji_tags/1" do
assert Transmogrifier.take_emoji_tags(user) == [
%{
"icon" => %{"type" => "Image", "url" => "https://example.org/firefox.png"},
"id" => nil,
"name" => ":firefox:",
"type" => "Emoji",
"updated" => "1970-01-01T00:00:00Z"

View file

@ -47,7 +47,6 @@ test "Renders with emoji tags" do
"tag" => [
%{
"icon" => %{"type" => "Image", "url" => "/test"},
"id" => nil,
"name" => ":bib:",
"type" => "Emoji",
"updated" => "1970-01-01T00:00:00Z"

View file

@ -37,6 +37,10 @@ test "ignores local url" do
assert MediaProxy.url(local_root) == local_root
end
test "ignores data url" do
assert MediaProxy.url("data:image/png;base64,") == "data:image/png;base64,"
end
test "encodes and decodes URL" do
url = "https://pleroma.soykaf.com/static/logo.png"
encoded = MediaProxy.url(url)