### Environment
-* Installation type:
- - [ ] OTP
- - [ ] From source
+* Installation type (OTP or From Source):
* Pleroma version (could be found in the "Version" tab of settings in Pleroma-FE):
* Elixir version (`elixir -v` for from source installations, N/A for OTP):
* Operating system:
has been simplified down to `block_from_strangers`.
- **Breaking:** Notification Settings API option for hiding push notification
contents has been renamed to `hide_notification_contents`
+- Mastodon API: Added `pleroma.metadata.post_formats` to /api/v1/instance
</details>
<details>
<details>
<summary>API Changes</summary>
-- Mastodon API: Add pleroma.parents_visible field to statuses.
+
+- Mastodon API: Add pleroma.parent_visible field to statuses.
- Mastodon API: Extended `/api/v1/instance`.
- Mastodon API: Support for `include_types` in `/api/v1/notifications`.
- Mastodon API: Added `/api/v1/notifications/:id/dismiss` endpoint.
- Follow request notifications
<details>
<summary>API Changes</summary>
+
- Admin API: `GET /api/pleroma/admin/need_reboot`.
</details>
- **Breaking**: Using third party engines for user recommendation
<details>
<summary>API Changes</summary>
+
- **Breaking**: AdminAPI: migrate_from_db endpoint
</details>
- `pleroma.metadata.features`: A list of supported features
- `pleroma.metadata.federation`: The federation restrictions of this instance
- `pleroma.metadata.fields_limits`: A list of values detailing the length and count limitation for various instance-configurable fields.
+- `pleroma.metadata.post_formats`: A list of the allowed post format types
- `vapid_public_key`: The public key needed for push messages
## Markers
def response("/main/public") do
posts =
- ActivityPub.fetch_public_activities(%{"type" => ["Create"], "local_only" => true})
- |> render_activities
+ %{type: ["Create"], local_only: true}
+ |> ActivityPub.fetch_public_activities()
+ |> render_activities()
info("Welcome to the Public Timeline!") <> posts <> ".\r\n"
end
def response("/main/all") do
posts =
- ActivityPub.fetch_public_activities(%{"type" => ["Create"]})
- |> render_activities
+ %{type: ["Create"]}
+ |> ActivityPub.fetch_public_activities()
+ |> render_activities()
info("Welcome to the Federated Timeline!") <> posts <> ".\r\n"
end
def response("/users/" <> nickname) do
with %User{} = user <- User.get_cached_by_nickname(nickname) do
params = %{
- "type" => ["Create"],
- "actor_id" => user.ap_id
+ type: ["Create"],
+ actor_id: user.ap_id
}
activities =
- ActivityPub.fetch_public_activities(params)
- |> render_activities
+ params
+ |> ActivityPub.fetch_public_activities()
+ |> render_activities()
info("Posts by #{user.nickname}") <> activities <> ".\r\n"
else
request = build_request(method, headers, options, url, body, params)
adapter = Application.get_env(:tesla, :adapter)
- client = Tesla.client([Pleroma.HTTP.Middleware.FollowRedirects], adapter)
+
+ client = Tesla.client(adapter_middlewares(adapter), adapter)
maybe_limit(
fn ->
defp maybe_limit(fun, _, _) do
fun.()
end
+
+ defp adapter_middlewares(Tesla.Adapter.Gun) do
+ [Pleroma.HTTP.Middleware.FollowRedirects]
+ end
+
+ defp adapter_middlewares(_), do: []
end
"Accounts which follow the given account, if network is not hidden by the account owner.",
parameters: [
%Reference{"$ref": "#/components/parameters/accountIdOrNickname"},
+ Operation.parameter(:id, :query, :string, "ID of the resource owner"),
with_relationships_param() | pagination_params()
],
responses: %{
"Accounts which the given account is following, if network is not hidden by the account owner.",
parameters: [
%Reference{"$ref": "#/components/parameters/accountIdOrNickname"},
+ Operation.parameter(:id, :query, :string, "ID of the resource owner"),
with_relationships_param() | pagination_params()
],
responses: %{200 => Operation.response("Accounts", "application/json", array_of_accounts())}
account_activation_required: Keyword.get(instance, :account_activation_required),
features: features(),
federation: federation(),
- fields_limits: fields_limits()
+ fields_limits: fields_limits(),
+ post_formats: Config.get([:instance, :allowed_post_formats])
},
vapid_public_key: Keyword.get(Pleroma.Web.Push.vapid_config(), :public_key)
}
<%= form_for @conn, mfa_verify_path(@conn, :verify), [as: "mfa"], fn f -> %>
<div class="input">
<%= label f, :code, "Recovery code" %>
- <%= text_input f, :code %>
+ <%= text_input f, :code, [autocomplete: false, autocorrect: "off", autocapitalize: "off", autofocus: true, spellcheck: false] %>
<%= hidden_input f, :mfa_token, value: @mfa_token %>
<%= hidden_input f, :state, value: @state %>
<%= hidden_input f, :redirect_uri, value: @redirect_uri %>
<%= form_for @conn, mfa_verify_path(@conn, :verify), [as: "mfa"], fn f -> %>
<div class="input">
<%= label f, :code, "Authentication code" %>
- <%= text_input f, :code %>
+ <%= text_input f, :code, [autocomplete: false, autocorrect: "off", autocapitalize: "off", autofocus: true, pattern: "[0-9]*", spellcheck: false] %>
<%= hidden_input f, :mfa_token, value: @mfa_token %>
<%= hidden_input f, :state, value: @state %>
<%= hidden_input f, :redirect_uri, value: @redirect_uri %>
assert length(paginated) == 1
end
+
+ test "handles id gracefully", %{notes: notes} do
+ id = Enum.at(notes, 1).id |> Integer.to_string()
+
+ paginated =
+ Pagination.fetch_paginated(Object, %{
+ id: "9s99Hq44Cnv8PKBwWG",
+ max_id: id,
+ limit: 20,
+ offset: 0
+ })
+
+ assert length(paginated) == 1
+ end
end
describe "offset" do
alias Pleroma.Upload
setup do
+ File.cp!("test/fixtures/image.jpg", "test/fixtures/image_tmp.jpg")
+
upload_file = %Upload{
name: "an… image.jpg",
content_type: "image/jpg",
describe "put_file/1" do
test "put file to local folder" do
+ File.cp!("test/fixtures/image.jpg", "test/fixtures/image_tmp.jpg")
file_path = "local_upload/files/image.jpg"
file = %Pleroma.Upload{
describe "delete_file/1" do
test "deletes local file" do
+ File.cp!("test/fixtures/image.jpg", "test/fixtures/image_tmp.jpg")
file_path = "local_upload/files/image.jpg"
file = %Pleroma.Upload{
|> get("/api/v1/accounts/#{user.id}/followers?max_id=#{follower3_id}")
|> json_response_and_validate_schema(200)
+ assert [%{"id" => ^follower2_id}, %{"id" => ^follower1_id}] =
+ conn
+ |> get(
+ "/api/v1/accounts/#{user.id}/followers?id=#{user.id}&limit=20&max_id=#{
+ follower3_id
+ }"
+ )
+ |> json_response_and_validate_schema(200)
+
res_conn = get(conn, "/api/v1/accounts/#{user.id}/followers?limit=1&max_id=#{follower3_id}")
assert [%{"id" => ^follower2_id}] = json_response_and_validate_schema(res_conn, 200)
assert id2 == following2.id
assert id1 == following1.id
+ res_conn =
+ get(
+ conn,
+ "/api/v1/accounts/#{user.id}/following?id=#{user.id}&limit=20&max_id=#{following3.id}"
+ )
+
+ assert [%{"id" => id2}, %{"id" => id1}] = json_response_and_validate_schema(res_conn, 200)
+ assert id2 == following2.id
+ assert id1 == following1.id
+
res_conn =
get(conn, "/api/v1/accounts/#{user.id}/following?limit=1&max_id=#{following3.id}")