feat: Accept follow requests

This commit is contained in:
Ro 2024-10-11 02:44:55 +00:00
parent 4bb55c08a5
commit 7824edbec0
6 changed files with 72 additions and 6 deletions

View file

@ -1,10 +1,25 @@
# Postland
## Backend
- [ ] Posting
- [ ] Timeline
- [ ] Deleting posts
- [x] Following
- [ ] Unfollowing
- [ ] Being followed
- [x] Being followed
- [x] Accepting follows
- [ ] Liking
- [ ] Unliking
## UX
- [ ] Posting
- [ ] Timeline
- [ ] Deleting posts
- [x] Following
- [ ] Unfollowing
- [x] Being followed
- [ ] Accepting follows
- [ ] Liking
- [ ] Unliking

View file

@ -52,11 +52,9 @@ defmodule ActivityPub.Headers do
end
def verify(method, path, headers, actor_fetcher \\ &fetch_actor_key/1) do
dbg(headers)
{_key, signature_header} = Enum.find(headers, fn {key, _} -> key == "signature" end)
signature_kv = SignatureSplitter.split(signature_header) |> dbg()
signature_kv = SignatureSplitter.split(signature_header)
key_id = find_value(signature_kv, "keyId")
signature = signature_kv |> find_value("signature") |> Base.decode64!()
signing_text_headers = signature_kv |> find_value("headers") |> String.split(" ")

View file

@ -28,7 +28,6 @@ defmodule Postland.Activities do
actor_id = case Regex.run(pattern, follow_id) do
[_, encoded_actor_id] ->
dbg(encoded_actor_id)
Base.url_decode64!(encoded_actor_id, padding: false)
_other ->

View file

@ -12,13 +12,15 @@ defmodule Postland.Activity do
def changeset(attrs) do
attrs = %{
"id" => Map.get(attrs, "id", Ecto.UUID.autogenerate()),
"actor_id" => Map.get(attrs, "actor"),
"type" => Map.get(attrs, "type"),
"data" => attrs
}
%__MODULE__{}
|> cast(attrs, [:actor_id, :type, :data])
|> cast(attrs, [:id, :actor_id, :type, :data])
|> validate_required(:id)
|> validate_required(:data)
|> validate_required(:type)
end

View file

@ -4,12 +4,55 @@ defmodule Postland.Follows do
import Ecto.Query, warn: false
alias Postland.Accounts
alias Postland.Activity
alias Postland.Follow
alias Postland.Repo
alias ActivityPub.Headers
alias Ecto.Multi
def record_and_send_acceptance(request) do
Multi.new()
|> Multi.run(:confirm_timestamp, fn _data, _repo -> confirm_request(request) end)
|> Multi.run(:send_acceptance, fn _data, _repo ->
send_acceptance(request)
end)
|> Repo.transaction()
end
def send_acceptance(request) do
{:ok, actor} = ActivityPub.fetch_actor(request.follower)
inbox = Map.get(actor, "inbox")
case get_follow_activity(request.follower) do
nil ->
{:error, "could not find Follow activity to Accept"}
follow_activity ->
body =
%{
"@context" => "https://www.w3.org/ns/activitystreams",
"type" => "Accept",
"actor" => Postland.my_actor_id(),
"object" => %{
"actor" => request.follower,
"id" => Map.get(follow_activity.data, "id"),
"object" => Postland.my_actor_id(),
"type" => "Follow"
}
}
|> Jason.encode!()
headers = Headers.signing_headers("POST", inbox, body, Postland.my_actor_id(), Accounts.solo_user().private_key)
Req.post(inbox, headers: headers, body: body)
end
end
def get_follow_activity(follower) do
from(a in Activity, where: a.type == "Follow", where: a.actor_id == ^follower, limit: 1, order_by: [desc: :inserted_at]) |> Repo.one()
end
def record_and_send_follow_request(to_actor_id) do
Multi.new()
|> Multi.run(:follow_record, fn _data, _repo -> record_outbound_request(to_actor_id) end)

View file

@ -0,0 +1,9 @@
defmodule Postland.Repo.Migrations.AddTimestampsToActivities do
use Ecto.Migration
def change do
alter table("activities") do
timestamps()
end
end
end