forked from mirrors/akkoma
Remote interaction with posts (#198)
Grabbed from https://git.pleroma.social/pleroma/pleroma/-/merge_requests/3587 Co-authored-by: Tusooa Zhu <tusooa@kazv.moe> Reviewed-on: https://akkoma.dev/AkkomaGang/akkoma/pulls/198 Co-authored-by: Norm <normandy@biribiri.dev> Co-committed-by: Norm <normandy@biribiri.dev>
This commit is contained in:
parent
7af32634be
commit
a6d85003fe
|
@ -42,6 +42,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- amd64 is built for debian stable. Compatible with ubuntu 20.
|
- amd64 is built for debian stable. Compatible with ubuntu 20.
|
||||||
- ubuntu-jammy is built for... well, ubuntu 22 (LTS)
|
- ubuntu-jammy is built for... well, ubuntu 22 (LTS)
|
||||||
- amd64-musl is built for alpine 3.16
|
- amd64-musl is built for alpine 3.16
|
||||||
|
- Enable remote users to interact with posts
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Updated mastoFE path, for the newer version
|
- Updated mastoFE path, for the newer version
|
||||||
|
|
|
@ -405,6 +405,16 @@ defp remote_interaction_request do
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def show_subscribe_form_operation do
|
||||||
|
%Operation{
|
||||||
|
tags: ["Accounts"],
|
||||||
|
summary: "Show remote subscribe form",
|
||||||
|
operationId: "UtilController.show_subscribe_form",
|
||||||
|
parameters: [],
|
||||||
|
responses: %{200 => Operation.response("Web Page", "test/html", %Schema{type: :string})}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
defp delete_account_request do
|
defp delete_account_request do
|
||||||
%Schema{
|
%Schema{
|
||||||
title: "AccountDeleteRequest",
|
title: "AccountDeleteRequest",
|
||||||
|
|
|
@ -85,7 +85,8 @@ def features do
|
||||||
if Config.get([:translator, :enabled], false) do
|
if Config.get([:translator, :enabled], false) do
|
||||||
"akkoma:machine_translation"
|
"akkoma:machine_translation"
|
||||||
end,
|
end,
|
||||||
"custom_emoji_reactions"
|
"custom_emoji_reactions",
|
||||||
|
"pleroma:get:main/ostatus"
|
||||||
]
|
]
|
||||||
|> Enum.filter(& &1)
|
|> Enum.filter(& &1)
|
||||||
end
|
end
|
||||||
|
|
|
@ -337,6 +337,7 @@ defmodule Pleroma.Web.Router do
|
||||||
pipe_through(:pleroma_html)
|
pipe_through(:pleroma_html)
|
||||||
|
|
||||||
post("/main/ostatus", UtilController, :remote_subscribe)
|
post("/main/ostatus", UtilController, :remote_subscribe)
|
||||||
|
get("/main/ostatus", UtilController, :show_subscribe_form)
|
||||||
get("/ostatus_subscribe", RemoteFollowController, :follow)
|
get("/ostatus_subscribe", RemoteFollowController, :follow)
|
||||||
post("/ostatus_subscribe", RemoteFollowController, :do_follow)
|
post("/ostatus_subscribe", RemoteFollowController, :do_follow)
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
<%= if @error do %>
|
||||||
|
<h2><%= Gettext.dpgettext("static_pages", "status interact error", "Error: %{error}", error: @error) %></h2>
|
||||||
|
<% else %>
|
||||||
|
<h2><%= raw Gettext.dpgettext("static_pages", "status interact header", "Interacting with %{nickname}'s %{status_link}", nickname: safe_to_string(html_escape(@nickname)), status_link: safe_to_string(link(Gettext.dpgettext("static_pages", "status interact header - status link text", "status"), to: @status_link))) %></h2>
|
||||||
|
<%= form_for @conn, Routes.util_path(@conn, :remote_subscribe), [as: "status"], fn f -> %>
|
||||||
|
<%= hidden_input f, :status_id, value: @status_id %>
|
||||||
|
<%= text_input f, :profile, placeholder: Gettext.dpgettext("static_pages", "placeholder text for account id", "Your account ID, e.g. lain@quitter.se") %>
|
||||||
|
<%= submit Gettext.dpgettext("static_pages", "status interact authorization button", "Interact") %>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
|
@ -7,6 +7,7 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
|
||||||
|
|
||||||
require Logger
|
require Logger
|
||||||
|
|
||||||
|
alias Pleroma.Activity
|
||||||
alias Pleroma.Config
|
alias Pleroma.Config
|
||||||
alias Pleroma.Emoji
|
alias Pleroma.Emoji
|
||||||
alias Pleroma.Healthcheck
|
alias Pleroma.Healthcheck
|
||||||
|
@ -16,8 +17,16 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
|
||||||
alias Pleroma.Web.Plugs.OAuthScopesPlug
|
alias Pleroma.Web.Plugs.OAuthScopesPlug
|
||||||
alias Pleroma.Web.WebFinger
|
alias Pleroma.Web.WebFinger
|
||||||
|
|
||||||
plug(Pleroma.Web.ApiSpec.CastAndValidate when action != :remote_subscribe)
|
plug(
|
||||||
plug(Pleroma.Web.Plugs.FederatingPlug when action == :remote_subscribe)
|
Pleroma.Web.ApiSpec.CastAndValidate
|
||||||
|
when action != :remote_subscribe and action != :show_subscribe_form
|
||||||
|
)
|
||||||
|
|
||||||
|
plug(
|
||||||
|
Pleroma.Web.Plugs.FederatingPlug
|
||||||
|
when action == :remote_subscribe
|
||||||
|
when action == :show_subscribe_form
|
||||||
|
)
|
||||||
|
|
||||||
plug(
|
plug(
|
||||||
OAuthScopesPlug,
|
OAuthScopesPlug,
|
||||||
|
@ -44,7 +53,7 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
|
||||||
|
|
||||||
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.TwitterUtilOperation
|
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.TwitterUtilOperation
|
||||||
|
|
||||||
def remote_subscribe(conn, %{"nickname" => nick, "profile" => _}) do
|
def show_subscribe_form(conn, %{"nickname" => nick}) do
|
||||||
with %User{} = user <- User.get_cached_by_nickname(nick),
|
with %User{} = user <- User.get_cached_by_nickname(nick),
|
||||||
avatar = User.avatar_url(user) do
|
avatar = User.avatar_url(user) do
|
||||||
conn
|
conn
|
||||||
|
@ -54,11 +63,52 @@ def remote_subscribe(conn, %{"nickname" => nick, "profile" => _}) do
|
||||||
render(conn, "subscribe.html", %{
|
render(conn, "subscribe.html", %{
|
||||||
nickname: nick,
|
nickname: nick,
|
||||||
avatar: nil,
|
avatar: nil,
|
||||||
error: "Could not find user"
|
error:
|
||||||
|
Pleroma.Web.Gettext.dpgettext(
|
||||||
|
"static_pages",
|
||||||
|
"remote follow error message - user not found",
|
||||||
|
"Could not find user"
|
||||||
|
)
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def show_subscribe_form(conn, %{"status_id" => id}) do
|
||||||
|
with %Activity{} = activity <- Activity.get_by_id(id),
|
||||||
|
{:ok, ap_id} <- get_ap_id(activity),
|
||||||
|
%User{} = user <- User.get_cached_by_ap_id(activity.actor),
|
||||||
|
avatar = User.avatar_url(user) do
|
||||||
|
conn
|
||||||
|
|> render("status_interact.html", %{
|
||||||
|
status_link: ap_id,
|
||||||
|
status_id: id,
|
||||||
|
nickname: user.nickname,
|
||||||
|
avatar: avatar,
|
||||||
|
error: false
|
||||||
|
})
|
||||||
|
else
|
||||||
|
_e ->
|
||||||
|
render(conn, "status_interact.html", %{
|
||||||
|
status_id: id,
|
||||||
|
avatar: nil,
|
||||||
|
error:
|
||||||
|
Pleroma.Web.Gettext.dpgettext(
|
||||||
|
"static_pages",
|
||||||
|
"status interact error message - status not found",
|
||||||
|
"Could not find status"
|
||||||
|
)
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def remote_subscribe(conn, %{"nickname" => nick, "profile" => _}) do
|
||||||
|
show_subscribe_form(conn, %{"nickname" => nick})
|
||||||
|
end
|
||||||
|
|
||||||
|
def remote_subscribe(conn, %{"status_id" => id, "profile" => _}) do
|
||||||
|
show_subscribe_form(conn, %{"status_id" => id})
|
||||||
|
end
|
||||||
|
|
||||||
def remote_subscribe(conn, %{"user" => %{"nickname" => nick, "profile" => profile}}) do
|
def remote_subscribe(conn, %{"user" => %{"nickname" => nick, "profile" => profile}}) do
|
||||||
with {:ok, %{"subscribe_address" => template}} <- WebFinger.finger(profile),
|
with {:ok, %{"subscribe_address" => template}} <- WebFinger.finger(profile),
|
||||||
%User{ap_id: ap_id} <- User.get_cached_by_nickname(nick) do
|
%User{ap_id: ap_id} <- User.get_cached_by_nickname(nick) do
|
||||||
|
@ -69,7 +119,33 @@ def remote_subscribe(conn, %{"user" => %{"nickname" => nick, "profile" => profil
|
||||||
render(conn, "subscribe.html", %{
|
render(conn, "subscribe.html", %{
|
||||||
nickname: nick,
|
nickname: nick,
|
||||||
avatar: nil,
|
avatar: nil,
|
||||||
error: "Something went wrong."
|
error:
|
||||||
|
Pleroma.Web.Gettext.dpgettext(
|
||||||
|
"static_pages",
|
||||||
|
"remote follow error message - unknown error",
|
||||||
|
"Something went wrong."
|
||||||
|
)
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def remote_subscribe(conn, %{"status" => %{"status_id" => id, "profile" => profile}}) do
|
||||||
|
with {:ok, %{"subscribe_address" => template}} <- WebFinger.finger(profile),
|
||||||
|
%Activity{} = activity <- Activity.get_by_id(id),
|
||||||
|
{:ok, ap_id} <- get_ap_id(activity) do
|
||||||
|
conn
|
||||||
|
|> Phoenix.Controller.redirect(external: String.replace(template, "{uri}", ap_id))
|
||||||
|
else
|
||||||
|
_e ->
|
||||||
|
render(conn, "status_interact.html", %{
|
||||||
|
status_id: id,
|
||||||
|
avatar: nil,
|
||||||
|
error:
|
||||||
|
Pleroma.Web.Gettext.dpgettext(
|
||||||
|
"static_pages",
|
||||||
|
"status interact error message - unknown error",
|
||||||
|
"Something went wrong."
|
||||||
|
)
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -83,6 +159,15 @@ def remote_interaction(%{body_params: %{ap_id: ap_id, profile: profile}} = conn,
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp get_ap_id(activity) do
|
||||||
|
object = Pleroma.Object.normalize(activity, fetch: false)
|
||||||
|
|
||||||
|
case object do
|
||||||
|
%{data: %{"id" => ap_id}} -> {:ok, ap_id}
|
||||||
|
_ -> {:no_ap_id, nil}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def frontend_configurations(conn, _params) do
|
def frontend_configurations(conn, _params) do
|
||||||
render(conn, "frontend_configurations.json")
|
render(conn, "frontend_configurations.json")
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,7 +4,9 @@
|
||||||
|
|
||||||
defmodule Pleroma.Web.TwitterAPI.UtilView do
|
defmodule Pleroma.Web.TwitterAPI.UtilView do
|
||||||
use Pleroma.Web, :view
|
use Pleroma.Web, :view
|
||||||
|
import Phoenix.HTML
|
||||||
import Phoenix.HTML.Form
|
import Phoenix.HTML.Form
|
||||||
|
import Phoenix.HTML.Link
|
||||||
alias Pleroma.Config
|
alias Pleroma.Config
|
||||||
alias Pleroma.Web.Endpoint
|
alias Pleroma.Web.Endpoint
|
||||||
alias Pleroma.Web.Gettext
|
alias Pleroma.Web.Gettext
|
||||||
|
|
|
@ -233,6 +233,102 @@ test "it renders form with error when user not found", %{conn: conn} do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "POST /main/ostatus - remote_subscribe/2 - with statuses" do
|
||||||
|
setup do: clear_config([:instance, :federating], true)
|
||||||
|
|
||||||
|
test "renders subscribe form", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
status = insert(:note_activity, %{user: user})
|
||||||
|
status_id = status.id
|
||||||
|
|
||||||
|
assert is_binary(status_id)
|
||||||
|
|
||||||
|
response =
|
||||||
|
conn
|
||||||
|
|> post("/main/ostatus", %{"status_id" => status_id, "profile" => ""})
|
||||||
|
|> response(:ok)
|
||||||
|
|
||||||
|
refute response =~ "Could not find status"
|
||||||
|
assert response =~ "Interacting with"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "renders subscribe form with error when status not found", %{conn: conn} do
|
||||||
|
response =
|
||||||
|
conn
|
||||||
|
|> post("/main/ostatus", %{"status_id" => "somerandomid", "profile" => ""})
|
||||||
|
|> response(:ok)
|
||||||
|
|
||||||
|
assert response =~ "Could not find status"
|
||||||
|
refute response =~ "Interacting with"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it redirect to webfinger url", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
status = insert(:note_activity, %{user: user})
|
||||||
|
status_id = status.id
|
||||||
|
status_ap_id = status.data["object"]
|
||||||
|
|
||||||
|
assert is_binary(status_id)
|
||||||
|
assert is_binary(status_ap_id)
|
||||||
|
|
||||||
|
user2 = insert(:user, ap_id: "shp@social.heldscal.la")
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> post("/main/ostatus", %{
|
||||||
|
"status" => %{"status_id" => status_id, "profile" => user2.ap_id}
|
||||||
|
})
|
||||||
|
|
||||||
|
assert redirected_to(conn) ==
|
||||||
|
"https://social.heldscal.la/main/ostatussub?profile=#{status_ap_id}"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it renders form with error when status not found", %{conn: conn} do
|
||||||
|
user2 = insert(:user, ap_id: "shp@social.heldscal.la")
|
||||||
|
|
||||||
|
response =
|
||||||
|
conn
|
||||||
|
|> post("/main/ostatus", %{
|
||||||
|
"status" => %{"status_id" => "somerandomid", "profile" => user2.ap_id}
|
||||||
|
})
|
||||||
|
|> response(:ok)
|
||||||
|
|
||||||
|
assert response =~ "Something went wrong."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "GET /main/ostatus - show_subscribe_form/2" do
|
||||||
|
setup do: clear_config([:instance, :federating], true)
|
||||||
|
|
||||||
|
test "it works with users", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
response =
|
||||||
|
conn
|
||||||
|
|> get("/main/ostatus", %{"nickname" => user.nickname})
|
||||||
|
|> response(:ok)
|
||||||
|
|
||||||
|
refute response =~ "Could not find user"
|
||||||
|
assert response =~ "Remotely follow #{user.nickname}"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it works with statuses", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
status = insert(:note_activity, %{user: user})
|
||||||
|
status_id = status.id
|
||||||
|
|
||||||
|
assert is_binary(status_id)
|
||||||
|
|
||||||
|
response =
|
||||||
|
conn
|
||||||
|
|> get("/main/ostatus", %{"status_id" => status_id})
|
||||||
|
|> response(:ok)
|
||||||
|
|
||||||
|
refute response =~ "Could not find status"
|
||||||
|
assert response =~ "Interacting with"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
test "it returns new captcha", %{conn: conn} do
|
test "it returns new captcha", %{conn: conn} do
|
||||||
with_mock Pleroma.Captcha,
|
with_mock Pleroma.Captcha,
|
||||||
new: fn -> "test_captcha" end do
|
new: fn -> "test_captcha" end do
|
||||||
|
|
Loading…
Reference in a new issue