1
0
Fork 0
forked from mirrors/akkoma

Compare commits

...

4 commits

Author SHA1 Message Date
Erin Shepherd 02b4164b56 bites you 2024-03-02 22:56:02 +01:00
Erin Shepherd d5f3ffb774 context: add featured definition
This was missing from our context, which caused interoperability issues with
people who do context processing
2024-03-02 21:32:58 +01:00
Erin Shepherd 6c25ef3e12 Refresh Users much more aggressively when processing Move activities
The default refresh interval of 1 day is woefully inadequate here;
users expect to be able to add the alias to their new account and
press the move button on their old account and have it work.

This allows callers to specify a maximum age before a refetch is
triggered. We set that to 5s for the move code, as a nice compromise
between Making Things Work and ensuring that this can't be used
to hammer a remote server
2024-02-29 21:08:25 +01:00
Erin Shepherd b63c609103 Don't list old accounts as aliases in WebFinger
Per the XRD specification:

> 2.4. Element <Alias>
>
> The <Alias> element contains a URI value that is an additional
> identifier for the resource described by the XRD. This value
> MUST be an absolute URI. The <Alias> element does not identify
> additional resources the XRD is describing, **but rather provides
> additional identifiers for the same resource.**

(http://docs.oasis-open.org/xri/xrd/v1.0/os/xrd-1.0-os.html#element.alias, emphasis mine)

In other words, the alias list is expected to link to things which are
not just semantically the same, but exactly the same. Old user accounts
don't do that

This change should not pose a compatibility issue: Mastodon does not
list old accounts here (See e1fcb02867/app/serializers/webfinger_serializer.rb (L12))

The use of as:alsoKnownAs is also not quite semantically right here
(see https://www.w3.org/TR/did-core/#dfn-alsoknownas, which defines
it to be used to refer to identifiers which are interchangable) but
that's what DID get for reusing a property definition that Mastodon
already squatted long before they got to it
2024-02-29 20:56:32 +01:00
9 changed files with 55 additions and 15 deletions

View file

@ -1,4 +1,6 @@
## akkoma
## snaccoma: akkoma with bites
this is a silly little fork which can receive [Bite](https://ns.mia.jetzt/as/) activities
*a smallish microblogging platform, aka the cooler pleroma*

View file

@ -72,6 +72,7 @@ def unread_notifications_count(%User{id: user_id}) do
pleroma:report
reblog
poll
bite
}
def changeset(%Notification{} = notification, attrs) do
@ -402,7 +403,7 @@ def create_notifications(%Activity{data: %{"to" => _, "type" => "Create"}} = act
end
def create_notifications(%Activity{data: %{"type" => type}} = activity, options)
when type in ["Follow", "Like", "Announce", "Move", "EmojiReact", "Flag", "Update"] do
when type in ["Follow", "Like", "Announce", "Move", "EmojiReact", "Flag", "Update", "Bite"] do
do_create_notifications(activity, options)
end
@ -459,6 +460,9 @@ defp type_from_activity(%{data: %{"type" => type}} = activity) do
"Update" ->
"update"
"Bite" ->
"bite"
t ->
raise "No notification type for activity type #{t}"
end
@ -532,7 +536,8 @@ def get_notified_from_activity(%Activity{data: %{"type" => type}} = activity, lo
"Move",
"EmojiReact",
"Flag",
"Update"
"Update",
"Bite"
] do
potential_receiver_ap_ids = get_potential_receiver_ap_ids(activity)

View file

@ -969,15 +969,16 @@ defp maybe_send_registration_email(%User{email: email} = user) when is_binary(em
defp maybe_send_registration_email(_), do: {:ok, :noop}
def needs_update?(%User{local: true}), do: false
def needs_update?(user, options \\ [])
def needs_update?(%User{local: true}, _options), do: false
def needs_update?(%User{local: false, last_refreshed_at: nil}, _options), do: true
def needs_update?(%User{local: false, last_refreshed_at: nil}), do: true
def needs_update?(%User{local: false} = user) do
NaiveDateTime.diff(NaiveDateTime.utc_now(), user.last_refreshed_at) >= 86_400
def needs_update?(%User{local: false} = user, options) do
NaiveDateTime.diff(NaiveDateTime.utc_now(), user.last_refreshed_at) >=
Keyword.get(options, :maximum_age, 86_400)
end
def needs_update?(_), do: true
def needs_update?(_, _options), do: true
# "Locked" (self-locked) users demand explicit authorization of follow requests
@spec can_direct_follow_local(User.t(), User.t()) :: true | false
@ -1980,10 +1981,10 @@ def html_filter_policy(_), do: Config.get([:markup, :scrub_policy])
def fetch_by_ap_id(ap_id), do: ActivityPub.make_user_from_ap_id(ap_id)
def get_or_fetch_by_ap_id(ap_id) do
def get_or_fetch_by_ap_id(ap_id, options \\ []) do
cached_user = get_cached_by_ap_id(ap_id)
maybe_fetched_user = needs_update?(cached_user) && fetch_by_ap_id(ap_id)
maybe_fetched_user = needs_update?(cached_user, options) && fetch_by_ap_id(ap_id)
case {cached_user, maybe_fetched_user} do
{_, {:ok, %User{} = user}} ->

View file

@ -186,6 +186,13 @@ def handle(%{data: %{"type" => "Like"}} = object, meta) do
{:ok, object, meta}
end
# Tasks this handles
# - Set up bite notification
def handle(%{data: %{"type" => "Bite"}} = object, meta) do
Notification.create_notifications(object)
{:ok, object, meta}
end
# Tasks this handles
# - Actually create object
# - Rollback if we couldn't create it

View file

@ -485,7 +485,7 @@ def handle_incoming(
%{"type" => type} = data,
_options
)
when type in ~w{Update Block Follow Accept Reject} do
when type in ~w{Update Block Follow Accept Reject Bite} do
with {:ok, %User{}} <- ObjectValidator.fetch_actor(data),
{:ok, activity, _} <-
Pipeline.common_pipeline(data, local: false) do
@ -576,7 +576,12 @@ def handle_incoming(
_options
) do
with %User{} = origin_user <- User.get_cached_by_ap_id(origin_actor),
{:ok, %User{} = target_user} <- User.get_or_fetch_by_ap_id(target_actor),
# Use a dramatically shortened maximum age before refresh here because it is reasonable
# for a user to
# 1. Add the alias to their new account and then
# 2. Press the button on their new account
# within a very short period of time and expect it to work
{:ok, %User{} = target_user} <- User.get_or_fetch_by_ap_id(target_actor, maximum_age: 5),
true <- origin_actor in target_user.also_known_as do
ActivityPub.move(origin_user, target_user, false)
else

View file

@ -128,7 +128,7 @@ def render(
"pleroma:report" ->
put_report(response, activity)
type when type in ["follow", "follow_request"] ->
type when type in ["follow", "follow_request", "bite"] ->
response
end
end

View file

@ -65,7 +65,7 @@ defp gather_links(%User{} = user) do
end
defp gather_aliases(%User{} = user) do
[user.ap_id | user.also_known_as]
[user.ap_id]
end
def represent_user(user, "JSON") do

View file

@ -0,0 +1,16 @@
defmodule Pleroma.Repo.Migrations.AddBiteToNotificationsEnum do
use Ecto.Migration
@disable_ddl_transaction true
def up do
"""
alter type notification_type add value if not exists 'bite'
"""
|> execute()
end
def down do
# Leave value in place
end
end

View file

@ -45,6 +45,10 @@
"contentMap": {
"@id": "as:content",
"@container": "@language"
},
"featured": {
"@id": "toot:featured",
"@type": "@id"
}
}
]