Merge remote-tracking branch 'pleroma/develop' into merge-pleroma
Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
commit
bda8589f16
55 changed files with 563 additions and 132 deletions
21
CHANGELOG.md
21
CHANGELOG.md
|
@ -12,7 +12,28 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
- rel="me" was missing its cache
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
- BREAKING: Support for passwords generated with `crypt(3)` (Gnu Social migration artifact)
|
||||||
|
|
||||||
|
## 2.5.1
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Allow customizing instance languages
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Security: uploading HTTP endpoint can no longer create directories in the upload dir (internal APIs, like backup, still can do it.)
|
||||||
|
- ~ character in urls in Markdown posts are handled properly
|
||||||
|
- Exiftool upload filter will now ignore SVG files
|
||||||
|
- Fix `block_from_stranger` setting
|
||||||
|
- Fix rel="me"
|
||||||
|
- Docker images will now run properly
|
||||||
|
- Fix inproper content being cached in report content
|
||||||
|
- Notification filter on object content will not operate on the ones that inherently have no content
|
||||||
|
- ZWNJ and double dots in links are parsed properly for Plain-text posts
|
||||||
|
- OTP releases will work on systems with a newer libcrypt
|
||||||
|
- Errors when running Exiftool.ReadDescription filter will not be filled into the image description
|
||||||
|
|
||||||
## 2.5.0 - 2022-12-23
|
## 2.5.0 - 2022-12-23
|
||||||
|
|
||||||
|
|
|
@ -1080,6 +1080,15 @@
|
||||||
description:
|
description:
|
||||||
"Number of days for which users won't be able to migrate account again after successful migration.",
|
"Number of days for which users won't be able to migrate account again after successful migration.",
|
||||||
suggestions: [30]
|
suggestions: [30]
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
key: :languages,
|
||||||
|
type: {:list, :string},
|
||||||
|
description:
|
||||||
|
"Languages to be exposed in /api/v1/instance. Should be in the format of BCP47 language codes.",
|
||||||
|
suggestions: [
|
||||||
|
"en"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -6,7 +6,70 @@ defmodule Mix.Tasks.Pleroma.OpenapiSpec do
|
||||||
def run([path]) do
|
def run([path]) do
|
||||||
# Load Pleroma application to get version info
|
# Load Pleroma application to get version info
|
||||||
Application.load(:pleroma)
|
Application.load(:pleroma)
|
||||||
spec = Pleroma.Web.ApiSpec.spec(server_specific: false) |> Jason.encode!()
|
|
||||||
File.write(path, spec)
|
spec_json = Pleroma.Web.ApiSpec.spec(server_specific: false) |> Jason.encode!()
|
||||||
|
# to get rid of the structs
|
||||||
|
spec_regened = spec_json |> Jason.decode!()
|
||||||
|
|
||||||
|
check_specs!(spec_regened)
|
||||||
|
|
||||||
|
File.write(path, spec_json)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp check_specs!(spec) do
|
||||||
|
with :ok <- check_specs(spec) do
|
||||||
|
:ok
|
||||||
|
else
|
||||||
|
{_, errors} ->
|
||||||
|
IO.puts(IO.ANSI.format([:red, :bright, "Spec check failed, errors:"]))
|
||||||
|
Enum.map(errors, &IO.puts/1)
|
||||||
|
|
||||||
|
raise "Spec check failed"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_specs(spec) do
|
||||||
|
errors =
|
||||||
|
spec["paths"]
|
||||||
|
|> Enum.flat_map(fn {path, %{} = endpoints} ->
|
||||||
|
Enum.map(
|
||||||
|
endpoints,
|
||||||
|
fn {method, endpoint} ->
|
||||||
|
with :ok <- check_endpoint(spec, endpoint) do
|
||||||
|
:ok
|
||||||
|
else
|
||||||
|
error ->
|
||||||
|
"#{endpoint["operationId"]} (#{method} #{path}): #{error}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
)
|
||||||
|
|> Enum.reject(fn res -> res == :ok end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
if errors == [] do
|
||||||
|
:ok
|
||||||
|
else
|
||||||
|
{:error, errors}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp check_endpoint(spec, endpoint) do
|
||||||
|
valid_tags = available_tags(spec)
|
||||||
|
|
||||||
|
with {_, [_ | _] = tags} <- {:tags, endpoint["tags"]},
|
||||||
|
{_, []} <- {:unavailable, Enum.reject(tags, &(&1 in valid_tags))} do
|
||||||
|
:ok
|
||||||
|
else
|
||||||
|
{:tags, _} ->
|
||||||
|
"No tags specified"
|
||||||
|
|
||||||
|
{:unavailable, tags} ->
|
||||||
|
"Tags #{inspect(tags)} not available. Please add it in \"x-tagGroups\" in Pleroma.Web.ApiSpec"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp available_tags(spec) do
|
||||||
|
spec["x-tagGroups"]
|
||||||
|
|> Enum.flat_map(fn %{"tags" => tags} -> tags end)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -183,6 +183,7 @@ defp exclude_filtered(query, user) do
|
||||||
from([_n, a, o] in query,
|
from([_n, a, o] in query,
|
||||||
where:
|
where:
|
||||||
fragment("not(?->>'content' ~* ?)", o.data, ^regex) or
|
fragment("not(?->>'content' ~* ?)", o.data, ^regex) or
|
||||||
|
fragment("?->>'content' is null", o.data) or
|
||||||
fragment("?->>'actor' = ?", o.data, ^user.ap_id)
|
fragment("?->>'actor' = ?", o.data, ^user.ap_id)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
@ -816,7 +817,7 @@ def skip?(
|
||||||
cond do
|
cond do
|
||||||
opts[:type] == "poll" -> false
|
opts[:type] == "poll" -> false
|
||||||
user.ap_id == actor -> false
|
user.ap_id == actor -> false
|
||||||
!User.following?(follower, user) -> true
|
!User.following?(user, follower) -> true
|
||||||
true -> false
|
true -> false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -33,7 +33,10 @@ defp read_when_empty(current_description, _, _) when is_binary(current_descripti
|
||||||
defp read_when_empty(_, file, tag) do
|
defp read_when_empty(_, file, tag) do
|
||||||
try do
|
try do
|
||||||
{tag_content, 0} =
|
{tag_content, 0} =
|
||||||
System.cmd("exiftool", ["-b", "-s3", tag, file], stderr_to_stdout: true, parallelism: true)
|
System.cmd("exiftool", ["-b", "-s3", tag, file],
|
||||||
|
stderr_to_stdout: false,
|
||||||
|
parallelism: true
|
||||||
|
)
|
||||||
|
|
||||||
tag_content = String.trim(tag_content)
|
tag_content = String.trim(tag_content)
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ def extract_report_info(
|
||||||
|
|
||||||
defp make_fake_activity(act, user) do
|
defp make_fake_activity(act, user) do
|
||||||
%Activity{
|
%Activity{
|
||||||
id: "pleroma:fake",
|
id: "pleroma:fake:#{act["id"]}",
|
||||||
data: %{
|
data: %{
|
||||||
"actor" => user.ap_id,
|
"actor" => user.ap_id,
|
||||||
"type" => "Create",
|
"type" => "Create",
|
||||||
|
|
|
@ -95,7 +95,8 @@ def spec(opts \\ []) do
|
||||||
"Relays",
|
"Relays",
|
||||||
"Report managment",
|
"Report managment",
|
||||||
"Status administration",
|
"Status administration",
|
||||||
"User administration"
|
"User administration",
|
||||||
|
"Announcement management"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
%{"name" => "Applications", "tags" => ["Applications", "Push subscriptions"]},
|
%{"name" => "Applications", "tags" => ["Applications", "Push subscriptions"]},
|
||||||
|
@ -110,10 +111,12 @@ def spec(opts \\ []) do
|
||||||
"Follow requests",
|
"Follow requests",
|
||||||
"Mascot",
|
"Mascot",
|
||||||
"Markers",
|
"Markers",
|
||||||
"Notifications"
|
"Notifications",
|
||||||
|
"Filters",
|
||||||
|
"Settings"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
%{"name" => "Instance", "tags" => ["Custom emojis"]},
|
%{"name" => "Instance", "tags" => ["Custom emojis", "Instance misc"]},
|
||||||
%{"name" => "Messaging", "tags" => ["Chats", "Conversations"]},
|
%{"name" => "Messaging", "tags" => ["Chats", "Conversations"]},
|
||||||
%{
|
%{
|
||||||
"name" => "Statuses",
|
"name" => "Statuses",
|
||||||
|
@ -125,10 +128,21 @@ def spec(opts \\ []) do
|
||||||
"Retrieve status information",
|
"Retrieve status information",
|
||||||
"Scheduled statuses",
|
"Scheduled statuses",
|
||||||
"Search",
|
"Search",
|
||||||
"Status actions"
|
"Status actions",
|
||||||
|
"Media attachments"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
%{"name" => "Miscellaneous", "tags" => ["Emoji packs", "Reports", "Suggestions"]}
|
%{
|
||||||
|
"name" => "Miscellaneous",
|
||||||
|
"tags" => [
|
||||||
|
"Emoji packs",
|
||||||
|
"Reports",
|
||||||
|
"Suggestions",
|
||||||
|
"Announcements",
|
||||||
|
"Remote interaction",
|
||||||
|
"Others"
|
||||||
|
]
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -458,7 +458,7 @@ def blocks_operation do
|
||||||
operationId: "AccountController.blocks",
|
operationId: "AccountController.blocks",
|
||||||
description: "View your blocks. See also accounts/:id/{block,unblock}",
|
description: "View your blocks. See also accounts/:id/{block,unblock}",
|
||||||
security: [%{"oAuth" => ["read:blocks"]}],
|
security: [%{"oAuth" => ["read:blocks"]}],
|
||||||
parameters: pagination_params(),
|
parameters: [with_relationships_param() | pagination_params()],
|
||||||
responses: %{
|
responses: %{
|
||||||
200 => Operation.response("Accounts", "application/json", array_of_accounts())
|
200 => Operation.response("Accounts", "application/json", array_of_accounts())
|
||||||
}
|
}
|
||||||
|
@ -467,7 +467,7 @@ def blocks_operation do
|
||||||
|
|
||||||
def lookup_operation do
|
def lookup_operation do
|
||||||
%Operation{
|
%Operation{
|
||||||
tags: ["Account lookup"],
|
tags: ["Retrieve account information"],
|
||||||
summary: "Find a user by nickname",
|
summary: "Find a user by nickname",
|
||||||
operationId: "AccountController.lookup",
|
operationId: "AccountController.lookup",
|
||||||
parameters: [
|
parameters: [
|
||||||
|
|
|
@ -17,7 +17,7 @@ def open_api_operation(action) do
|
||||||
|
|
||||||
def index_operation do
|
def index_operation do
|
||||||
%Operation{
|
%Operation{
|
||||||
tags: ["Announcement managment"],
|
tags: ["Announcement management"],
|
||||||
summary: "Retrieve a list of announcements",
|
summary: "Retrieve a list of announcements",
|
||||||
operationId: "AdminAPI.AnnouncementController.index",
|
operationId: "AdminAPI.AnnouncementController.index",
|
||||||
security: [%{"oAuth" => ["admin:read"]}],
|
security: [%{"oAuth" => ["admin:read"]}],
|
||||||
|
@ -46,7 +46,7 @@ def index_operation do
|
||||||
|
|
||||||
def show_operation do
|
def show_operation do
|
||||||
%Operation{
|
%Operation{
|
||||||
tags: ["Announcement managment"],
|
tags: ["Announcement management"],
|
||||||
summary: "Display one announcement",
|
summary: "Display one announcement",
|
||||||
operationId: "AdminAPI.AnnouncementController.show",
|
operationId: "AdminAPI.AnnouncementController.show",
|
||||||
security: [%{"oAuth" => ["admin:read"]}],
|
security: [%{"oAuth" => ["admin:read"]}],
|
||||||
|
@ -69,7 +69,7 @@ def show_operation do
|
||||||
|
|
||||||
def delete_operation do
|
def delete_operation do
|
||||||
%Operation{
|
%Operation{
|
||||||
tags: ["Announcement managment"],
|
tags: ["Announcement management"],
|
||||||
summary: "Delete one announcement",
|
summary: "Delete one announcement",
|
||||||
operationId: "AdminAPI.AnnouncementController.delete",
|
operationId: "AdminAPI.AnnouncementController.delete",
|
||||||
security: [%{"oAuth" => ["admin:write"]}],
|
security: [%{"oAuth" => ["admin:write"]}],
|
||||||
|
@ -92,7 +92,7 @@ def delete_operation do
|
||||||
|
|
||||||
def create_operation do
|
def create_operation do
|
||||||
%Operation{
|
%Operation{
|
||||||
tags: ["Announcement managment"],
|
tags: ["Announcement management"],
|
||||||
summary: "Create one announcement",
|
summary: "Create one announcement",
|
||||||
operationId: "AdminAPI.AnnouncementController.create",
|
operationId: "AdminAPI.AnnouncementController.create",
|
||||||
security: [%{"oAuth" => ["admin:write"]}],
|
security: [%{"oAuth" => ["admin:write"]}],
|
||||||
|
@ -107,7 +107,7 @@ def create_operation do
|
||||||
|
|
||||||
def change_operation do
|
def change_operation do
|
||||||
%Operation{
|
%Operation{
|
||||||
tags: ["Announcement managment"],
|
tags: ["Announcement management"],
|
||||||
summary: "Change one announcement",
|
summary: "Change one announcement",
|
||||||
operationId: "AdminAPI.AnnouncementController.change",
|
operationId: "AdminAPI.AnnouncementController.change",
|
||||||
security: [%{"oAuth" => ["admin:write"]}],
|
security: [%{"oAuth" => ["admin:write"]}],
|
||||||
|
|
|
@ -70,7 +70,7 @@ def index_operation do
|
||||||
|
|
||||||
def show_operation do
|
def show_operation do
|
||||||
%Operation{
|
%Operation{
|
||||||
tags: ["Status adminitration)"],
|
tags: ["Status administration"],
|
||||||
summary: "Get status",
|
summary: "Get status",
|
||||||
operationId: "AdminAPI.StatusController.show",
|
operationId: "AdminAPI.StatusController.show",
|
||||||
parameters: [id_param() | admin_api_params()],
|
parameters: [id_param() | admin_api_params()],
|
||||||
|
@ -84,7 +84,7 @@ def show_operation do
|
||||||
|
|
||||||
def update_operation do
|
def update_operation do
|
||||||
%Operation{
|
%Operation{
|
||||||
tags: ["Status adminitration)"],
|
tags: ["Status administration"],
|
||||||
summary: "Change the scope of a status",
|
summary: "Change the scope of a status",
|
||||||
operationId: "AdminAPI.StatusController.update",
|
operationId: "AdminAPI.StatusController.update",
|
||||||
parameters: [id_param() | admin_api_params()],
|
parameters: [id_param() | admin_api_params()],
|
||||||
|
@ -99,7 +99,7 @@ def update_operation do
|
||||||
|
|
||||||
def delete_operation do
|
def delete_operation do
|
||||||
%Operation{
|
%Operation{
|
||||||
tags: ["Status adminitration)"],
|
tags: ["Status administration"],
|
||||||
summary: "Delete status",
|
summary: "Delete status",
|
||||||
operationId: "AdminAPI.StatusController.delete",
|
operationId: "AdminAPI.StatusController.delete",
|
||||||
parameters: [id_param() | admin_api_params()],
|
parameters: [id_param() | admin_api_params()],
|
||||||
|
@ -143,7 +143,7 @@ def admin_account do
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
tags: %Schema{type: :string},
|
tags: %Schema{type: :string},
|
||||||
is_confirmed: %Schema{type: :string}
|
is_confirmed: %Schema{type: :boolean}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
|
@ -15,7 +15,7 @@ def open_api_operation(action) do
|
||||||
|
|
||||||
def index_operation do
|
def index_operation do
|
||||||
%Operation{
|
%Operation{
|
||||||
tags: ["Announcement"],
|
tags: ["Announcements"],
|
||||||
summary: "Retrieve a list of announcements",
|
summary: "Retrieve a list of announcements",
|
||||||
operationId: "MastodonAPI.AnnouncementController.index",
|
operationId: "MastodonAPI.AnnouncementController.index",
|
||||||
security: [%{"oAuth" => []}],
|
security: [%{"oAuth" => []}],
|
||||||
|
@ -28,7 +28,7 @@ def index_operation do
|
||||||
|
|
||||||
def mark_read_operation do
|
def mark_read_operation do
|
||||||
%Operation{
|
%Operation{
|
||||||
tags: ["Announcement"],
|
tags: ["Announcements"],
|
||||||
summary: "Mark one announcement as read",
|
summary: "Mark one announcement as read",
|
||||||
operationId: "MastodonAPI.AnnouncementController.mark_read",
|
operationId: "MastodonAPI.AnnouncementController.mark_read",
|
||||||
security: [%{"oAuth" => ["write:accounts"]}],
|
security: [%{"oAuth" => ["write:accounts"]}],
|
||||||
|
|
|
@ -17,7 +17,7 @@ def open_api_operation(action) do
|
||||||
|
|
||||||
def index_operation do
|
def index_operation do
|
||||||
%Operation{
|
%Operation{
|
||||||
tags: ["Directory"],
|
tags: ["Others"],
|
||||||
summary: "Profile directory",
|
summary: "Profile directory",
|
||||||
operationId: "DirectoryController.index",
|
operationId: "DirectoryController.index",
|
||||||
parameters:
|
parameters:
|
||||||
|
|
|
@ -13,7 +13,7 @@ def open_api_operation(action) do
|
||||||
|
|
||||||
def show_operation do
|
def show_operation do
|
||||||
%Operation{
|
%Operation{
|
||||||
tags: ["Instance"],
|
tags: ["Instance misc"],
|
||||||
summary: "Retrieve instance information",
|
summary: "Retrieve instance information",
|
||||||
description: "Information about the server",
|
description: "Information about the server",
|
||||||
operationId: "InstanceController.show",
|
operationId: "InstanceController.show",
|
||||||
|
@ -37,7 +37,7 @@ def show2_operation do
|
||||||
|
|
||||||
def peers_operation do
|
def peers_operation do
|
||||||
%Operation{
|
%Operation{
|
||||||
tags: ["Instance"],
|
tags: ["Instance misc"],
|
||||||
summary: "Retrieve list of known instances",
|
summary: "Retrieve list of known instances",
|
||||||
operationId: "InstanceController.peers",
|
operationId: "InstanceController.peers",
|
||||||
responses: %{
|
responses: %{
|
||||||
|
|
|
@ -133,7 +133,11 @@ defp name_param do
|
||||||
defp files_object do
|
defp files_object do
|
||||||
%Schema{
|
%Schema{
|
||||||
type: :object,
|
type: :object,
|
||||||
additionalProperties: %Schema{type: :string},
|
additionalProperties: %Schema{
|
||||||
|
type: :string,
|
||||||
|
description: "Filename of the emoji",
|
||||||
|
extensions: %{"x-additionalPropertiesName": "Emoji name"}
|
||||||
|
},
|
||||||
description: "Object with emoji names as keys and filenames as values"
|
description: "Object with emoji names as keys and filenames as values"
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
|
@ -227,13 +227,29 @@ defp ok_response do
|
||||||
|
|
||||||
defp emoji_packs_response do
|
defp emoji_packs_response do
|
||||||
Operation.response(
|
Operation.response(
|
||||||
"Object with pack names as keys and pack contents as values",
|
"Emoji packs and the count",
|
||||||
"application/json",
|
"application/json",
|
||||||
%Schema{
|
%Schema{
|
||||||
type: :object,
|
type: :object,
|
||||||
additionalProperties: emoji_pack(),
|
properties: %{
|
||||||
|
packs: %Schema{
|
||||||
|
type: :object,
|
||||||
|
description: "Object with pack names as keys and pack contents as values",
|
||||||
|
additionalProperties: %Schema{
|
||||||
|
emoji_pack()
|
||||||
|
| extensions: %{"x-additionalPropertiesName": "Pack name"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
count: %Schema{
|
||||||
|
type: :integer,
|
||||||
|
description: "Number of emoji packs"
|
||||||
|
}
|
||||||
|
},
|
||||||
example: %{
|
example: %{
|
||||||
"emojos" => emoji_pack().example
|
"packs" => %{
|
||||||
|
"emojos" => emoji_pack().example
|
||||||
|
},
|
||||||
|
"count" => 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -274,7 +290,11 @@ defp emoji_pack do
|
||||||
defp files_object do
|
defp files_object do
|
||||||
%Schema{
|
%Schema{
|
||||||
type: :object,
|
type: :object,
|
||||||
additionalProperties: %Schema{type: :string},
|
additionalProperties: %Schema{
|
||||||
|
type: :string,
|
||||||
|
description: "Filename",
|
||||||
|
extensions: %{"x-additionalPropertiesName": "Emoji name"}
|
||||||
|
},
|
||||||
description: "Object with emoji names as keys and filenames as values"
|
description: "Object with emoji names as keys and filenames as values"
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
|
@ -13,7 +13,7 @@ def open_api_operation(action) do
|
||||||
|
|
||||||
def show_operation do
|
def show_operation do
|
||||||
%Operation{
|
%Operation{
|
||||||
tags: ["Instance"],
|
tags: ["Instance misc"],
|
||||||
summary: "Retrieve federation status",
|
summary: "Retrieve federation status",
|
||||||
description: "Information about instances deemed unreachable by the server",
|
description: "Information about instances deemed unreachable by the server",
|
||||||
operationId: "PleromaInstances.show",
|
operationId: "PleromaInstances.show",
|
||||||
|
|
|
@ -473,7 +473,7 @@ def bookmarks_operation do
|
||||||
|
|
||||||
def show_history_operation do
|
def show_history_operation do
|
||||||
%Operation{
|
%Operation{
|
||||||
tags: ["Retrieve status history"],
|
tags: ["Retrieve status information"],
|
||||||
summary: "Status history",
|
summary: "Status history",
|
||||||
description: "View history of a status",
|
description: "View history of a status",
|
||||||
operationId: "StatusController.show_history",
|
operationId: "StatusController.show_history",
|
||||||
|
@ -490,7 +490,7 @@ def show_history_operation do
|
||||||
|
|
||||||
def show_source_operation do
|
def show_source_operation do
|
||||||
%Operation{
|
%Operation{
|
||||||
tags: ["Retrieve status source"],
|
tags: ["Retrieve status information"],
|
||||||
summary: "Status source",
|
summary: "Status source",
|
||||||
description: "View source of a status",
|
description: "View source of a status",
|
||||||
operationId: "StatusController.show_source",
|
operationId: "StatusController.show_source",
|
||||||
|
@ -507,7 +507,7 @@ def show_source_operation do
|
||||||
|
|
||||||
def update_operation do
|
def update_operation do
|
||||||
%Operation{
|
%Operation{
|
||||||
tags: ["Update status"],
|
tags: ["Status actions"],
|
||||||
summary: "Update status",
|
summary: "Update status",
|
||||||
description: "Change the content of a status",
|
description: "Change the content of a status",
|
||||||
operationId: "StatusController.update",
|
operationId: "StatusController.update",
|
||||||
|
|
|
@ -17,7 +17,7 @@ def open_api_operation(action) do
|
||||||
|
|
||||||
def emoji_operation do
|
def emoji_operation do
|
||||||
%Operation{
|
%Operation{
|
||||||
tags: ["Emojis"],
|
tags: ["Custom emojis"],
|
||||||
summary: "List all custom emojis",
|
summary: "List all custom emojis",
|
||||||
operationId: "UtilController.emoji",
|
operationId: "UtilController.emoji",
|
||||||
parameters: [],
|
parameters: [],
|
||||||
|
@ -30,7 +30,8 @@ def emoji_operation do
|
||||||
properties: %{
|
properties: %{
|
||||||
image_url: %Schema{type: :string},
|
image_url: %Schema{type: :string},
|
||||||
tags: %Schema{type: :array, items: %Schema{type: :string}}
|
tags: %Schema{type: :array, items: %Schema{type: :string}}
|
||||||
}
|
},
|
||||||
|
extensions: %{"x-additionalPropertiesName": "Emoji name"}
|
||||||
},
|
},
|
||||||
example: %{
|
example: %{
|
||||||
"firefox" => %{
|
"firefox" => %{
|
||||||
|
@ -45,7 +46,7 @@ def emoji_operation do
|
||||||
|
|
||||||
def frontend_configurations_operation do
|
def frontend_configurations_operation do
|
||||||
%Operation{
|
%Operation{
|
||||||
tags: ["Configuration"],
|
tags: ["Others"],
|
||||||
summary: "Dump frontend configurations",
|
summary: "Dump frontend configurations",
|
||||||
operationId: "UtilController.frontend_configurations",
|
operationId: "UtilController.frontend_configurations",
|
||||||
parameters: [],
|
parameters: [],
|
||||||
|
@ -53,7 +54,12 @@ def frontend_configurations_operation do
|
||||||
200 =>
|
200 =>
|
||||||
Operation.response("List", "application/json", %Schema{
|
Operation.response("List", "application/json", %Schema{
|
||||||
type: :object,
|
type: :object,
|
||||||
additionalProperties: %Schema{type: :object}
|
additionalProperties: %Schema{
|
||||||
|
type: :object,
|
||||||
|
description:
|
||||||
|
"Opaque object representing the instance-wide configuration for the frontend",
|
||||||
|
extensions: %{"x-additionalPropertiesName": "Frontend name"}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -132,7 +138,7 @@ defp change_email_request do
|
||||||
|
|
||||||
def update_notificaton_settings_operation do
|
def update_notificaton_settings_operation do
|
||||||
%Operation{
|
%Operation{
|
||||||
tags: ["Accounts"],
|
tags: ["Settings"],
|
||||||
summary: "Update Notification Settings",
|
summary: "Update Notification Settings",
|
||||||
security: [%{"oAuth" => ["write:accounts"]}],
|
security: [%{"oAuth" => ["write:accounts"]}],
|
||||||
operationId: "UtilController.update_notificaton_settings",
|
operationId: "UtilController.update_notificaton_settings",
|
||||||
|
@ -207,6 +213,7 @@ def captcha_operation do
|
||||||
%Operation{
|
%Operation{
|
||||||
summary: "Get a captcha",
|
summary: "Get a captcha",
|
||||||
operationId: "UtilController.captcha",
|
operationId: "UtilController.captcha",
|
||||||
|
tags: ["Others"],
|
||||||
parameters: [],
|
parameters: [],
|
||||||
responses: %{
|
responses: %{
|
||||||
200 => Operation.response("Success", "application/json", %Schema{type: :object})
|
200 => Operation.response("Success", "application/json", %Schema{type: :object})
|
||||||
|
@ -357,7 +364,7 @@ defp delete_alias_request do
|
||||||
|
|
||||||
def healthcheck_operation do
|
def healthcheck_operation do
|
||||||
%Operation{
|
%Operation{
|
||||||
tags: ["Accounts"],
|
tags: ["Others"],
|
||||||
summary: "Quick status check on the instance",
|
summary: "Quick status check on the instance",
|
||||||
security: [%{"oAuth" => ["write:accounts"]}],
|
security: [%{"oAuth" => ["write:accounts"]}],
|
||||||
operationId: "UtilController.healthcheck",
|
operationId: "UtilController.healthcheck",
|
||||||
|
@ -372,7 +379,7 @@ def healthcheck_operation do
|
||||||
|
|
||||||
def remote_subscribe_operation do
|
def remote_subscribe_operation do
|
||||||
%Operation{
|
%Operation{
|
||||||
tags: ["Accounts"],
|
tags: ["Remote interaction"],
|
||||||
summary: "Remote Subscribe",
|
summary: "Remote Subscribe",
|
||||||
operationId: "UtilController.remote_subscribe",
|
operationId: "UtilController.remote_subscribe",
|
||||||
parameters: [],
|
parameters: [],
|
||||||
|
@ -382,7 +389,7 @@ def remote_subscribe_operation do
|
||||||
|
|
||||||
def remote_interaction_operation do
|
def remote_interaction_operation do
|
||||||
%Operation{
|
%Operation{
|
||||||
tags: ["Accounts"],
|
tags: ["Remote interaction"],
|
||||||
summary: "Remote interaction",
|
summary: "Remote interaction",
|
||||||
operationId: "UtilController.remote_interaction",
|
operationId: "UtilController.remote_interaction",
|
||||||
requestBody: request_body("Parameters", remote_interaction_request(), required: true),
|
requestBody: request_body("Parameters", remote_interaction_request(), required: true),
|
||||||
|
@ -408,7 +415,7 @@ defp remote_interaction_request do
|
||||||
|
|
||||||
def show_subscribe_form_operation do
|
def show_subscribe_form_operation do
|
||||||
%Operation{
|
%Operation{
|
||||||
tags: ["Accounts"],
|
tags: ["Remote interaction"],
|
||||||
summary: "Show remote subscribe form",
|
summary: "Show remote subscribe form",
|
||||||
operationId: "UtilController.show_subscribe_form",
|
operationId: "UtilController.show_subscribe_form",
|
||||||
parameters: [],
|
parameters: [],
|
||||||
|
|
|
@ -145,7 +145,11 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Status do
|
||||||
properties: %{
|
properties: %{
|
||||||
content: %Schema{
|
content: %Schema{
|
||||||
type: :object,
|
type: :object,
|
||||||
additionalProperties: %Schema{type: :string},
|
additionalProperties: %Schema{
|
||||||
|
type: :string,
|
||||||
|
description: "Alternate representation in the MIME type specified",
|
||||||
|
extensions: %{"x-additionalPropertiesName": "MIME type"}
|
||||||
|
},
|
||||||
description:
|
description:
|
||||||
"A map consisting of alternate representations of the `content` property with the key being it's mimetype. Currently the only alternate representation supported is `text/plain`"
|
"A map consisting of alternate representations of the `content` property with the key being it's mimetype. Currently the only alternate representation supported is `text/plain`"
|
||||||
},
|
},
|
||||||
|
@ -215,7 +219,11 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Status do
|
||||||
},
|
},
|
||||||
spoiler_text: %Schema{
|
spoiler_text: %Schema{
|
||||||
type: :object,
|
type: :object,
|
||||||
additionalProperties: %Schema{type: :string},
|
additionalProperties: %Schema{
|
||||||
|
type: :string,
|
||||||
|
description: "Alternate representation in the MIME type specified",
|
||||||
|
extensions: %{"x-additionalPropertiesName": "MIME type"}
|
||||||
|
},
|
||||||
description:
|
description:
|
||||||
"A map consisting of alternate representations of the `spoiler_text` property with the key being it's mimetype. Currently the only alternate representation supported is `text/plain`."
|
"A map consisting of alternate representations of the `spoiler_text` property with the key being it's mimetype. Currently the only alternate representation supported is `text/plain`."
|
||||||
},
|
},
|
||||||
|
|
|
@ -6,7 +6,6 @@ defmodule Pleroma.Web.Feed.FeedView do
|
||||||
use Phoenix.HTML
|
use Phoenix.HTML
|
||||||
use Pleroma.Web, :view
|
use Pleroma.Web, :view
|
||||||
|
|
||||||
alias Pleroma.Formatter
|
|
||||||
alias Pleroma.Object
|
alias Pleroma.Object
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.Gettext
|
alias Pleroma.Web.Gettext
|
||||||
|
@ -72,7 +71,9 @@ def logo(user) do
|
||||||
|
|
||||||
def last_activity(activities), do: List.last(activities)
|
def last_activity(activities), do: List.last(activities)
|
||||||
|
|
||||||
def activity_title(%{"content" => content, "summary" => summary} = data, opts \\ %{}) do
|
def activity_title(%{"content" => content} = data, opts \\ %{}) do
|
||||||
|
summary = Map.get(data, "summary", "")
|
||||||
|
|
||||||
title =
|
title =
|
||||||
cond do
|
cond do
|
||||||
summary != "" -> summary
|
summary != "" -> summary
|
||||||
|
@ -81,9 +82,8 @@ def activity_title(%{"content" => content, "summary" => summary} = data, opts \\
|
||||||
end
|
end
|
||||||
|
|
||||||
title
|
title
|
||||||
|> Pleroma.Web.Metadata.Utils.scrub_html()
|
|> Pleroma.Web.Metadata.Utils.scrub_html_and_truncate(opts[:max_length], opts[:omission])
|
||||||
|> Pleroma.Emoji.Formatter.demojify()
|
|> HtmlEntities.encode()
|
||||||
|> Formatter.truncate(opts[:max_length], opts[:omission])
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def activity_description(data) do
|
def activity_description(data) do
|
||||||
|
|
|
@ -544,7 +544,12 @@ def blocks(%{assigns: %{user: user}} = conn, params) do
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> add_link_headers(users)
|
|> add_link_headers(users)
|
||||||
|> render("index.json", users: users, for: user, as: :user)
|
|> render("index.json",
|
||||||
|
users: users,
|
||||||
|
for: user,
|
||||||
|
as: :user,
|
||||||
|
embed_relationships: embed_relationships?(params)
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc "GET /api/v1/accounts/lookup"
|
@doc "GET /api/v1/accounts/lookup"
|
||||||
|
|
|
@ -34,7 +34,7 @@ def render("show.json", _) do
|
||||||
thumbnail:
|
thumbnail:
|
||||||
URI.merge(Pleroma.Web.Endpoint.url(), Keyword.get(instance, :instance_thumbnail))
|
URI.merge(Pleroma.Web.Endpoint.url(), Keyword.get(instance, :instance_thumbnail))
|
||||||
|> to_string,
|
|> to_string,
|
||||||
languages: ["en"],
|
languages: Keyword.get(instance, :languages, ["en"]),
|
||||||
registrations: Keyword.get(instance, :registrations_open),
|
registrations: Keyword.get(instance, :registrations_open),
|
||||||
approval_required: Keyword.get(instance, :account_approval_required),
|
approval_required: Keyword.get(instance, :account_approval_required),
|
||||||
configuration: configuration(),
|
configuration: configuration(),
|
||||||
|
|
|
@ -30,12 +30,13 @@ def scrub_html_and_truncate(%{data: %{"content" => content}} = object) do
|
||||||
|> scrub_html_and_truncate_object_field(object)
|
|> scrub_html_and_truncate_object_field(object)
|
||||||
end
|
end
|
||||||
|
|
||||||
def scrub_html_and_truncate(content, max_length \\ 200) when is_binary(content) do
|
def scrub_html_and_truncate(content, max_length \\ 200, omission \\ "...")
|
||||||
|
when is_binary(content) do
|
||||||
content
|
content
|
||||||
|> scrub_html
|
|> scrub_html
|
||||||
|> Emoji.Formatter.demojify()
|
|> Emoji.Formatter.demojify()
|
||||||
|> HtmlEntities.decode()
|
|> HtmlEntities.decode()
|
||||||
|> Formatter.truncate(max_length)
|
|> Formatter.truncate(max_length, omission)
|
||||||
end
|
end
|
||||||
|
|
||||||
def scrub_html(content) when is_binary(content) do
|
def scrub_html(content) when is_binary(content) do
|
||||||
|
|
|
@ -38,10 +38,6 @@ def call(
|
||||||
|
|
||||||
def call(conn, _), do: conn
|
def call(conn, _), do: conn
|
||||||
|
|
||||||
def checkpw(password, "$6" <> _ = password_hash) do
|
|
||||||
:crypt.crypt(password, password_hash) == password_hash
|
|
||||||
end
|
|
||||||
|
|
||||||
def checkpw(password, "$2" <> _ = password_hash) do
|
def checkpw(password, "$2" <> _ = password_hash) do
|
||||||
# Handle bcrypt passwords for Mastodon migration
|
# Handle bcrypt passwords for Mastodon migration
|
||||||
Bcrypt.verify_pass(password, password_hash)
|
Bcrypt.verify_pass(password, password_hash)
|
||||||
|
@ -60,10 +56,6 @@ def maybe_update_password(%User{password_hash: "$2" <> _} = user, password) do
|
||||||
do_update_password(user, password)
|
do_update_password(user, password)
|
||||||
end
|
end
|
||||||
|
|
||||||
def maybe_update_password(%User{password_hash: "$6" <> _} = user, password) do
|
|
||||||
do_update_password(user, password)
|
|
||||||
end
|
|
||||||
|
|
||||||
def maybe_update_password(user, _), do: {:ok, user}
|
def maybe_update_password(user, _), do: {:ok, user}
|
||||||
|
|
||||||
defp do_update_password(user, password) do
|
defp do_update_password(user, password) do
|
||||||
|
|
|
@ -9,17 +9,13 @@ defmodule Pleroma.Web.RelMe do
|
||||||
recv_timeout: 2_000
|
recv_timeout: 2_000
|
||||||
]
|
]
|
||||||
|
|
||||||
if Pleroma.Config.get(:env) == :test do
|
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
|
||||||
def parse(url) when is_binary(url), do: parse_url(url)
|
def parse(url) when is_binary(url) do
|
||||||
else
|
@cachex.fetch!(:rel_me_cache, url, fn _ ->
|
||||||
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
|
{:commit, parse_url(url)}
|
||||||
def parse(url) when is_binary(url) do
|
end)
|
||||||
@cachex.fetch!(:rel_me_cache, url, fn _ ->
|
rescue
|
||||||
{:commit, parse_url(url)}
|
e -> {:error, "Cachex error: #{inspect(e)}"}
|
||||||
end)
|
|
||||||
rescue
|
|
||||||
e -> {:error, "Cachex error: #{inspect(e)}"}
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse(_), do: {:error, "No URL provided"}
|
def parse(_), do: {:error, "No URL provided"}
|
||||||
|
|
|
@ -928,8 +928,7 @@ defmodule Pleroma.Web.Router do
|
||||||
end
|
end
|
||||||
|
|
||||||
scope "/", Pleroma.Web do
|
scope "/", Pleroma.Web do
|
||||||
# Note: html format is supported only if static FE is enabled
|
pipe_through([:accepts_html_xml])
|
||||||
pipe_through([:accepts_html_xml, :static_fe])
|
|
||||||
|
|
||||||
get("/users/:nickname/feed", Feed.UserController, :feed, as: :user_feed)
|
get("/users/:nickname/feed", Feed.UserController, :feed, as: :user_feed)
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
<id><%= @data["id"] %></id>
|
<id><%= @data["id"] %></id>
|
||||||
<title><%= activity_title(@data, Keyword.get(@feed_config, :post_title, %{})) %></title>
|
<title><%= activity_title(@data, Keyword.get(@feed_config, :post_title, %{})) %></title>
|
||||||
<content type="html"><%= activity_description(@data) %></content>
|
<content type="html"><%= activity_description(@data) %></content>
|
||||||
<published><%= to_rfc3339(@activity.data["published"]) %></published>
|
<published><%= to_rfc3339(@data["published"]) %></published>
|
||||||
<updated><%= to_rfc3339(@activity.data["published"]) %></updated>
|
<updated><%= to_rfc3339(@data["published"]) %></updated>
|
||||||
<ostatus:conversation ref="<%= activity_context(@activity) %>">
|
<ostatus:conversation ref="<%= activity_context(@activity) %>">
|
||||||
<%= activity_context(@activity) %>
|
<%= activity_context(@activity) %>
|
||||||
</ostatus:conversation>
|
</ostatus:conversation>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<guid><%= @data["id"] %></guid>
|
<guid><%= @data["id"] %></guid>
|
||||||
<title><%= activity_title(@data, Keyword.get(@feed_config, :post_title, %{})) %></title>
|
<title><%= activity_title(@data, Keyword.get(@feed_config, :post_title, %{})) %></title>
|
||||||
<description><%= activity_description(@data) %></description>
|
<description><%= activity_description(@data) %></description>
|
||||||
<pubDate><%= to_rfc2822(@activity.data["published"]) %></pubDate>
|
<pubDate><%= to_rfc2822(@data["published"]) %></pubDate>
|
||||||
<ostatus:conversation ref="<%= activity_context(@activity) %>">
|
<ostatus:conversation ref="<%= activity_context(@activity) %>">
|
||||||
<%= activity_context(@activity) %>
|
<%= activity_context(@activity) %>
|
||||||
</ostatus:conversation>
|
</ostatus:conversation>
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
<id><%= @data["id"] %></id>
|
<id><%= @data["id"] %></id>
|
||||||
<title><%= activity_title(@data, Keyword.get(@feed_config, :post_title, %{})) %></title>
|
<title><%= activity_title(@data, Keyword.get(@feed_config, :post_title, %{})) %></title>
|
||||||
<content type="html"><%= activity_description(@data) %></content>
|
<content type="html"><%= activity_description(@data) %></content>
|
||||||
<published><%= to_rfc3339(@activity.data["published"]) %></published>
|
<published><%= to_rfc3339(@data["published"]) %></published>
|
||||||
<updated><%= to_rfc3339(@activity.data["published"]) %></updated>
|
<updated><%= to_rfc3339(@data["published"]) %></updated>
|
||||||
<ostatus:conversation ref="<%= activity_context(@activity) %>">
|
<ostatus:conversation ref="<%= activity_context(@activity) %>">
|
||||||
<%= activity_context(@activity) %>
|
<%= activity_context(@activity) %>
|
||||||
</ostatus:conversation>
|
</ostatus:conversation>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
<guid isPermalink="true"><%= activity_context(@activity) %></guid>
|
<guid isPermalink="true"><%= activity_context(@activity) %></guid>
|
||||||
<link><%= activity_context(@activity) %></link>
|
<link><%= activity_context(@activity) %></link>
|
||||||
<pubDate><%= to_rfc2822(@activity.data["published"]) %></pubDate>
|
<pubDate><%= to_rfc2822(@data["published"]) %></pubDate>
|
||||||
|
|
||||||
<description><%= activity_description(@data) %></description>
|
<description><%= activity_description(@data) %></description>
|
||||||
<%= for attachment <- @data["attachment"] || [] do %>
|
<%= for attachment <- @data["attachment"] || [] do %>
|
||||||
|
|
|
@ -13,6 +13,9 @@ def perform(%Job{args: %{"op" => "incoming_ap_doc", "params" => params}}) do
|
||||||
{:ok, res}
|
{:ok, res}
|
||||||
else
|
else
|
||||||
{:error, :origin_containment_failed} -> {:cancel, :origin_containment_failed}
|
{:error, :origin_containment_failed} -> {:cancel, :origin_containment_failed}
|
||||||
|
{:error, :already_present} -> {:cancel, :already_present}
|
||||||
|
{:error, {:validate_object, reason}} -> {:cancel, reason}
|
||||||
|
{:error, {:error, {:validate, reason}}} -> {:cancel, reason}
|
||||||
{:error, {:reject, reason}} -> {:cancel, reason}
|
{:error, {:reject, reason}} -> {:cancel, reason}
|
||||||
e -> e
|
e -> e
|
||||||
end
|
end
|
||||||
|
|
9
mix.exs
9
mix.exs
|
@ -8,7 +8,7 @@ def project do
|
||||||
app: :pleroma,
|
app: :pleroma,
|
||||||
name: "Rebased",
|
name: "Rebased",
|
||||||
compat_name: "Pleroma",
|
compat_name: "Pleroma",
|
||||||
version: version("2.5.50"),
|
version: version("2.5.51"),
|
||||||
elixir: "~> 1.11",
|
elixir: "~> 1.11",
|
||||||
elixirc_paths: elixirc_paths(Mix.env()),
|
elixirc_paths: elixirc_paths(Mix.env()),
|
||||||
compilers: [:phoenix, :gettext] ++ Mix.compilers(),
|
compilers: [:phoenix, :gettext] ++ Mix.compilers(),
|
||||||
|
@ -156,9 +156,6 @@ defp deps do
|
||||||
{:sweet_xml, "~> 0.7.2"},
|
{:sweet_xml, "~> 0.7.2"},
|
||||||
{:earmark, "~> 1.4.22"},
|
{:earmark, "~> 1.4.22"},
|
||||||
{:bbcode_pleroma, "~> 0.2.0"},
|
{:bbcode_pleroma, "~> 0.2.0"},
|
||||||
{:crypt,
|
|
||||||
git: "https://github.com/msantos/crypt.git",
|
|
||||||
ref: "f75cd55325e33cbea198fb41fe41871392f8fb76"},
|
|
||||||
{:cors_plug, "~> 2.0"},
|
{:cors_plug, "~> 2.0"},
|
||||||
{:web_push_encryption, "~> 0.3.1"},
|
{:web_push_encryption, "~> 0.3.1"},
|
||||||
{:swoosh, "~> 1.8.2"},
|
{:swoosh, "~> 1.8.2"},
|
||||||
|
@ -168,7 +165,7 @@ defp deps do
|
||||||
{:floki, "~> 0.27"},
|
{:floki, "~> 0.27"},
|
||||||
{:timex, "~> 3.6"},
|
{:timex, "~> 3.6"},
|
||||||
{:ueberauth, "~> 0.4"},
|
{:ueberauth, "~> 0.4"},
|
||||||
{:linkify, "~> 0.5.2"},
|
{:linkify, "~> 0.5.3"},
|
||||||
{:http_signatures, "~> 0.1.1"},
|
{:http_signatures, "~> 0.1.1"},
|
||||||
{:telemetry, "~> 1.0", override: true},
|
{:telemetry, "~> 1.0", override: true},
|
||||||
{:poolboy, "~> 1.5"},
|
{:poolboy, "~> 1.5"},
|
||||||
|
@ -203,7 +200,7 @@ defp deps do
|
||||||
{:majic, "~> 1.0"},
|
{:majic, "~> 1.0"},
|
||||||
{:eblurhash, "~> 1.2.2"},
|
{:eblurhash, "~> 1.2.2"},
|
||||||
{:oembed_providers, "~> 0.1.0"},
|
{:oembed_providers, "~> 0.1.0"},
|
||||||
{:open_api_spex, "~> 3.10"},
|
{:open_api_spex, "~> 3.16"},
|
||||||
{:ecto_psql_extras, "~> 0.6"},
|
{:ecto_psql_extras, "~> 0.6"},
|
||||||
{:icalendar, "~> 1.1"},
|
{:icalendar, "~> 1.1"},
|
||||||
{:geospatial, "~> 0.2.0"},
|
{:geospatial, "~> 0.2.0"},
|
||||||
|
|
4
mix.lock
4
mix.lock
|
@ -71,7 +71,7 @@
|
||||||
"joken": {:hex, :joken, "2.3.0", "62a979c46f2c81dcb8ddc9150453b60d3757d1ac393c72bb20fc50a7b0827dc6", [:mix], [{:jose, "~> 1.10", [hex: :jose, repo: "hexpm", optional: false]}], "hexpm", "57b263a79c0ec5d536ac02d569c01e6b4de91bd1cb825625fe90eab4feb7bc1e"},
|
"joken": {:hex, :joken, "2.3.0", "62a979c46f2c81dcb8ddc9150453b60d3757d1ac393c72bb20fc50a7b0827dc6", [:mix], [{:jose, "~> 1.10", [hex: :jose, repo: "hexpm", optional: false]}], "hexpm", "57b263a79c0ec5d536ac02d569c01e6b4de91bd1cb825625fe90eab4feb7bc1e"},
|
||||||
"jose": {:hex, :jose, "1.11.1", "59da64010c69aad6cde2f5b9248b896b84472e99bd18f246085b7b9fe435dcdb", [:mix, :rebar3], [], "hexpm", "078f6c9fb3cd2f4cfafc972c814261a7d1e8d2b3685c0a76eb87e158efff1ac5"},
|
"jose": {:hex, :jose, "1.11.1", "59da64010c69aad6cde2f5b9248b896b84472e99bd18f246085b7b9fe435dcdb", [:mix, :rebar3], [], "hexpm", "078f6c9fb3cd2f4cfafc972c814261a7d1e8d2b3685c0a76eb87e158efff1ac5"},
|
||||||
"jumper": {:hex, :jumper, "1.0.1", "3c00542ef1a83532b72269fab9f0f0c82bf23a35e27d278bfd9ed0865cecabff", [:mix], [], "hexpm", "318c59078ac220e966d27af3646026db9b5a5e6703cb2aa3e26bcfaba65b7433"},
|
"jumper": {:hex, :jumper, "1.0.1", "3c00542ef1a83532b72269fab9f0f0c82bf23a35e27d278bfd9ed0865cecabff", [:mix], [], "hexpm", "318c59078ac220e966d27af3646026db9b5a5e6703cb2aa3e26bcfaba65b7433"},
|
||||||
"linkify": {:hex, :linkify, "0.5.2", "fb66be139fdf1656ecb31f78a93592724d1b78d960a1b3598bd661013ea0e3c7", [:mix], [], "hexpm", "8d71ac690218d8952c90cbeb63cb8cc33738bb230d8a56d487d9447f2a5eab86"},
|
"linkify": {:hex, :linkify, "0.5.3", "5f8143d8f61f5ff08d3aeeff47ef6509492b4948d8f08007fbf66e4d2246a7f2", [:mix], [], "hexpm", "3ef35a1377d47c25506e07c1c005ea9d38d700699d92ee92825f024434258177"},
|
||||||
"majic": {:hex, :majic, "1.0.0", "37e50648db5f5c2ff0c9fb46454d034d11596c03683807b9fb3850676ffdaab3", [:make, :mix], [{:elixir_make, "~> 0.6.1", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "7905858f76650d49695f14ea55cd9aaaee0c6654fa391671d4cf305c275a0a9e"},
|
"majic": {:hex, :majic, "1.0.0", "37e50648db5f5c2ff0c9fb46454d034d11596c03683807b9fb3850676ffdaab3", [:make, :mix], [{:elixir_make, "~> 0.6.1", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "7905858f76650d49695f14ea55cd9aaaee0c6654fa391671d4cf305c275a0a9e"},
|
||||||
"makeup": {:hex, :makeup, "1.0.5", "d5a830bc42c9800ce07dd97fa94669dfb93d3bf5fcf6ea7a0c67b2e0e4a7f26c", [:mix], [{:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cfa158c02d3f5c0c665d0af11512fed3fba0144cf1aadee0f2ce17747fba2ca9"},
|
"makeup": {:hex, :makeup, "1.0.5", "d5a830bc42c9800ce07dd97fa94669dfb93d3bf5fcf6ea7a0c67b2e0e4a7f26c", [:mix], [{:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cfa158c02d3f5c0c665d0af11512fed3fba0144cf1aadee0f2ce17747fba2ca9"},
|
||||||
"makeup_elixir": {:hex, :makeup_elixir, "0.14.1", "4f0e96847c63c17841d42c08107405a005a2680eb9c7ccadfd757bd31dabccfb", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "f2438b1a80eaec9ede832b5c41cd4f373b38fd7aa33e3b22d9db79e640cbde11"},
|
"makeup_elixir": {:hex, :makeup_elixir, "0.14.1", "4f0e96847c63c17841d42c08107405a005a2680eb9c7ccadfd757bd31dabccfb", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "f2438b1a80eaec9ede832b5c41cd4f373b38fd7aa33e3b22d9db79e640cbde11"},
|
||||||
|
@ -93,7 +93,7 @@
|
||||||
"oauther": {:hex, :oauther, "1.3.0", "82b399607f0ca9d01c640438b34d74ebd9e4acd716508f868e864537ecdb1f76", [:mix], [], "hexpm", "78eb888ea875c72ca27b0864a6f550bc6ee84f2eeca37b093d3d833fbcaec04e"},
|
"oauther": {:hex, :oauther, "1.3.0", "82b399607f0ca9d01c640438b34d74ebd9e4acd716508f868e864537ecdb1f76", [:mix], [], "hexpm", "78eb888ea875c72ca27b0864a6f550bc6ee84f2eeca37b093d3d833fbcaec04e"},
|
||||||
"oban": {:hex, :oban, "2.13.4", "b4c4f48f4c89cc01036670eefa28aa9c03d09aadd402655475b936983d597006", [:mix], [{:ecto_sql, "~> 3.6", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16", [hex: :postgrex, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a7d26f82b409e2d7928fbb75a17716e06ad3f783ebe9af260e3dd23abed7f124"},
|
"oban": {:hex, :oban, "2.13.4", "b4c4f48f4c89cc01036670eefa28aa9c03d09aadd402655475b936983d597006", [:mix], [{:ecto_sql, "~> 3.6", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16", [hex: :postgrex, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a7d26f82b409e2d7928fbb75a17716e06ad3f783ebe9af260e3dd23abed7f124"},
|
||||||
"oembed_providers": {:hex, :oembed_providers, "0.1.0", "9b336ee5f3ca20ee4ed005383c74b154d30d0abeb98e95828855c0e2841ae46b", [:mix], [{:glob, "~> 1.0", [hex: :glob, repo: "hexpm", optional: false]}, {:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "ac1dda0f743aa6fdead3eef59decfefc9de91d550bf0805b8fce16ed10d421ba"},
|
"oembed_providers": {:hex, :oembed_providers, "0.1.0", "9b336ee5f3ca20ee4ed005383c74b154d30d0abeb98e95828855c0e2841ae46b", [:mix], [{:glob, "~> 1.0", [hex: :glob, repo: "hexpm", optional: false]}, {:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "ac1dda0f743aa6fdead3eef59decfefc9de91d550bf0805b8fce16ed10d421ba"},
|
||||||
"open_api_spex": {:hex, :open_api_spex, "3.10.0", "94e9521ad525b3fcf6dc77da7c45f87fdac24756d4de588cb0816b413e7c1844", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:poison, "~> 3.1", [hex: :poison, repo: "hexpm", optional: true]}], "hexpm", "2dbb2bde3d2b821f06936e8dfaf3284331186556291946d84eeba3750ac28765"},
|
"open_api_spex": {:hex, :open_api_spex, "3.16.0", "9843af4e87550cd8ac5821b10e4c74f1d51f0d4e3310f824d780614743423b25", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:poison, "~> 3.0 or ~> 4.0 or ~> 5.0", [hex: :poison, repo: "hexpm", optional: true]}, {:ymlr, "~> 2.0 or ~> 3.0", [hex: :ymlr, repo: "hexpm", optional: true]}], "hexpm", "bb0be24a648b73e8fc8cbda17f514b8486262275e8b33e8b5ae66283df972129"},
|
||||||
"parallel_stream": {:hex, :parallel_stream, "1.0.6", "b967be2b23f0f6787fab7ed681b4c45a215a81481fb62b01a5b750fa8f30f76c", [:mix], [], "hexpm", "639b2e8749e11b87b9eb42f2ad325d161c170b39b288ac8d04c4f31f8f0823eb"},
|
"parallel_stream": {:hex, :parallel_stream, "1.0.6", "b967be2b23f0f6787fab7ed681b4c45a215a81481fb62b01a5b750fa8f30f76c", [:mix], [], "hexpm", "639b2e8749e11b87b9eb42f2ad325d161c170b39b288ac8d04c4f31f8f0823eb"},
|
||||||
"parse_trans": {:hex, :parse_trans, "3.3.1", "16328ab840cc09919bd10dab29e431da3af9e9e7e7e6f0089dd5a2d2820011d8", [:rebar3], [], "hexpm", "07cd9577885f56362d414e8c4c4e6bdf10d43a8767abb92d24cbe8b24c54888b"},
|
"parse_trans": {:hex, :parse_trans, "3.3.1", "16328ab840cc09919bd10dab29e431da3af9e9e7e7e6f0089dd5a2d2820011d8", [:rebar3], [], "hexpm", "07cd9577885f56362d414e8c4c4e6bdf10d43a8767abb92d24cbe8b24c54888b"},
|
||||||
"pbkdf2_elixir": {:hex, :pbkdf2_elixir, "1.2.1", "9cbe354b58121075bd20eb83076900a3832324b7dd171a6895fab57b6bb2752c", [:mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}], "hexpm", "d3b40a4a4630f0b442f19eca891fcfeeee4c40871936fed2f68e1c4faa30481f"},
|
"pbkdf2_elixir": {:hex, :pbkdf2_elixir, "1.2.1", "9cbe354b58121075bd20eb83076900a3832324b7dd171a6895fab57b6bb2752c", [:mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}], "hexpm", "d3b40a4a4630f0b442f19eca891fcfeeee4c40871936fed2f68e1c4faa30481f"},
|
||||||
|
|
|
@ -6033,3 +6033,15 @@ msgstr ""
|
||||||
msgctxt "config label at :pleroma-:instance > :moderator_privileges"
|
msgctxt "config label at :pleroma-:instance > :moderator_privileges"
|
||||||
msgid "Moderator privileges"
|
msgid "Moderator privileges"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
|
msgctxt "config description at :pleroma-:instance > :languages"
|
||||||
|
msgid "Languages to be exposed in /api/v1/instance. Should be in the format of BCP47 language codes."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
|
msgctxt "config label at :pleroma-:instance > :languages"
|
||||||
|
msgid "Languages"
|
||||||
|
msgstr ""
|
||||||
|
|
|
@ -111,7 +111,7 @@ msgid "Can't display this activity"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:337
|
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:334
|
||||||
msgid "Can't find user"
|
msgid "Can't find user"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -236,7 +236,7 @@ msgid "Poll's author can't vote"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:502
|
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:499
|
||||||
#: lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:20
|
#: lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:20
|
||||||
#: lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:39
|
#: lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:39
|
||||||
#: lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:51
|
#: lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:51
|
||||||
|
@ -558,7 +558,7 @@ msgid "Access denied"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:334
|
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:331
|
||||||
msgid "This API requires an authenticated user"
|
msgid "This API requires an authenticated user"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
BIN
test/fixtures/image_with_imagedescription_and_caption-abstract_and_stray_data_after.png
vendored
Normal file
BIN
test/fixtures/image_with_imagedescription_and_caption-abstract_and_stray_data_after.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 820 B |
BIN
test/fixtures/image_with_stray_data_after.png
vendored
Executable file
BIN
test/fixtures/image_with_stray_data_after.png
vendored
Executable file
Binary file not shown.
After Width: | Height: | Size: 102 KiB |
62
test/mix/tasks/pleroma/openapi_spec_test.exs
Normal file
62
test/mix/tasks/pleroma/openapi_spec_test.exs
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Mix.Tasks.Pleroma.OpenapiSpecTest do
|
||||||
|
use Pleroma.DataCase, async: true
|
||||||
|
|
||||||
|
alias Mix.Tasks.Pleroma.OpenapiSpec
|
||||||
|
|
||||||
|
@spec_base %{
|
||||||
|
"paths" => %{
|
||||||
|
"/cofe" => %{
|
||||||
|
"get" => %{
|
||||||
|
"operationId" => "Some.operation",
|
||||||
|
"tags" => []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/mew" => %{
|
||||||
|
"post" => %{
|
||||||
|
"operationId" => "Another.operation",
|
||||||
|
"tags" => ["mew mew"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"x-tagGroups" => [
|
||||||
|
%{
|
||||||
|
"name" => "mew",
|
||||||
|
"tags" => ["mew mew", "abc"]
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
"name" => "lol",
|
||||||
|
"tags" => ["lol lol", "xyz"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
describe "check_specs/1" do
|
||||||
|
test "Every operation must have a tag" do
|
||||||
|
assert {:error, ["Some.operation (get /cofe): No tags specified"]} ==
|
||||||
|
OpenapiSpec.check_specs(@spec_base)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "Every tag must be in tag groups" do
|
||||||
|
spec =
|
||||||
|
@spec_base
|
||||||
|
|> put_in(["paths", "/cofe", "get", "tags"], ["abc", "def", "not specified"])
|
||||||
|
|
||||||
|
assert {:error,
|
||||||
|
[
|
||||||
|
"Some.operation (get /cofe): Tags #{inspect(["def", "not specified"])} not available. Please add it in \"x-tagGroups\" in Pleroma.Web.ApiSpec"
|
||||||
|
]} == OpenapiSpec.check_specs(spec)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "No errors if ok" do
|
||||||
|
spec =
|
||||||
|
@spec_base
|
||||||
|
|> put_in(["paths", "/cofe", "get", "tags"], ["abc", "mew mew"])
|
||||||
|
|
||||||
|
assert :ok == OpenapiSpec.check_specs(spec)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -476,6 +476,32 @@ test "it disables notifications from strangers" do
|
||||||
refute Notification.create_notification(activity, followed)
|
refute Notification.create_notification(activity, followed)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "it disables notifications from non-followees" do
|
||||||
|
follower = insert(:user)
|
||||||
|
|
||||||
|
followed =
|
||||||
|
insert(:user,
|
||||||
|
notification_settings: %Pleroma.User.NotificationSetting{block_from_strangers: true}
|
||||||
|
)
|
||||||
|
|
||||||
|
CommonAPI.follow(follower, followed)
|
||||||
|
{:ok, activity} = CommonAPI.post(follower, %{status: "hey @#{followed.nickname}"})
|
||||||
|
refute Notification.create_notification(activity, followed)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it allows notifications from followees" do
|
||||||
|
poster = insert(:user)
|
||||||
|
|
||||||
|
receiver =
|
||||||
|
insert(:user,
|
||||||
|
notification_settings: %Pleroma.User.NotificationSetting{block_from_strangers: true}
|
||||||
|
)
|
||||||
|
|
||||||
|
CommonAPI.follow(receiver, poster)
|
||||||
|
{:ok, activity} = CommonAPI.post(poster, %{status: "hey @#{receiver.nickname}"})
|
||||||
|
assert Notification.create_notification(activity, receiver)
|
||||||
|
end
|
||||||
|
|
||||||
test "it doesn't create a notification for user if he is the activity author" do
|
test "it doesn't create a notification for user if he is the activity author" do
|
||||||
activity = insert(:note_activity)
|
activity = insert(:note_activity)
|
||||||
author = User.get_cached_by_ap_id(activity.data["actor"])
|
author = User.get_cached_by_ap_id(activity.data["actor"])
|
||||||
|
@ -1394,5 +1420,32 @@ test "it returns notifications about favorites with filtered word", %{user: user
|
||||||
|
|
||||||
assert length(Notification.for_user(user)) == 1
|
assert length(Notification.for_user(user)) == 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "it returns notifications when related object is without content and filters are defined",
|
||||||
|
%{user: user} do
|
||||||
|
followed_user = insert(:user, is_locked: true)
|
||||||
|
|
||||||
|
insert(:filter, user: followed_user, phrase: "test", hide: true)
|
||||||
|
|
||||||
|
{:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
|
||||||
|
refute FollowingRelationship.following?(user, followed_user)
|
||||||
|
assert [notification] = Notification.for_user(followed_user)
|
||||||
|
|
||||||
|
assert %{type: "follow_request"} =
|
||||||
|
NotificationView.render("show.json", %{
|
||||||
|
notification: notification,
|
||||||
|
for: followed_user
|
||||||
|
})
|
||||||
|
|
||||||
|
assert {:ok, _} = CommonAPI.accept_follow_request(user, followed_user)
|
||||||
|
|
||||||
|
assert [notification] = Notification.for_user(followed_user)
|
||||||
|
|
||||||
|
assert %{type: "follow"} =
|
||||||
|
NotificationView.render("show.json", %{
|
||||||
|
notification: notification,
|
||||||
|
for: followed_user
|
||||||
|
})
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -42,6 +42,33 @@ test "otherwise returns ImageDescription when present" do
|
||||||
{:ok, :filtered, uploads_after}
|
{:ok, :filtered, uploads_after}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "Ignores warnings" do
|
||||||
|
uploads = %Pleroma.Upload{
|
||||||
|
name: "image_with_imagedescription_and_caption-abstract_and_stray_data_after.png",
|
||||||
|
content_type: "image/png",
|
||||||
|
path:
|
||||||
|
Path.absname(
|
||||||
|
"test/fixtures/image_with_imagedescription_and_caption-abstract_and_stray_data_after.png"
|
||||||
|
),
|
||||||
|
tempfile:
|
||||||
|
Path.absname(
|
||||||
|
"test/fixtures/image_with_imagedescription_and_caption-abstract_and_stray_data_after.png"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
assert {:ok, :filtered, %{description: "a descriptive white pixel"}} =
|
||||||
|
Filter.Exiftool.ReadDescription.filter(uploads)
|
||||||
|
|
||||||
|
uploads = %Pleroma.Upload{
|
||||||
|
name: "image_with_stray_data_after.png",
|
||||||
|
content_type: "image/png",
|
||||||
|
path: Path.absname("test/fixtures/image_with_stray_data_after.png"),
|
||||||
|
tempfile: Path.absname("test/fixtures/image_with_stray_data_after.png")
|
||||||
|
}
|
||||||
|
|
||||||
|
assert {:ok, :filtered, %{description: nil}} = Filter.Exiftool.ReadDescription.filter(uploads)
|
||||||
|
end
|
||||||
|
|
||||||
test "otherwise returns iptc:Caption-Abstract when present" do
|
test "otherwise returns iptc:Caption-Abstract when present" do
|
||||||
upload = %Pleroma.Upload{
|
upload = %Pleroma.Upload{
|
||||||
name: "image_with_caption-abstract.jpg",
|
name: "image_with_caption-abstract.jpg",
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
# SPDX-License-Identifier: AGPL-3.0-only
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
defmodule Pleroma.User.ImportTest do
|
defmodule Pleroma.User.ImportTest do
|
||||||
alias Pleroma.Repo
|
|
||||||
alias Pleroma.Tests.ObanHelpers
|
alias Pleroma.Tests.ObanHelpers
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
# SPDX-License-Identifier: AGPL-3.0-only
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
defmodule Pleroma.UserSearchTest do
|
defmodule Pleroma.UserSearchTest do
|
||||||
alias Pleroma.Repo
|
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
use Pleroma.DataCase
|
use Pleroma.DataCase
|
||||||
|
|
||||||
|
|
|
@ -104,6 +104,7 @@ test "it does not fetch reply-to activities beyond max replies depth limit" do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@tag capture_log: true
|
||||||
test "it does not crash if the object in inReplyTo can't be fetched" do
|
test "it does not crash if the object in inReplyTo can't be fetched" do
|
||||||
data =
|
data =
|
||||||
File.read!("test/fixtures/mastodon-post-activity.json")
|
File.read!("test/fixtures/mastodon-post-activity.json")
|
||||||
|
@ -834,6 +835,7 @@ test "the standalone note uses its own ID when context is missing" do
|
||||||
assert modified.data["context"] == object.data["id"]
|
assert modified.data["context"] == object.data["id"]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@tag capture_log: true
|
||||||
test "the reply note uses its parent's ID when context is missing and reply is unreachable" do
|
test "the reply note uses its parent's ID when context is missing and reply is unreachable" do
|
||||||
insert(:user, ap_id: "https://mk.absturztau.be/users/8ozbzjs3o8")
|
insert(:user, ap_id: "https://mk.absturztau.be/users/8ozbzjs3o8")
|
||||||
|
|
||||||
|
|
|
@ -316,6 +316,7 @@ test "create new config setting in db", %{conn: conn} do
|
||||||
assert Application.get_env(:idna, :key5) == {"string", Pleroma.Captcha.NotReal, []}
|
assert Application.get_env(:idna, :key5) == {"string", Pleroma.Captcha.NotReal, []}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@tag capture_log: true
|
||||||
test "save configs setting without explicit key", %{conn: conn} do
|
test "save configs setting without explicit key", %{conn: conn} do
|
||||||
adapter = Application.get_env(:http, :adapter)
|
adapter = Application.get_env(:http, :adapter)
|
||||||
send_user_agent = Application.get_env(:http, :send_user_agent)
|
send_user_agent = Application.get_env(:http, :send_user_agent)
|
||||||
|
|
|
@ -398,6 +398,34 @@ test "returns reports with specified assigned user", %{conn: conn, admin: admin}
|
||||||
assert response["total"] == 1
|
assert response["total"] == 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "renders content correctly", %{conn: conn} do
|
||||||
|
[reporter, target_user] = insert_pair(:user)
|
||||||
|
note = insert(:note, user: target_user, data: %{"content" => "mew 1"})
|
||||||
|
note2 = insert(:note, user: target_user, data: %{"content" => "mew 2"})
|
||||||
|
activity = insert(:note_activity, user: target_user, note: note)
|
||||||
|
activity2 = insert(:note_activity, user: target_user, note: note2)
|
||||||
|
|
||||||
|
{:ok, _report} =
|
||||||
|
CommonAPI.report(reporter, %{
|
||||||
|
account_id: target_user.id,
|
||||||
|
comment: "I feel offended",
|
||||||
|
status_ids: [activity.id, activity2.id]
|
||||||
|
})
|
||||||
|
|
||||||
|
CommonAPI.delete(activity.id, target_user)
|
||||||
|
CommonAPI.delete(activity2.id, target_user)
|
||||||
|
|
||||||
|
response =
|
||||||
|
conn
|
||||||
|
|> get(report_path(conn, :index))
|
||||||
|
|> json_response_and_validate_schema(:ok)
|
||||||
|
|
||||||
|
assert [open_report] = response["reports"]
|
||||||
|
assert %{"statuses" => [s1, s2]} = open_report
|
||||||
|
assert "mew 1" in [s1["content"], s2["content"]]
|
||||||
|
assert "mew 2" in [s1["content"], s2["content"]]
|
||||||
|
end
|
||||||
|
|
||||||
test "returns 403 when requested by a non-admin" do
|
test "returns 403 when requested by a non-admin" do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
token = insert(:oauth_token, user: user)
|
token = insert(:oauth_token, user: user)
|
||||||
|
|
|
@ -519,6 +519,25 @@ test "it de-duplicates tags" do
|
||||||
assert Object.tags(object) == ["2hu"]
|
assert Object.tags(object) == ["2hu"]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "zwnj is treated as word character" do
|
||||||
|
user = insert(:user)
|
||||||
|
{:ok, activity} = CommonAPI.post(user, %{status: "#ساٴينس"})
|
||||||
|
|
||||||
|
object = Object.normalize(activity, fetch: false)
|
||||||
|
|
||||||
|
assert Object.tags(object) == ["ساٴينس"]
|
||||||
|
end
|
||||||
|
|
||||||
|
test "double dot in link is allowed" do
|
||||||
|
user = insert(:user)
|
||||||
|
text = "https://example.to/something..mp3"
|
||||||
|
{:ok, activity} = CommonAPI.post(user, %{status: text})
|
||||||
|
|
||||||
|
object = Object.normalize(activity, fetch: false)
|
||||||
|
|
||||||
|
assert object.data["content"] == "<a href=\"#{text}\" rel=\"ugc\">#{text}</a>"
|
||||||
|
end
|
||||||
|
|
||||||
test "it adds emoji in the object" do
|
test "it adds emoji in the object" do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
{:ok, activity} = CommonAPI.post(user, %{status: ":firefox:"})
|
{:ok, activity} = CommonAPI.post(user, %{status: ":firefox:"})
|
||||||
|
|
|
@ -133,7 +133,7 @@ test "successfully processes incoming AP docs with correct origin" do
|
||||||
assert {:ok, _activity} = ObanHelpers.perform(job)
|
assert {:ok, _activity} = ObanHelpers.perform(job)
|
||||||
|
|
||||||
assert {:ok, job} = Federator.incoming_ap_doc(params)
|
assert {:ok, job} = Federator.incoming_ap_doc(params)
|
||||||
assert {:error, :already_present} = ObanHelpers.perform(job)
|
assert {:cancel, :already_present} = ObanHelpers.perform(job)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "rejects incoming AP docs with incorrect origin" do
|
test "rejects incoming AP docs with incorrect origin" do
|
||||||
|
|
|
@ -57,9 +57,23 @@ defmodule Pleroma.Web.Feed.UserControllerTest do
|
||||||
)
|
)
|
||||||
|
|
||||||
note_activity2 = insert(:note_activity, note: note2)
|
note_activity2 = insert(:note_activity, note: note2)
|
||||||
|
|
||||||
|
note3 =
|
||||||
|
insert(:note,
|
||||||
|
user: user,
|
||||||
|
data: %{
|
||||||
|
"content" => "This note tests whether HTML entities are truncated properly",
|
||||||
|
"summary" => "Won't, didn't fail",
|
||||||
|
"inReplyTo" => note_activity2.id
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
_note_activity3 = insert(:note_activity, note: note3)
|
||||||
object = Object.normalize(note_activity, fetch: false)
|
object = Object.normalize(note_activity, fetch: false)
|
||||||
|
|
||||||
[user: user, object: object, max_id: note_activity2.id]
|
encoded_title = FeedView.activity_title(note3.data)
|
||||||
|
|
||||||
|
[user: user, object: object, max_id: note_activity2.id, encoded_title: encoded_title]
|
||||||
end
|
end
|
||||||
|
|
||||||
test "gets an atom feed", %{conn: conn, user: user, object: object, max_id: max_id} do
|
test "gets an atom feed", %{conn: conn, user: user, object: object, max_id: max_id} do
|
||||||
|
@ -74,7 +88,7 @@ test "gets an atom feed", %{conn: conn, user: user, object: object, max_id: max_
|
||||||
|> SweetXml.parse()
|
|> SweetXml.parse()
|
||||||
|> SweetXml.xpath(~x"//entry/title/text()"l)
|
|> SweetXml.xpath(~x"//entry/title/text()"l)
|
||||||
|
|
||||||
assert activity_titles == ['2hu', '2hu & as']
|
assert activity_titles == ['Won\'t, didn\'...', '2hu', '2hu & as']
|
||||||
assert resp =~ FeedView.escape(object.data["content"])
|
assert resp =~ FeedView.escape(object.data["content"])
|
||||||
assert resp =~ FeedView.escape(object.data["summary"])
|
assert resp =~ FeedView.escape(object.data["summary"])
|
||||||
assert resp =~ FeedView.escape(object.data["context"])
|
assert resp =~ FeedView.escape(object.data["context"])
|
||||||
|
@ -105,7 +119,7 @@ test "gets a rss feed", %{conn: conn, user: user, object: object, max_id: max_id
|
||||||
|> SweetXml.parse()
|
|> SweetXml.parse()
|
||||||
|> SweetXml.xpath(~x"//item/title/text()"l)
|
|> SweetXml.xpath(~x"//item/title/text()"l)
|
||||||
|
|
||||||
assert activity_titles == ['2hu', '2hu & as']
|
assert activity_titles == ['Won\'t, didn\'...', '2hu', '2hu & as']
|
||||||
assert resp =~ FeedView.escape(object.data["content"])
|
assert resp =~ FeedView.escape(object.data["content"])
|
||||||
assert resp =~ FeedView.escape(object.data["summary"])
|
assert resp =~ FeedView.escape(object.data["summary"])
|
||||||
assert resp =~ FeedView.escape(object.data["context"])
|
assert resp =~ FeedView.escape(object.data["context"])
|
||||||
|
@ -176,6 +190,30 @@ test "does not require authentication on non-federating instances", %{conn: conn
|
||||||
|> get("/users/#{user.nickname}/feed.rss")
|
|> get("/users/#{user.nickname}/feed.rss")
|
||||||
|> response(200)
|
|> response(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "does not mangle HTML entities midway", %{
|
||||||
|
conn: conn,
|
||||||
|
user: user,
|
||||||
|
object: object,
|
||||||
|
encoded_title: encoded_title
|
||||||
|
} do
|
||||||
|
resp =
|
||||||
|
conn
|
||||||
|
|> put_req_header("accept", "application/atom+xml")
|
||||||
|
|> get(user_feed_path(conn, :feed, user.nickname))
|
||||||
|
|> response(200)
|
||||||
|
|
||||||
|
activity_titles =
|
||||||
|
resp
|
||||||
|
|> SweetXml.parse()
|
||||||
|
|> SweetXml.xpath(~x"//entry/title/text()"l)
|
||||||
|
|
||||||
|
assert activity_titles == ['Won\'t, didn\'...', '2hu', '2hu & as']
|
||||||
|
assert resp =~ FeedView.escape(object.data["content"])
|
||||||
|
assert resp =~ FeedView.escape(object.data["summary"])
|
||||||
|
assert resp =~ FeedView.escape(object.data["context"])
|
||||||
|
assert resp =~ encoded_title
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Note: see ActivityPubControllerTest for JSON format tests
|
# Note: see ActivityPubControllerTest for JSON format tests
|
||||||
|
|
|
@ -2045,6 +2045,39 @@ test "getting a list of blocks" do
|
||||||
assert [%{"id" => ^id1}] = result
|
assert [%{"id" => ^id1}] = result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "list of blocks with with_relationships parameter" do
|
||||||
|
%{user: user, conn: conn} = oauth_access(["read:blocks"])
|
||||||
|
%{id: id1} = other_user1 = insert(:user)
|
||||||
|
%{id: id2} = other_user2 = insert(:user)
|
||||||
|
%{id: id3} = other_user3 = insert(:user)
|
||||||
|
|
||||||
|
{:ok, _, _} = User.follow(other_user1, user)
|
||||||
|
{:ok, _, _} = User.follow(other_user2, user)
|
||||||
|
{:ok, _, _} = User.follow(other_user3, user)
|
||||||
|
|
||||||
|
{:ok, _} = User.block(user, other_user1)
|
||||||
|
{:ok, _} = User.block(user, other_user2)
|
||||||
|
{:ok, _} = User.block(user, other_user3)
|
||||||
|
|
||||||
|
assert [
|
||||||
|
%{
|
||||||
|
"id" => ^id3,
|
||||||
|
"pleroma" => %{"relationship" => %{"blocking" => true, "followed_by" => false}}
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
"id" => ^id2,
|
||||||
|
"pleroma" => %{"relationship" => %{"blocking" => true, "followed_by" => false}}
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
"id" => ^id1,
|
||||||
|
"pleroma" => %{"relationship" => %{"blocking" => true, "followed_by" => false}}
|
||||||
|
}
|
||||||
|
] =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/blocks?with_relationships=true")
|
||||||
|
|> json_response_and_validate_schema(200)
|
||||||
|
end
|
||||||
|
|
||||||
test "account lookup", %{conn: conn} do
|
test "account lookup", %{conn: conn} do
|
||||||
%{nickname: acct} = insert(:user, %{nickname: "nickname"})
|
%{nickname: acct} = insert(:user, %{nickname: "nickname"})
|
||||||
%{nickname: acct_two} = insert(:user, %{nickname: "nickname@notlocaldoma.in"})
|
%{nickname: acct_two} = insert(:user, %{nickname: "nickname@notlocaldoma.in"})
|
||||||
|
|
|
@ -181,4 +181,18 @@ test "returns empty array if mrf transparency is disabled", %{conn: conn} do
|
||||||
assert [] == json_response_and_validate_schema(conn, 200)
|
assert [] == json_response_and_validate_schema(conn, 200)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "instance languages", %{conn: conn} do
|
||||||
|
assert %{"languages" => ["en"]} =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/instance")
|
||||||
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
|
clear_config([:instance, :languages], ["aa", "bb"])
|
||||||
|
|
||||||
|
assert %{"languages" => ["aa", "bb"]} =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/instance")
|
||||||
|
|> json_response_and_validate_schema(200)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -382,7 +382,9 @@ test "updates the user's background, upload_limit, returns a HTTP 413", %{
|
||||||
"pleroma_background_image" => new_background_oversized
|
"pleroma_background_image" => new_background_oversized
|
||||||
})
|
})
|
||||||
|
|
||||||
assert user_response = json_response_and_validate_schema(res, 413)
|
assert %{"error" => "File is too large"} == json_response_and_validate_schema(res, 413)
|
||||||
|
|
||||||
|
user = Repo.get(User, user.id)
|
||||||
assert user.background == %{}
|
assert user.background == %{}
|
||||||
|
|
||||||
clear_config([:instance, :upload_limit], upload_limit)
|
clear_config([:instance, :upload_limit], upload_limit)
|
||||||
|
|
|
@ -72,7 +72,7 @@ test "it does not return old content after editing" do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "scrub_html_and_truncate/2" do
|
describe "scrub_html_and_truncate/3" do
|
||||||
test "it returns text without encode HTML" do
|
test "it returns text without encode HTML" do
|
||||||
assert Utils.scrub_html_and_truncate("Pleroma's really cool!") == "Pleroma's really cool!"
|
assert Utils.scrub_html_and_truncate("Pleroma's really cool!") == "Pleroma's really cool!"
|
||||||
end
|
end
|
||||||
|
|
|
@ -70,28 +70,6 @@ test "with a bcrypt hash, it updates to a pkbdf2 hash", %{conn: conn} do
|
||||||
assert "$pbkdf2" <> _ = user.password_hash
|
assert "$pbkdf2" <> _ = user.password_hash
|
||||||
end
|
end
|
||||||
|
|
||||||
@tag :skip_on_mac
|
|
||||||
test "with a crypt hash, it updates to a pkbdf2 hash", %{conn: conn} do
|
|
||||||
user =
|
|
||||||
insert(:user,
|
|
||||||
password_hash:
|
|
||||||
"$6$9psBWV8gxkGOZWBz$PmfCycChoxeJ3GgGzwvhlgacb9mUoZ.KUXNCssekER4SJ7bOK53uXrHNb2e4i8yPFgSKyzaW9CcmrDXWIEMtD1"
|
|
||||||
)
|
|
||||||
|
|
||||||
conn =
|
|
||||||
conn
|
|
||||||
|> assign(:auth_user, user)
|
|
||||||
|> assign(:auth_credentials, %{password: "password"})
|
|
||||||
|> AuthenticationPlug.call(%{})
|
|
||||||
|
|
||||||
assert conn.assigns.user.id == conn.assigns.auth_user.id
|
|
||||||
assert conn.assigns.token == nil
|
|
||||||
assert PlugHelper.plug_skipped?(conn, OAuthScopesPlug)
|
|
||||||
|
|
||||||
user = User.get_by_id(user.id)
|
|
||||||
assert "$pbkdf2" <> _ = user.password_hash
|
|
||||||
end
|
|
||||||
|
|
||||||
describe "checkpw/2" do
|
describe "checkpw/2" do
|
||||||
test "check pbkdf2 hash" do
|
test "check pbkdf2 hash" do
|
||||||
hash =
|
hash =
|
||||||
|
@ -101,14 +79,6 @@ test "check pbkdf2 hash" do
|
||||||
refute AuthenticationPlug.checkpw("test-password1", hash)
|
refute AuthenticationPlug.checkpw("test-password1", hash)
|
||||||
end
|
end
|
||||||
|
|
||||||
@tag :skip_on_mac
|
|
||||||
test "check sha512-crypt hash" do
|
|
||||||
hash =
|
|
||||||
"$6$9psBWV8gxkGOZWBz$PmfCycChoxeJ3GgGzwvhlgacb9mUoZ.KUXNCssekER4SJ7bOK53uXrHNb2e4i8yPFgSKyzaW9CcmrDXWIEMtD1"
|
|
||||||
|
|
||||||
assert AuthenticationPlug.checkpw("password", hash)
|
|
||||||
end
|
|
||||||
|
|
||||||
test "check bcrypt hash" do
|
test "check bcrypt hash" do
|
||||||
hash = "$2a$10$uyhC/R/zoE1ndwwCtMusK.TLVzkQ/Ugsbqp3uXI.CTTz0gBw.24jS"
|
hash = "$2a$10$uyhC/R/zoE1ndwwCtMusK.TLVzkQ/Ugsbqp3uXI.CTTz0gBw.24jS"
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ defmodule Pleroma.Workers.ReceiverWorkerTest do
|
||||||
|
|
||||||
alias Pleroma.Workers.ReceiverWorker
|
alias Pleroma.Workers.ReceiverWorker
|
||||||
|
|
||||||
test "it ignores MRF reject" do
|
test "it does not retry MRF reject" do
|
||||||
params = insert(:note).data
|
params = insert(:note).data
|
||||||
|
|
||||||
with_mock Pleroma.Web.ActivityPub.Transmogrifier,
|
with_mock Pleroma.Web.ActivityPub.Transmogrifier,
|
||||||
|
@ -22,4 +22,31 @@ test "it ignores MRF reject" do
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "it does not retry ObjectValidator reject" do
|
||||||
|
params =
|
||||||
|
insert(:note_activity).data
|
||||||
|
|> Map.put("id", Pleroma.Web.ActivityPub.Utils.generate_activity_id())
|
||||||
|
|> Map.put("object", %{
|
||||||
|
"type" => "Note",
|
||||||
|
"id" => Pleroma.Web.ActivityPub.Utils.generate_object_id()
|
||||||
|
})
|
||||||
|
|
||||||
|
with_mock Pleroma.Web.ActivityPub.ObjectValidator, [:passthrough],
|
||||||
|
validate: fn _, _ -> {:error, %Ecto.Changeset{}} end do
|
||||||
|
assert {:cancel, {:error, %Ecto.Changeset{}}} =
|
||||||
|
ReceiverWorker.perform(%Oban.Job{
|
||||||
|
args: %{"op" => "incoming_ap_doc", "params" => params}
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it does not retry duplicates" do
|
||||||
|
params = insert(:note_activity).data
|
||||||
|
|
||||||
|
assert {:cancel, :already_present} =
|
||||||
|
ReceiverWorker.perform(%Oban.Job{
|
||||||
|
args: %{"op" => "incoming_ap_doc", "params" => params}
|
||||||
|
})
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||||
# SPDX-License-Identifier: AGPL-3.0-only
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
Code.put_compiler_option(:warnings_as_errors, true)
|
||||||
|
|
||||||
os_exclude = if :os.type() == {:unix, :darwin}, do: [skip_on_mac: true], else: []
|
os_exclude = if :os.type() == {:unix, :darwin}, do: [skip_on_mac: true], else: []
|
||||||
ExUnit.start(exclude: [:federated, :erratic] ++ os_exclude)
|
ExUnit.start(exclude: [:federated, :erratic] ++ os_exclude)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue