forked from AkkomaGang/akkoma
relay fix for admin-fe
This commit is contained in:
parent
3d5d8c05c9
commit
7dc275b69b
12 changed files with 138 additions and 89 deletions
|
@ -313,31 +313,53 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret
|
||||||
- On failure: `Not found`
|
- On failure: `Not found`
|
||||||
- On success: JSON array of user's latest statuses
|
- On success: JSON array of user's latest statuses
|
||||||
|
|
||||||
|
## `GET /api/pleroma/admin/relay`
|
||||||
|
|
||||||
|
### List Relays
|
||||||
|
|
||||||
|
Params: none
|
||||||
|
Response:
|
||||||
|
|
||||||
|
* On success: JSON array of relays
|
||||||
|
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{"actor": "https://example.com/relay", "followed_back": true},
|
||||||
|
{"actor": "https://example2.com/relay", "followed_back": false}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
## `POST /api/pleroma/admin/relay`
|
## `POST /api/pleroma/admin/relay`
|
||||||
|
|
||||||
### Follow a Relay
|
### Follow a Relay
|
||||||
|
|
||||||
- Params:
|
Params:
|
||||||
- `relay_url`
|
|
||||||
- Response:
|
* `relay_url`
|
||||||
- On success: URL of the followed relay
|
|
||||||
|
Response:
|
||||||
|
|
||||||
|
* On success: relay json object
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"actor": "https://example.com/relay", "followed_back": true}
|
||||||
|
```
|
||||||
|
|
||||||
## `DELETE /api/pleroma/admin/relay`
|
## `DELETE /api/pleroma/admin/relay`
|
||||||
|
|
||||||
### Unfollow a Relay
|
### Unfollow a Relay
|
||||||
|
|
||||||
- Params:
|
Params:
|
||||||
- `relay_url`
|
|
||||||
- Response:
|
|
||||||
- On success: URL of the unfollowed relay
|
|
||||||
|
|
||||||
## `GET /api/pleroma/admin/relay`
|
* `relay_url`
|
||||||
|
|
||||||
### List Relays
|
Response:
|
||||||
|
|
||||||
- Params: none
|
* On success: URL of the unfollowed relay
|
||||||
- Response:
|
|
||||||
- On success: JSON array of relays
|
```json
|
||||||
|
{"https://example.com/relay"}
|
||||||
|
```
|
||||||
|
|
||||||
## `POST /api/pleroma/admin/users/invite_token`
|
## `POST /api/pleroma/admin/users/invite_token`
|
||||||
|
|
||||||
|
|
|
@ -35,10 +35,16 @@ def run(["unfollow", target]) do
|
||||||
def run(["list"]) do
|
def run(["list"]) do
|
||||||
start_pleroma()
|
start_pleroma()
|
||||||
|
|
||||||
with {:ok, list} <- Relay.list(true) do
|
with {:ok, list} <- Relay.list() do
|
||||||
list |> Enum.each(&shell_info(&1))
|
Enum.each(list, &print_relay_url/1)
|
||||||
else
|
else
|
||||||
{:error, e} -> shell_error("Error while fetching relay subscription list: #{inspect(e)}")
|
{:error, e} -> shell_error("Error while fetching relay subscription list: #{inspect(e)}")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp print_relay_url(%{followed_back: false} = relay) do
|
||||||
|
shell_info("#{relay.actor} - no Accept received (relay didn't follow back)")
|
||||||
|
end
|
||||||
|
|
||||||
|
defp print_relay_url(relay), do: shell_info(relay.actor)
|
||||||
end
|
end
|
||||||
|
|
|
@ -264,4 +264,12 @@ defp validate_following_id_follower_id_inequality(%Changeset{} = changeset) do
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@spec following_ap_ids(User.t()) :: [String.t()]
|
||||||
|
def following_ap_ids(%User{} = user) do
|
||||||
|
user
|
||||||
|
|> following_query()
|
||||||
|
|> select([r, u], u.ap_id)
|
||||||
|
|> Repo.all()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -247,6 +247,13 @@ def unquote(:"#{outgoing_relation_target}_ap_ids")(user, restrict_deactivated? \
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defdelegate following_count(user), to: FollowingRelationship
|
||||||
|
defdelegate following(user), to: FollowingRelationship
|
||||||
|
defdelegate following?(follower, followed), to: FollowingRelationship
|
||||||
|
defdelegate following_ap_ids(user), to: FollowingRelationship
|
||||||
|
defdelegate get_follow_requests(user), to: FollowingRelationship
|
||||||
|
defdelegate search(query, opts \\ []), to: User.Search
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Dumps Flake Id to SQL-compatible format (16-byte UUID).
|
Dumps Flake Id to SQL-compatible format (16-byte UUID).
|
||||||
E.g. "9pQtDGXuq4p3VlcJEm" -> <<0, 0, 1, 110, 179, 218, 42, 92, 213, 41, 44, 227, 95, 213, 0, 0>>
|
E.g. "9pQtDGXuq4p3VlcJEm" -> <<0, 0, 1, 110, 179, 218, 42, 92, 213, 41, 44, 227, 95, 213, 0, 0>>
|
||||||
|
@ -372,8 +379,6 @@ def restrict_deactivated(query) do
|
||||||
from(u in query, where: u.deactivated != ^true)
|
from(u in query, where: u.deactivated != ^true)
|
||||||
end
|
end
|
||||||
|
|
||||||
defdelegate following_count(user), to: FollowingRelationship
|
|
||||||
|
|
||||||
defp truncate_fields_param(params) do
|
defp truncate_fields_param(params) do
|
||||||
if Map.has_key?(params, :fields) do
|
if Map.has_key?(params, :fields) do
|
||||||
Map.put(params, :fields, Enum.map(params[:fields], &truncate_field/1))
|
Map.put(params, :fields, Enum.map(params[:fields], &truncate_field/1))
|
||||||
|
@ -868,8 +873,6 @@ def follow_all(follower, followeds) do
|
||||||
set_cache(follower)
|
set_cache(follower)
|
||||||
end
|
end
|
||||||
|
|
||||||
defdelegate following(user), to: FollowingRelationship
|
|
||||||
|
|
||||||
def follow(%User{} = follower, %User{} = followed, state \\ :follow_accept) do
|
def follow(%User{} = follower, %User{} = followed, state \\ :follow_accept) do
|
||||||
deny_follow_blocked = Config.get([:user, :deny_follow_blocked])
|
deny_follow_blocked = Config.get([:user, :deny_follow_blocked])
|
||||||
|
|
||||||
|
@ -923,8 +926,6 @@ defp do_unfollow(%User{} = follower, %User{} = followed) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defdelegate following?(follower, followed), to: FollowingRelationship
|
|
||||||
|
|
||||||
@doc "Returns follow state as Pleroma.FollowingRelationship.State value"
|
@doc "Returns follow state as Pleroma.FollowingRelationship.State value"
|
||||||
def get_follow_state(%User{} = follower, %User{} = following) do
|
def get_follow_state(%User{} = follower, %User{} = following) do
|
||||||
following_relationship = FollowingRelationship.get(follower, following)
|
following_relationship = FollowingRelationship.get(follower, following)
|
||||||
|
@ -1189,8 +1190,6 @@ def get_friends_ids(user, page \\ nil) do
|
||||||
|> Repo.all()
|
|> Repo.all()
|
||||||
end
|
end
|
||||||
|
|
||||||
defdelegate get_follow_requests(user), to: FollowingRelationship
|
|
||||||
|
|
||||||
def increase_note_count(%User{} = user) do
|
def increase_note_count(%User{} = user) do
|
||||||
User
|
User
|
||||||
|> where(id: ^user.id)
|
|> where(id: ^user.id)
|
||||||
|
@ -2163,8 +2162,6 @@ def get_ap_ids_by_nicknames(nicknames) do
|
||||||
|> Repo.all()
|
|> Repo.all()
|
||||||
end
|
end
|
||||||
|
|
||||||
defdelegate search(query, opts \\ []), to: User.Search
|
|
||||||
|
|
||||||
defp put_password_hash(
|
defp put_password_hash(
|
||||||
%Ecto.Changeset{valid?: true, changes: %{password: password}} = changeset
|
%Ecto.Changeset{valid?: true, changes: %{password: password}} = changeset
|
||||||
) do
|
) do
|
||||||
|
|
|
@ -1344,9 +1344,8 @@ def fetch_and_prepare_user_from_ap_id(ap_id) do
|
||||||
end
|
end
|
||||||
|
|
||||||
def maybe_handle_clashing_nickname(data) do
|
def maybe_handle_clashing_nickname(data) do
|
||||||
nickname = data[:nickname]
|
with nickname when is_binary(nickname) <- data[:nickname],
|
||||||
|
%User{} = old_user <- User.get_by_nickname(nickname),
|
||||||
with %User{} = old_user <- User.get_by_nickname(nickname),
|
|
||||||
{_, false} <- {:ap_id_comparison, data[:ap_id] == old_user.ap_id} do
|
{_, false} <- {:ap_id_comparison, data[:ap_id] == old_user.ap_id} do
|
||||||
Logger.info(
|
Logger.info(
|
||||||
"Found an old user for #{nickname}, the old ap id is #{old_user.ap_id}, new one is #{
|
"Found an old user for #{nickname}, the old ap id is #{old_user.ap_id}, new one is #{
|
||||||
|
@ -1360,7 +1359,7 @@ def maybe_handle_clashing_nickname(data) do
|
||||||
else
|
else
|
||||||
{:ap_id_comparison, true} ->
|
{:ap_id_comparison, true} ->
|
||||||
Logger.info(
|
Logger.info(
|
||||||
"Found an old user for #{nickname}, but the ap id #{data[:ap_id]} is the same as the new user. Race condition? Not changing anything."
|
"Found an old user for #{data[:nickname]}, but the ap id #{data[:ap_id]} is the same as the new user. Race condition? Not changing anything."
|
||||||
)
|
)
|
||||||
|
|
||||||
_ ->
|
_ ->
|
||||||
|
|
|
@ -215,7 +215,7 @@ def announce(actor, object, options \\ []) do
|
||||||
|
|
||||||
to =
|
to =
|
||||||
cond do
|
cond do
|
||||||
actor.ap_id == Relay.relay_ap_id() ->
|
actor.ap_id == Relay.ap_id() ->
|
||||||
[actor.follower_address]
|
[actor.follower_address]
|
||||||
|
|
||||||
public? ->
|
public? ->
|
||||||
|
|
|
@ -10,19 +10,13 @@ defmodule Pleroma.Web.ActivityPub.Relay do
|
||||||
alias Pleroma.Web.CommonAPI
|
alias Pleroma.Web.CommonAPI
|
||||||
require Logger
|
require Logger
|
||||||
|
|
||||||
@relay_nickname "relay"
|
@nickname "relay"
|
||||||
|
|
||||||
def get_actor do
|
@spec ap_id() :: String.t()
|
||||||
actor =
|
def ap_id, do: "#{Pleroma.Web.Endpoint.url()}/#{@nickname}"
|
||||||
relay_ap_id()
|
|
||||||
|> User.get_or_create_service_actor_by_ap_id(@relay_nickname)
|
|
||||||
|
|
||||||
actor
|
@spec get_actor() :: User.t() | nil
|
||||||
end
|
def get_actor, do: User.get_or_create_service_actor_by_ap_id(ap_id(), @nickname)
|
||||||
|
|
||||||
def relay_ap_id do
|
|
||||||
"#{Pleroma.Web.Endpoint.url()}/relay"
|
|
||||||
end
|
|
||||||
|
|
||||||
@spec follow(String.t()) :: {:ok, Activity.t()} | {:error, any()}
|
@spec follow(String.t()) :: {:ok, Activity.t()} | {:error, any()}
|
||||||
def follow(target_instance) do
|
def follow(target_instance) do
|
||||||
|
@ -61,34 +55,38 @@ def publish(%Activity{data: %{"type" => "Create"}} = activity) do
|
||||||
|
|
||||||
def publish(_), do: {:error, "Not implemented"}
|
def publish(_), do: {:error, "Not implemented"}
|
||||||
|
|
||||||
@spec list(boolean()) :: {:ok, [String.t()]} | {:error, any()}
|
@spec list() :: {:ok, [%{actor: String.t(), followed_back: boolean()}]} | {:error, any()}
|
||||||
def list(with_not_accepted \\ false) do
|
def list do
|
||||||
with %User{} = user <- get_actor() do
|
with %User{} = user <- get_actor() do
|
||||||
accepted =
|
accepted =
|
||||||
user
|
user
|
||||||
|> User.following()
|
|> following()
|
||||||
|> Enum.map(fn entry -> URI.parse(entry).host end)
|
|> Enum.map(fn actor -> %{actor: actor, followed_back: true} end)
|
||||||
|> Enum.uniq()
|
|
||||||
|
|
||||||
list =
|
|
||||||
if with_not_accepted do
|
|
||||||
without_accept =
|
without_accept =
|
||||||
user
|
user
|
||||||
|> Pleroma.Activity.following_requests_for_actor()
|
|> Pleroma.Activity.following_requests_for_actor()
|
||||||
|> Enum.map(fn a -> URI.parse(a.data["object"]).host <> " (no Accept received)" end)
|
|> Enum.map(fn activity -> %{actor: activity.data["object"], followed_back: false} end)
|
||||||
|> Enum.uniq()
|
|> Enum.uniq()
|
||||||
|
|
||||||
accepted ++ without_accept
|
{:ok, accepted ++ without_accept}
|
||||||
else
|
|
||||||
accepted
|
|
||||||
end
|
|
||||||
|
|
||||||
{:ok, list}
|
|
||||||
else
|
else
|
||||||
error -> format_error(error)
|
error -> format_error(error)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@spec following() :: [String.t()]
|
||||||
|
def following do
|
||||||
|
get_actor()
|
||||||
|
|> following()
|
||||||
|
end
|
||||||
|
|
||||||
|
defp following(user) do
|
||||||
|
user
|
||||||
|
|> User.following_ap_ids()
|
||||||
|
|> Enum.uniq()
|
||||||
|
end
|
||||||
|
|
||||||
defp format_error({:error, error}), do: format_error(error)
|
defp format_error({:error, error}), do: format_error(error)
|
||||||
|
|
||||||
defp format_error(error) do
|
defp format_error(error) do
|
||||||
|
|
|
@ -39,7 +39,7 @@ def follow(%{assigns: %{user: admin}, body_params: %{relay_url: target}} = conn,
|
||||||
target: target
|
target: target
|
||||||
})
|
})
|
||||||
|
|
||||||
json(conn, target)
|
json(conn, %{actor: target, followed_back: target in Relay.following()})
|
||||||
else
|
else
|
||||||
_ ->
|
_ ->
|
||||||
conn
|
conn
|
||||||
|
|
|
@ -27,8 +27,7 @@ def index_operation do
|
||||||
properties: %{
|
properties: %{
|
||||||
relays: %Schema{
|
relays: %Schema{
|
||||||
type: :array,
|
type: :array,
|
||||||
items: %Schema{type: :string},
|
items: relay()
|
||||||
example: ["lain.com", "mstdn.io"]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -43,19 +42,9 @@ def follow_operation do
|
||||||
operationId: "AdminAPI.RelayController.follow",
|
operationId: "AdminAPI.RelayController.follow",
|
||||||
security: [%{"oAuth" => ["write:follows"]}],
|
security: [%{"oAuth" => ["write:follows"]}],
|
||||||
parameters: admin_api_params(),
|
parameters: admin_api_params(),
|
||||||
requestBody:
|
requestBody: request_body("Parameters", relay_url()),
|
||||||
request_body("Parameters", %Schema{
|
|
||||||
type: :object,
|
|
||||||
properties: %{
|
|
||||||
relay_url: %Schema{type: :string, format: :uri}
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
responses: %{
|
responses: %{
|
||||||
200 =>
|
200 => Operation.response("Status", "application/json", relay())
|
||||||
Operation.response("Status", "application/json", %Schema{
|
|
||||||
type: :string,
|
|
||||||
example: "http://mastodon.example.org/users/admin"
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
@ -67,13 +56,7 @@ def unfollow_operation do
|
||||||
operationId: "AdminAPI.RelayController.unfollow",
|
operationId: "AdminAPI.RelayController.unfollow",
|
||||||
security: [%{"oAuth" => ["write:follows"]}],
|
security: [%{"oAuth" => ["write:follows"]}],
|
||||||
parameters: admin_api_params(),
|
parameters: admin_api_params(),
|
||||||
requestBody:
|
requestBody: request_body("Parameters", relay_url()),
|
||||||
request_body("Parameters", %Schema{
|
|
||||||
type: :object,
|
|
||||||
properties: %{
|
|
||||||
relay_url: %Schema{type: :string, format: :uri}
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
responses: %{
|
responses: %{
|
||||||
200 =>
|
200 =>
|
||||||
Operation.response("Status", "application/json", %Schema{
|
Operation.response("Status", "application/json", %Schema{
|
||||||
|
@ -83,4 +66,29 @@ def unfollow_operation do
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp relay do
|
||||||
|
%Schema{
|
||||||
|
type: :object,
|
||||||
|
properties: %{
|
||||||
|
actor: %Schema{
|
||||||
|
type: :string,
|
||||||
|
example: "https://example.com/relay"
|
||||||
|
},
|
||||||
|
followed_back: %Schema{
|
||||||
|
type: :boolean,
|
||||||
|
description: "Is relay followed back by this actor?"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp relay_url do
|
||||||
|
%Schema{
|
||||||
|
type: :object,
|
||||||
|
properties: %{
|
||||||
|
relay_url: %Schema{type: :string, format: :uri}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -42,7 +42,11 @@ test "relay is followed" do
|
||||||
assert activity.data["object"] == target_user.ap_id
|
assert activity.data["object"] == target_user.ap_id
|
||||||
|
|
||||||
:ok = Mix.Tasks.Pleroma.Relay.run(["list"])
|
:ok = Mix.Tasks.Pleroma.Relay.run(["list"])
|
||||||
assert_receive {:mix_shell, :info, ["mastodon.example.org (no Accept received)"]}
|
|
||||||
|
assert_receive {:mix_shell, :info,
|
||||||
|
[
|
||||||
|
"http://mastodon.example.org/users/admin - no Accept received (relay didn't follow back)"
|
||||||
|
]}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -95,8 +99,8 @@ test "Prints relay subscription list" do
|
||||||
|
|
||||||
:ok = Mix.Tasks.Pleroma.Relay.run(["list"])
|
:ok = Mix.Tasks.Pleroma.Relay.run(["list"])
|
||||||
|
|
||||||
assert_receive {:mix_shell, :info, ["mstdn.io"]}
|
assert_receive {:mix_shell, :info, ["https://mstdn.io/users/mayuutann"]}
|
||||||
assert_receive {:mix_shell, :info, ["mastodon.example.org"]}
|
assert_receive {:mix_shell, :info, ["http://mastodon.example.org/users/admin"]}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -533,7 +533,7 @@ test "accept follow activity", %{conn: conn} do
|
||||||
end)
|
end)
|
||||||
|
|
||||||
:ok = Mix.Tasks.Pleroma.Relay.run(["list"])
|
:ok = Mix.Tasks.Pleroma.Relay.run(["list"])
|
||||||
assert_receive {:mix_shell, :info, ["relay.mastodon.host"]}
|
assert_receive {:mix_shell, :info, ["https://relay.mastodon.host/actor"]}
|
||||||
end
|
end
|
||||||
|
|
||||||
@tag capture_log: true
|
@tag capture_log: true
|
||||||
|
|
|
@ -39,8 +39,10 @@ test "POST /relay", %{conn: conn, admin: admin} do
|
||||||
relay_url: "http://mastodon.example.org/users/admin"
|
relay_url: "http://mastodon.example.org/users/admin"
|
||||||
})
|
})
|
||||||
|
|
||||||
assert json_response_and_validate_schema(conn, 200) ==
|
assert json_response_and_validate_schema(conn, 200) == %{
|
||||||
"http://mastodon.example.org/users/admin"
|
"actor" => "http://mastodon.example.org/users/admin",
|
||||||
|
"followed_back" => false
|
||||||
|
}
|
||||||
|
|
||||||
log_entry = Repo.one(ModerationLog)
|
log_entry = Repo.one(ModerationLog)
|
||||||
|
|
||||||
|
@ -59,8 +61,13 @@ test "GET /relay", %{conn: conn} do
|
||||||
|
|
||||||
conn = get(conn, "/api/pleroma/admin/relay")
|
conn = get(conn, "/api/pleroma/admin/relay")
|
||||||
|
|
||||||
assert json_response_and_validate_schema(conn, 200)["relays"] --
|
assert json_response_and_validate_schema(conn, 200)["relays"] == [
|
||||||
["mastodon.example.org", "mstdn.io"] == []
|
%{
|
||||||
|
"actor" => "http://mastodon.example.org/users/admin",
|
||||||
|
"followed_back" => true
|
||||||
|
},
|
||||||
|
%{"actor" => "https://mstdn.io/users/mayuutann", "followed_back" => true}
|
||||||
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
test "DELETE /relay", %{conn: conn, admin: admin} do
|
test "DELETE /relay", %{conn: conn, admin: admin} do
|
||||||
|
|
Loading…
Reference in a new issue