Merge branch 'feat/client_app_details' into 'develop'

Support application field

See merge request pleroma/pleroma!3311
This commit is contained in:
lain 2021-02-28 16:17:34 +00:00
commit e6a14e1cd1
11 changed files with 103 additions and 19 deletions

View file

@ -59,6 +59,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Ability to define custom HTTP headers per each frontend - Ability to define custom HTTP headers per each frontend
- MRF (`NoEmptyPolicy`): New MRF Policy which will deny empty statuses or statuses of only mentions from being created by local users - MRF (`NoEmptyPolicy`): New MRF Policy which will deny empty statuses or statuses of only mentions from being created by local users
- New users will receive a simple email confirming their registration if no other emails will be dispatched. (e.g., Welcome, Confirmation, or Approval Required) - New users will receive a simple email confirming their registration if no other emails will be dispatched. (e.g., Welcome, Confirmation, or Approval Required)
- The `application` metadata returned with statuses is no longer hardcoded. Apps that want to display these details will now have valid data for new posts after this change.
<details> <details>
<summary>API Changes</summary> <summary>API Changes</summary>

View file

@ -18,7 +18,8 @@ defmodule Pleroma.Constants do
"emoji", "emoji",
"context_id", "context_id",
"deleted_activity_id", "deleted_activity_id",
"pleroma_internal" "pleroma_internal",
"application"
] ]
) )

View file

@ -147,6 +147,7 @@ defmodule Pleroma.User do
field(:shared_inbox, :string) field(:shared_inbox, :string)
field(:accepts_chat_messages, :boolean, default: nil) field(:accepts_chat_messages, :boolean, default: nil)
field(:last_active_at, :naive_datetime) field(:last_active_at, :naive_datetime)
field(:disclose_client, :boolean, default: true)
embeds_one( embeds_one(
:notification_settings, :notification_settings,
@ -513,7 +514,8 @@ def update_changeset(struct, params \\ %{}) do
:pleroma_settings_store, :pleroma_settings_store,
:is_discoverable, :is_discoverable,
:actor_type, :actor_type,
:accepts_chat_messages :accepts_chat_messages,
:disclose_client
] ]
) )
|> unique_constraint(:nickname) |> unique_constraint(:nickname)

View file

@ -23,9 +23,10 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Status do
application: %Schema{ application: %Schema{
description: "The application used to post this status", description: "The application used to post this status",
type: :object, type: :object,
nullable: true,
properties: %{ properties: %{
name: %Schema{type: :string}, name: %Schema{type: :string},
website: %Schema{type: :string, nullable: true, format: :uri} website: %Schema{type: :string, format: :uri}
} }
}, },
bookmarked: %Schema{type: :boolean, description: "Have you bookmarked this status?"}, bookmarked: %Schema{type: :boolean, description: "Have you bookmarked this status?"},
@ -291,7 +292,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Status do
"url" => "http://localhost:4001/users/nick6", "url" => "http://localhost:4001/users/nick6",
"username" => "nick6" "username" => "nick6"
}, },
"application" => %{"name" => "Web", "website" => nil}, "application" => nil,
"bookmarked" => false, "bookmarked" => false,
"card" => nil, "card" => nil,
"content" => "foobar", "content" => "foobar",

View file

@ -190,6 +190,7 @@ defp object(draft) do
Utils.make_note_data(draft) Utils.make_note_data(draft)
|> Map.put("emoji", emoji) |> Map.put("emoji", emoji)
|> Map.put("source", draft.status) |> Map.put("source", draft.status)
|> Map.put("application", draft.params[:application])
%__MODULE__{draft | object: object} %__MODULE__{draft | object: object}
end end

View file

@ -21,6 +21,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
alias Pleroma.Web.CommonAPI alias Pleroma.Web.CommonAPI
alias Pleroma.Web.MastodonAPI.AccountView alias Pleroma.Web.MastodonAPI.AccountView
alias Pleroma.Web.MastodonAPI.ScheduledActivityView alias Pleroma.Web.MastodonAPI.ScheduledActivityView
alias Pleroma.Web.OAuth.Token
alias Pleroma.Web.Plugs.OAuthScopesPlug alias Pleroma.Web.Plugs.OAuthScopesPlug
alias Pleroma.Web.Plugs.RateLimiter alias Pleroma.Web.Plugs.RateLimiter
@ -138,7 +139,9 @@ def create(
_ _
) )
when not is_nil(scheduled_at) do when not is_nil(scheduled_at) do
params = Map.put(params, :in_reply_to_status_id, params[:in_reply_to_id]) params =
Map.put(params, :in_reply_to_status_id, params[:in_reply_to_id])
|> put_application(conn)
attrs = %{ attrs = %{
params: Map.new(params, fn {key, value} -> {to_string(key), value} end), params: Map.new(params, fn {key, value} -> {to_string(key), value} end),
@ -162,7 +165,9 @@ def create(
# Creates a regular status # Creates a regular status
def create(%{assigns: %{user: user}, body_params: %{status: _} = params} = conn, _) do def create(%{assigns: %{user: user}, body_params: %{status: _} = params} = conn, _) do
params = Map.put(params, :in_reply_to_status_id, params[:in_reply_to_id]) params =
Map.put(params, :in_reply_to_status_id, params[:in_reply_to_id])
|> put_application(conn)
with {:ok, activity} <- CommonAPI.post(user, params) do with {:ok, activity} <- CommonAPI.post(user, params) do
try_render(conn, "show.json", try_render(conn, "show.json",
@ -414,4 +419,15 @@ def bookmarks(%{assigns: %{user: user}} = conn, params) do
as: :activity as: :activity
) )
end end
defp put_application(params, %{assigns: %{token: %Token{user: %User{} = user} = token}} = _conn) do
if user.disclose_client do
%{client_name: client_name, website: website} = Repo.preload(token, :app).app
Map.put(params, :application, %{type: "Application", name: client_name, url: website})
else
Map.put(params, :application, nil)
end
end
defp put_application(params, _), do: Map.put(params, :application, nil)
end end

View file

@ -180,10 +180,7 @@ def render(
media_attachments: reblogged[:media_attachments] || [], media_attachments: reblogged[:media_attachments] || [],
mentions: mentions, mentions: mentions,
tags: reblogged[:tags] || [], tags: reblogged[:tags] || [],
application: %{ application: build_application(activity_object.data["application"]),
name: "Web",
website: nil
},
language: nil, language: nil,
emojis: [], emojis: [],
pleroma: %{ pleroma: %{
@ -348,10 +345,7 @@ def render("show.json", %{activity: %{data: %{"object" => _object}} = activity}
poll: render(PollView, "show.json", object: object, for: opts[:for]), poll: render(PollView, "show.json", object: object, for: opts[:for]),
mentions: mentions, mentions: mentions,
tags: build_tags(tags), tags: build_tags(tags),
application: %{ application: build_application(object.data["application"]),
name: "Web",
website: nil
},
language: nil, language: nil,
emojis: build_emojis(object.data["emoji"]), emojis: build_emojis(object.data["emoji"]),
pleroma: %{ pleroma: %{
@ -540,4 +534,8 @@ defp build_emoji_map(emoji, users, current_user) do
me: !!(current_user && current_user.ap_id in users) me: !!(current_user && current_user.ap_id in users)
} }
end end
@spec build_application(map() | nil) :: map() | nil
defp build_application(%{type: _type, name: name, url: url}), do: %{name: name, website: url}
defp build_application(_), do: nil
end end

View file

@ -0,0 +1,9 @@
defmodule Pleroma.Repo.Migrations.AddDiscloseClientToUsers do
use Ecto.Migration
def change do
alter table(:users) do
add(:disclose_client, :boolean, default: true)
end
end
end

View file

@ -202,7 +202,20 @@ test "it strips internal hashtag data" do
test "it strips internal fields" do test "it strips internal fields" do
user = insert(:user) user = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{status: "#2hu :firefox:"}) {:ok, activity} =
CommonAPI.post(user, %{
status: "#2hu :firefox:",
application: %{type: "Application", name: "TestClient", url: "https://pleroma.social"}
})
# Ensure injected application data made it into the activity
# as we don't have a Token to derive it from, otherwise it will
# be nil and the test will pass
assert %{
type: "Application",
name: "TestClient",
url: "https://pleroma.social"
} == activity.object.data["application"]
{:ok, modified} = Transmogrifier.prepare_outgoing(activity.data) {:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
@ -213,6 +226,7 @@ test "it strips internal fields" do
assert is_nil(modified["object"]["announcements"]) assert is_nil(modified["object"]["announcements"])
assert is_nil(modified["object"]["announcement_count"]) assert is_nil(modified["object"]["announcement_count"])
assert is_nil(modified["object"]["context_id"]) assert is_nil(modified["object"]["context_id"])
assert is_nil(modified["object"]["application"])
end end
test "it strips internal fields of article" do test "it strips internal fields of article" do

View file

@ -357,6 +357,50 @@ test "posting a direct status", %{conn: conn} do
assert activity.data["to"] == [user2.ap_id] assert activity.data["to"] == [user2.ap_id]
assert activity.data["cc"] == [] assert activity.data["cc"] == []
end end
test "discloses application metadata when enabled" do
user = insert(:user, disclose_client: true)
%{user: _user, token: token, conn: conn} = oauth_access(["write:statuses"], user: user)
%Pleroma.Web.OAuth.Token{
app: %Pleroma.Web.OAuth.App{
client_name: _app_name,
website: _app_website
}
} = token
result =
conn
|> put_req_header("content-type", "application/json")
|> post("/api/v1/statuses", %{
"status" => "cofe is my copilot"
})
assert %{
"content" => "cofe is my copilot",
"application" => %{
"name" => app_name,
"website" => app_website
}
} = json_response_and_validate_schema(result, 200)
end
test "hides application metadata when disabled" do
user = insert(:user, disclose_client: false)
%{user: _user, token: _token, conn: conn} = oauth_access(["write:statuses"], user: user)
result =
conn
|> put_req_header("content-type", "application/json")
|> post("/api/v1/statuses", %{
"status" => "club mate is my wingman"
})
assert %{
"content" => "club mate is my wingman",
"application" => nil
} = json_response_and_validate_schema(result, 200)
end
end end
describe "posting scheduled statuses" do describe "posting scheduled statuses" do

View file

@ -266,10 +266,7 @@ test "a note activity" do
url: "http://localhost:4001/tag/#{object_data["tag"]}" url: "http://localhost:4001/tag/#{object_data["tag"]}"
} }
], ],
application: %{ application: nil,
name: "Web",
website: nil
},
language: nil, language: nil,
emojis: [ emojis: [
%{ %{