Compare commits

...

39 Commits

Author SHA1 Message Date
Your New SJW Waifu af34602a4b spam https://poa.st/objects/75c7cb92-1de4-4131-92e7-875a27a3d345 2024-02-18 12:39:51 -06:00
Your New SJW Waifu 6078d63f4a Merge remote-tracking branch 'upstream/develop' into neckbeard 2024-02-18 12:37:26 -06:00
feld 0b9bc4a0d0 Merge branch 'memleak' into 'develop'
Force more frequent full_sweep GC runs on the Websocket processes

See merge request pleroma/pleroma!4060
2024-02-17 16:21:55 +00:00
Mark Felder 7e99d0619d Force more frequent full_sweep GC runs on the Websocket processes
Websocket processes seem to be the primary culprit for Binary memory allocation bloat.
2024-02-17 09:53:52 -05:00
Haelwenn a145d909b5 Merge branch 'weblate' into 'develop'
Translations update from Pleroma Weblate

See merge request pleroma/pleroma!4070
2024-02-16 18:28:55 +00:00
SyoBoN 2c9fed9b73 Translated using Weblate (Japanese)
Currently translated at 63.1% (60 of 95 strings)

Translation: Pleroma/Pleroma Backend (domain errors)
Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-backend-domain-errors/ja/
2024-02-16 17:54:01 +00:00
feld 0fbec6b532 Merge branch 'deps-changelog-revert' into 'develop'
Revert "Support a new changelog entry type: deps"

See merge request pleroma/pleroma!4071
2024-02-16 17:53:52 +00:00
Mark Felder 1951d56ed9 Revert "Add support for a "deps" changelog type and document deps changes since 2.6.1 release"
This reverts commit 2a4fa4c408.
2024-02-16 12:53:18 -05:00
Mark Felder c9cd449bba Revert "Support a new changelog entry type: deps"
This reverts commit 4648997a10.
2024-02-16 12:52:56 -05:00
feld 03834454d9 Merge branch 'tesla' into 'develop'
Update Tesla, document some deps changes

See merge request pleroma/pleroma!4069
2024-02-15 15:27:34 +00:00
Mark Felder 2a4fa4c408 Add support for a "deps" changelog type and document deps changes since 2.6.1 release 2024-02-15 10:27:13 -05:00
Mark Felder 772f8d08cf Tesla changelog 2024-02-15 10:24:32 -05:00
Mark Felder 4648997a10 Support a new changelog entry type: deps 2024-02-15 10:24:31 -05:00
feld b91317b9bf Merge branch 'bandit' into 'develop'
Support Bandit as a Phoenix HTTP adapter

See merge request pleroma/pleroma!4068
2024-02-15 15:23:41 +00:00
Mark Felder 202721e80c Remove Cowboy-specific HTTP options
These were only used in dev and served no specific purpose. The equivalent settings for Bandit are under a key called :http1_options and the default values are set to 10_000.
2024-02-15 09:55:03 -05:00
Mark Felder 0c5bec0493 Support Bandit as an alternate HTTP backend to Cowboy. This is currently considered experimental, but may improve performance and resource usage. 2024-02-15 09:54:52 -05:00
feld 4dd8a1a1ca Merge branch 'websocket-refactor' into 'develop'
Websocket refactor to use Phoenix.Socket.Transport

See merge request pleroma/pleroma!4064
2024-02-15 14:36:54 +00:00
lain d3208d2250 Merge branch 'oauth-nickname' into 'develop'
Use User.full_nickname/1 in oauth html template

See merge request pleroma/pleroma!4054
2024-02-15 09:35:39 +00:00
lain f2f455f283 Merge branch 'frontend-caching' into 'develop'
FrontendStatic should have reasonable caching

See merge request pleroma/pleroma!3685
2024-02-15 09:23:47 +00:00
Haelwenn f28dcc9cb7 Merge branch 'config-stat-symlink' into 'develop'
Config: Check the permissions of the linked file instead of the symlink

See merge request pleroma/pleroma!4061
2024-02-15 01:48:03 +00:00
Haelwenn d19642d7eb Merge branch 'bugfix-ccworks' into 'develop'
Bugfix for ccworks AP bridge

Closes #3234

See merge request pleroma/pleroma!4043
2024-02-15 01:30:22 +00:00
feld 802c618885 Merge branch 'atom-leaks' into 'develop'
Fix minor atom leaks

See merge request pleroma/pleroma!4065
2024-02-14 23:28:00 +00:00
Mark Felder 9138754b0a Changelog 2024-02-14 18:04:39 -05:00
Mark Felder 91c83a82a0 Fix atom leak in background worker
The only permitted values are "blocks_import", "follow_import", "mutes_import" of which we already have the equivalent atoms defined.
2024-02-14 18:03:54 -05:00
Mark Felder 86e6d395d9 Fix atom leak in password digest functionality
The value here gets passesd to :crypto.pbkdf2_hmac and it expects one of these atoms: :sha | :sha224 | :sha256 | :sha384 | :sha512 so it will always exist
2024-02-14 17:54:56 -05:00
Mark Felder 6be129ead2 Websocket refactor changelog 2024-02-14 15:27:12 -05:00
Mark Felder d0f4b2b02f Remove invalid test
It is not allowed to use the Sec-WebSocket-Protocol header for arbitrary values. This was possible due to the raw websocket handling we were doing with Cowboy, but Phoenix.Socket.Transport does not allow this as the value of this header is compared against a static list of subprotocols.

https://hexdocs.pm/phoenix/Phoenix.Endpoint.html#socket/3-websocket-configuration

Additionally I cannot find anywhere that we depended on this behavior. Setting the Sec-WebSocket-Protocol header does not appear to be a part of PleromaFE.
2024-02-14 15:27:12 -05:00
Mark Felder 64ad451a7b Websocket refactor to use Phoenix.Socket.Transport
This will make us compatible with Cowboy and Bandit
2024-02-14 15:27:07 -05:00
feld af9bb77cad Merge branch 'gun-logs' into 'develop'
Gun connection pool logs

See merge request pleroma/pleroma!4063
2024-02-14 18:57:11 +00:00
feld 1b2f9d4a6d Merge branch 'proxy-headers' into 'develop'
MediaProxy RFC compliance

See merge request pleroma/pleroma!4062
2024-02-14 18:56:54 +00:00
Mark Felder 9a4c8e2316 Change some Gun connection pool logs to debug level 2024-02-14 13:28:32 -05:00
Mark Felder 60ba6fd244 MediaProxy RFC compliance 2024-02-14 13:25:52 -05:00
Haelwenn (lanodan) Monnier 3b82864bcc
Config: Check the permissions of the linked file instead of the symlink↵ 2024-02-14 18:19:50 +01:00
marcin mikołajczak 0fcdcc2300 Use User.full_nickname/1 in oauth html template
Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
2024-02-09 16:46:45 +01:00
Haelwenn (lanodan) Monnier 799891d359
Transmogrifier: Cleanup obsolete handling of `"contentMap": null` 2024-01-26 17:10:10 +01:00
Haelwenn (lanodan) Monnier 558b421079
Test incoming federation from Convergence AP Bridge 2024-01-26 17:05:18 +01:00
Haelwenn (lanodan) Monnier acef2a4a40
CommonFixes: Use Maps.filter_empty_values on fix_object_defaults 2024-01-26 16:19:25 +01:00
Haelwenn (lanodan) Monnier 0de1a7629c
Maps: Add filter_empty_values/1 2024-01-26 16:18:29 +01:00
Mark Felder 6b74a55274 InstanceStatic should have reasonable caching
While here fix the naming convention of the old module attribute restricting caching and add a new one for the default cache value

All frontends should be shipped with versioned assets. There be dragons if you don't.
2022-07-01 15:40:40 -05:00
32 changed files with 365 additions and 323 deletions

View File

View File

@ -0,0 +1 @@
Support Bandit as an alternative to Cowboy for the HTTP server.

View File

@ -0,0 +1 @@
Fix federation with Convergence AP Bridge

View File

@ -0,0 +1 @@
- Config: Check the permissions of the linked file instead of the symlink

View File

@ -0,0 +1 @@
MediaProxy was setting the content-length header which is not permitted by RFC9112§6.2 when we are chunking the reply as it conflicts with the existence of the transfer-encoding header.

View File

1
changelog.d/memleak.fix Normal file
View File

@ -0,0 +1 @@
Fix a memory leak caused by Websocket connections that would not enter a state where a full garbage collection run could be triggered.

View File

@ -0,0 +1 @@
Use User.full_nickname/1 in oauth html template

1
changelog.d/tesla.deps Normal file
View File

@ -0,0 +1 @@
Update Tesla HTTP client middleware to 1.8.0

View File

@ -0,0 +1 @@
Refactor the Mastodon /api/v1/streaming websocket handler to use Phoenix.Socket.Transport

View File

@ -114,14 +114,7 @@ config :pleroma, :uri_schemes,
config :pleroma, Pleroma.Web.Endpoint,
url: [host: "localhost"],
http: [
ip: {127, 0, 0, 1},
dispatch: [
{:_,
[
{"/api/v1/streaming", Pleroma.Web.MastodonAPI.WebsocketHandler, []},
{:_, Plug.Cowboy.Handler, {Pleroma.Web.Endpoint, []}}
]}
]
ip: {127, 0, 0, 1}
],
protocol: "https",
secret_key_base: "aK4Abxf29xU9TTDKre9coZPUgevcVCFQJe/5xP/7Lt4BEif6idBIbjupVbOrbKxl",

View File

@ -8,8 +8,7 @@ import Config
# with brunch.io to recompile .js and .css sources.
config :pleroma, Pleroma.Web.Endpoint,
http: [
port: 4000,
protocol_options: [max_request_line_length: 8192, max_header_value_length: 8192]
port: 4000
],
protocol: "http",
debug_errors: true,

View File

@ -1,93 +0,0 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Phoenix.Transports.WebSocket.Raw do
import Plug.Conn,
only: [
fetch_query_params: 1,
send_resp: 3
]
alias Phoenix.Socket.Transport
def default_config do
[
timeout: 60_000,
transport_log: false,
cowboy: Phoenix.Endpoint.CowboyWebSocket
]
end
def init(%Plug.Conn{method: "GET"} = conn, {endpoint, handler, transport}) do
{_, opts} = handler.__transport__(transport)
conn =
conn
|> fetch_query_params
|> Transport.transport_log(opts[:transport_log])
|> Transport.check_origin(handler, endpoint, opts)
case conn do
%{halted: false} = conn ->
case handler.connect(%{
endpoint: endpoint,
transport: transport,
options: [serializer: nil],
params: conn.params
}) do
{:ok, socket} ->
{:ok, conn, {__MODULE__, {socket, opts}}}
:error ->
send_resp(conn, :forbidden, "")
{:error, conn}
end
_ ->
{:error, conn}
end
end
def init(conn, _) do
send_resp(conn, :bad_request, "")
{:error, conn}
end
def ws_init({socket, config}) do
Process.flag(:trap_exit, true)
{:ok, %{socket: socket}, config[:timeout]}
end
def ws_handle(op, data, state) do
state.socket.handler
|> apply(:handle, [op, data, state])
|> case do
{op, data} ->
{:reply, {op, data}, state}
{op, data, state} ->
{:reply, {op, data}, state}
%{} = state ->
{:ok, state}
_ ->
{:ok, state}
end
end
def ws_info({_, _} = tuple, state) do
{:reply, tuple, state}
end
def ws_info(_tuple, state), do: {:ok, state}
def ws_close(state) do
ws_handle(:closed, :normal, state)
end
def ws_terminate(reason, state) do
ws_handle(:closed, reason, state)
end
end

View File

@ -21,7 +21,7 @@ defmodule Pleroma.Config.ReleaseRuntimeProvider do
with_runtime_config =
if File.exists?(config_path) do
# <https://git.pleroma.social/pleroma/pleroma/-/issues/3135>
%File.Stat{mode: mode} = File.lstat!(config_path)
%File.Stat{mode: mode} = File.stat!(config_path)
if Bitwise.band(mode, 0o007) > 0 do
raise "Configuration at #{config_path} has world-permissions, execute the following: chmod o= #{config_path}"

View File

@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
# Copyright © 2017-2024 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Maps do
@ -18,4 +18,17 @@ defmodule Pleroma.Maps do
rescue
_ -> data
end
def filter_empty_values(data) do
# TODO: Change to Map.filter in Elixir 1.13+
data
|> Enum.filter(fn
{_k, nil} -> false
{_k, ""} -> false
{_k, []} -> false
{_k, %{} = v} -> Map.keys(v) != []
{_k, _v} -> true
end)
|> Map.new()
end
end

View File

@ -28,7 +28,7 @@ defmodule Pleroma.Password.Pbkdf2 do
iterations = String.to_integer(iterations)
digest = String.to_atom(digest)
digest = String.to_existing_atom(digest)
binary_hash =
KeyGenerator.generate(password, salt, digest: digest, iterations: iterations, length: 64)

View File

@ -8,7 +8,7 @@ defmodule Pleroma.ReverseProxy do
~w(if-unmodified-since if-none-match) ++ @range_headers
@resp_cache_headers ~w(etag date last-modified)
@keep_resp_headers @resp_cache_headers ++
~w(content-length content-type content-disposition content-encoding) ++
~w(content-type content-disposition content-encoding) ++
~w(content-range accept-ranges vary)
@default_cache_control_header "public, max-age=1209600"
@valid_resp_codes [200, 206, 304]

View File

@ -59,7 +59,7 @@ defmodule Pleroma.Telemetry.Logger do
_,
_
) do
Logger.error(fn ->
Logger.debug(fn ->
"Connection pool had to refuse opening a connection to #{key} due to connection limit exhaustion"
end)
end
@ -81,7 +81,7 @@ defmodule Pleroma.Telemetry.Logger do
%{key: key, protocol: :http},
_
) do
Logger.info(fn ->
Logger.debug(fn ->
"Pool worker for #{key}: #{length(clients)} clients are using an HTTP1 connection at the same time, head-of-line blocking might occur."
end)
end

View File

@ -0,0 +1,85 @@
# Pleroma: A lightweight social networking server
# Copyright ©️ 2017-2022 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.AntiMentionSpamPolicy do
alias Pleroma.User
require Pleroma.Constants
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
defp user_has_posted?(%User{} = u), do: u.note_count > 0
defp user_has_age?(%User{} = u) do
diff = NaiveDateTime.utc_now() |> NaiveDateTime.diff(u.inserted_at, :second)
diff >= :timer.seconds(30)
end
defp good_reputation?(%User{} = u) do
user_has_age?(u) and user_has_posted?(u)
end
# copied from HellthreadPolicy
defp get_recipient_count(message) do
recipients = (message["to"] || []) ++ (message["cc"] || [])
follower_collection =
User.get_cached_by_ap_id(message["actor"] || message["attributedTo"]).follower_address
if Enum.member?(recipients, Pleroma.Constants.as_public()) do
recipients =
recipients
|> List.delete(Pleroma.Constants.as_public())
|> List.delete(follower_collection)
{:public, length(recipients)}
else
recipients =
recipients
|> List.delete(follower_collection)
{:not_public, length(recipients)}
end
end
defp object_has_recipients?(%{"object" => object} = activity) do
{_, object_count} = get_recipient_count(object)
{_, activity_count} = get_recipient_count(activity)
object_count + activity_count > 0
end
defp object_has_recipients?(object) do
{_, count} = get_recipient_count(object)
count > 0
end
@impl true
def filter(%{"type" => "Create", "actor" => actor} = activity) do
with {:ok, %User{local: false} = u} <- User.get_or_fetch_by_ap_id(actor),
{:has_mentions, true} <- {:has_mentions, object_has_recipients?(activity)},
{:good_reputation, true} <- {:good_reputation, good_reputation?(u)} do
{:ok, activity}
else
{:ok, %User{local: true}} ->
{:ok, activity}
{:has_mentions, false} ->
{:ok, activity}
{:good_reputation, false} ->
{:reject, "[AntiMentionSpamPolicy] User rejected"}
{:error, _} ->
{:reject, "[AntiMentionSpamPolicy] Failed to get or fetch user by ap_id"}
e ->
{:reject, "[AntiMentionSpamPolicy] Unhandled error #{inspect(e)}"}
end
end
# in all other cases, pass through
def filter(message), do: {:ok, message}
@impl true
def describe, do: {:ok, %{}}
end

View File

@ -4,6 +4,7 @@
defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes do
alias Pleroma.EctoType.ActivityPub.ObjectValidators
alias Pleroma.Maps
alias Pleroma.Object
alias Pleroma.Object.Containment
alias Pleroma.User
@ -24,6 +25,8 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes do
end
def fix_object_defaults(data) do
data = Maps.filter_empty_values(data)
context =
Utils.maybe_create_context(
data["context"] || data["conversation"] || data["inReplyTo"] || data["id"]

View File

@ -336,10 +336,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
def fix_tag(object), do: object
def fix_content_map(%{"contentMap" => nil} = object) do
Map.drop(object, ["contentMap"])
end
# content map usually only has one language so this will do for now.
def fix_content_map(%{"contentMap" => content_map} = object) do
content_groups = Map.to_list(content_map)

View File

@ -9,6 +9,16 @@ defmodule Pleroma.Web.Endpoint do
alias Pleroma.Config
socket("/api/v1/streaming", Pleroma.Web.MastodonAPI.WebsocketHandler,
longpoll: false,
websocket: [
path: "/",
compress: false,
error_handler: {Pleroma.Web.MastodonAPI.WebsocketHandler, :handle_error, []},
fullsweep_after: 20
]
)
socket("/socket", Pleroma.Web.UserSocket,
websocket: [
path: "/websocket",
@ -18,7 +28,8 @@ defmodule Pleroma.Web.Endpoint do
],
timeout: 60_000,
transport_log: false,
compress: false
compress: false,
fullsweep_after: 20
],
longpoll: false
)
@ -32,7 +43,8 @@ defmodule Pleroma.Web.Endpoint do
plug(Pleroma.Web.Plugs.HTTPSecurityPlug)
plug(Pleroma.Web.Plugs.UploadedMedia)
@static_cache_control "public, no-cache"
@static_cache_control "public, max-age=1209600"
@static_cache_disabled "public, no-cache"
# InstanceStatic needs to be before Plug.Static to be able to override shipped-static files
# If you're adding new paths to `only:` you'll need to configure them in InstanceStatic as well
@ -43,22 +55,32 @@ defmodule Pleroma.Web.Endpoint do
from: :pleroma,
only: ["emoji", "images"],
gzip: true,
cache_control_for_etags: "public, max-age=1209600",
headers: %{
"cache-control" => "public, max-age=1209600"
}
)
plug(Pleroma.Web.Plugs.InstanceStatic,
at: "/",
gzip: true,
cache_control_for_etags: @static_cache_control,
headers: %{
"cache-control" => @static_cache_control
}
)
# Careful! No `only` restriction here, as we don't know what frontends contain.
plug(Pleroma.Web.Plugs.InstanceStatic,
at: "/",
gzip: true,
cache_control_for_etags: @static_cache_disabled,
headers: %{
"cache-control" => @static_cache_disabled
}
)
plug(Pleroma.Web.Plugs.FrontendStatic,
at: "/",
frontend_type: :primary,
only: ["index.html"],
gzip: true,
cache_control_for_etags: @static_cache_disabled,
headers: %{
"cache-control" => @static_cache_disabled
}
)
plug(Pleroma.Web.Plugs.FrontendStatic,
at: "/",
frontend_type: :primary,
@ -75,9 +97,9 @@ defmodule Pleroma.Web.Endpoint do
at: "/pleroma/admin",
frontend_type: :admin,
gzip: true,
cache_control_for_etags: @static_cache_control,
cache_control_for_etags: @static_cache_disabled,
headers: %{
"cache-control" => @static_cache_control
"cache-control" => @static_cache_disabled
}
)
@ -92,9 +114,9 @@ defmodule Pleroma.Web.Endpoint do
only: Pleroma.Constants.static_only_files(),
# credo:disable-for-previous-line Credo.Check.Readability.MaxLineLength
gzip: true,
cache_control_for_etags: @static_cache_control,
cache_control_for_etags: @static_cache_disabled,
headers: %{
"cache-control" => @static_cache_control
"cache-control" => @static_cache_disabled
}
)

View File

@ -11,28 +11,21 @@ defmodule Pleroma.Web.MastodonAPI.WebsocketHandler do
alias Pleroma.Web.Streamer
alias Pleroma.Web.StreamerView
@behaviour :cowboy_websocket
@behaviour Phoenix.Socket.Transport
# Client ping period.
@tick :timer.seconds(30)
# Cowboy timeout period.
@timeout :timer.seconds(60)
# Hibernate every X messages
@hibernate_every 100
def init(%{qs: qs} = req, state) do
with params <- Enum.into(:cow_qs.parse_qs(qs), %{}),
sec_websocket <- :cowboy_req.header("sec-websocket-protocol", req, nil),
access_token <- Map.get(params, "access_token"),
{:ok, user, oauth_token} <- authenticate_request(access_token, sec_websocket),
{:ok, topic} <- Streamer.get_topic(params["stream"], user, oauth_token, params) do
req =
if sec_websocket do
:cowboy_req.set_resp_header("sec-websocket-protocol", sec_websocket, req)
else
req
end
@impl Phoenix.Socket.Transport
def child_spec(_opts), do: :ignore
# This only prepares the connection and is not in the process yet
@impl Phoenix.Socket.Transport
def connect(%{params: params} = transport_info) do
with access_token <- Map.get(params, "access_token"),
{:ok, user, oauth_token} <- authenticate_request(access_token),
{:ok, topic} <-
Streamer.get_topic(params["stream"], user, oauth_token, params) do
topics =
if topic do
[topic]
@ -40,41 +33,40 @@ defmodule Pleroma.Web.MastodonAPI.WebsocketHandler do
[]
end
{:cowboy_websocket, req,
%{user: user, topics: topics, oauth_token: oauth_token, count: 0, timer: nil},
%{idle_timeout: @timeout}}
state = %{
user: user,
topics: topics,
oauth_token: oauth_token,
count: 0,
timer: nil
}
{:ok, state}
else
{:error, :bad_topic} ->
Logger.debug("#{__MODULE__} bad topic #{inspect(req)}")
req = :cowboy_req.reply(404, req)
{:ok, req, state}
Logger.debug("#{__MODULE__} bad topic #{inspect(transport_info)}")
{:error, :bad_topic}
{:error, :unauthorized} ->
Logger.debug("#{__MODULE__} authentication error: #{inspect(req)}")
req = :cowboy_req.reply(401, req)
{:ok, req, state}
Logger.debug("#{__MODULE__} authentication error: #{inspect(transport_info)}")
{:error, :unauthorized}
end
end
def websocket_init(state) do
Logger.debug(
"#{__MODULE__} accepted websocket connection for user #{(state.user || %{id: "anonymous"}).id}, topics #{state.topics}"
)
# All subscriptions/links and messages cannot be created
# until the processed is launched with init/1
@impl Phoenix.Socket.Transport
def init(state) do
Enum.each(state.topics, fn topic -> Streamer.add_socket(topic, state.oauth_token) end)
{:ok, %{state | timer: timer()}}
Process.send_after(self(), :ping, @tick)
{:ok, state}
end
# Client's Pong frame.
def websocket_handle(:pong, state) do
if state.timer, do: Process.cancel_timer(state.timer)
{:ok, %{state | timer: timer()}}
end
# We only receive pings for now
def websocket_handle(:ping, state), do: {:ok, state}
def websocket_handle({:text, text}, state) do
@impl Phoenix.Socket.Transport
def handle_in({text, [opcode: :text]}, state) do
with {:ok, %{} = event} <- Jason.decode(text) do
handle_client_event(event, state)
else
@ -84,50 +76,47 @@ defmodule Pleroma.Web.MastodonAPI.WebsocketHandler do
end
end
def websocket_handle(frame, state) do
def handle_in(frame, state) do
Logger.error("#{__MODULE__} received frame: #{inspect(frame)}")
{:ok, state}
end
def websocket_info({:render_with_user, view, template, item, topic}, state) do
@impl Phoenix.Socket.Transport
def handle_info({:render_with_user, view, template, item, topic}, state) do
user = %User{} = User.get_cached_by_ap_id(state.user.ap_id)
unless Streamer.filtered_by_user?(user, item) do
websocket_info({:text, view.render(template, item, user, topic)}, %{state | user: user})
message = view.render(template, item, user, topic)
{:push, {:text, message}, %{state | user: user}}
else
{:ok, state}
end
end
def websocket_info({:text, message}, state) do
# If the websocket processed X messages, force an hibernate/GC.
# We don't hibernate at every message to balance CPU usage/latency with RAM usage.
if state.count > @hibernate_every do
{:reply, {:text, message}, %{state | count: 0}, :hibernate}
else
{:reply, {:text, message}, %{state | count: state.count + 1}}
end
def handle_info({:text, text}, state) do
{:push, {:text, text}, state}
end
# Ping tick. We don't re-queue a timer there, it is instead queued when :pong is received.
# As we hibernate there, reset the count to 0.
# If the client misses :pong, Cowboy will automatically timeout the connection after
# `@idle_timeout`.
def websocket_info(:tick, state) do
{:reply, :ping, %{state | timer: nil, count: 0}, :hibernate}
def handle_info(:ping, state) do
Process.send_after(self(), :ping, @tick)
{:push, {:ping, ""}, state}
end
def websocket_info(:close, state) do
{:stop, state}
def handle_info(:close, state) do
{:stop, {:closed, 'connection closed by server'}, state}
end
# State can be `[]` only in case we terminate before switching to websocket,
# we already log errors for these cases in `init/1`, so just do nothing here
def terminate(_reason, _req, []), do: :ok
def handle_info(msg, state) do
Logger.debug("#{__MODULE__} received info: #{inspect(msg)}")
def terminate(reason, _req, state) do
{:ok, state}
end
@impl Phoenix.Socket.Transport
def terminate(reason, state) do
Logger.debug(
"#{__MODULE__} terminating websocket connection for user #{(state.user || %{id: "anonymous"}).id}, topics #{state.topics || "?"}: #{inspect(reason)}"
"#{__MODULE__} terminating websocket connection for user #{(state.user || %{id: "anonymous"}).id}, topics #{state.topics || "?"}: #{inspect(reason)})"
)
Enum.each(state.topics, fn topic -> Streamer.remove_socket(topic) end)
@ -135,16 +124,13 @@ defmodule Pleroma.Web.MastodonAPI.WebsocketHandler do
end
# Public streams without authentication.
defp authenticate_request(nil, nil) do
defp authenticate_request(nil) do
{:ok, nil, nil}
end
# Authenticated streams.
defp authenticate_request(access_token, sec_websocket) do
token = access_token || sec_websocket
with true <- is_bitstring(token),
oauth_token = %Token{user_id: user_id} <- Repo.get_by(Token, token: token),
defp authenticate_request(access_token) do
with oauth_token = %Token{user_id: user_id} <- Repo.get_by(Token, token: access_token),
user = %User{} <- User.get_cached_by_id(user_id) do
{:ok, user, oauth_token}
else
@ -152,36 +138,32 @@ defmodule Pleroma.Web.MastodonAPI.WebsocketHandler do
end
end
defp timer do
Process.send_after(self(), :tick, @tick)
end
defp handle_client_event(%{"type" => "subscribe", "stream" => _topic} = params, state) do
with {_, {:ok, topic}} <-
{:topic, Streamer.get_topic(params["stream"], state.user, state.oauth_token, params)},
{_, false} <- {:subscribed, topic in state.topics} do
Streamer.add_socket(topic, state.oauth_token)
{[
{:text,
StreamerView.render("pleroma_respond.json", %{type: "subscribe", result: "success"})}
], %{state | topics: [topic | state.topics]}}
message =
StreamerView.render("pleroma_respond.json", %{type: "subscribe", result: "success"})
{:reply, :ok, {:text, message}, %{state | topics: [topic | state.topics]}}
else
{:subscribed, true} ->
{[
{:text,
StreamerView.render("pleroma_respond.json", %{type: "subscribe", result: "ignored"})}
], state}
message =
StreamerView.render("pleroma_respond.json", %{type: "subscribe", result: "ignored"})
{:reply, :error, {:text, message}, state}
{:topic, {:error, error}} ->
{[
{:text,
StreamerView.render("pleroma_respond.json", %{
type: "subscribe",
result: "error",
error: error
})}
], state}
message =
StreamerView.render("pleroma_respond.json", %{
type: "subscribe",
result: "error",
error: error
})
{:reply, :error, {:text, message}, state}
end
end
@ -191,26 +173,26 @@ defmodule Pleroma.Web.MastodonAPI.WebsocketHandler do
{_, true} <- {:subscribed, topic in state.topics} do
Streamer.remove_socket(topic)
{[
{:text,
StreamerView.render("pleroma_respond.json", %{type: "unsubscribe", result: "success"})}
], %{state | topics: List.delete(state.topics, topic)}}
message =
StreamerView.render("pleroma_respond.json", %{type: "unsubscribe", result: "success"})
{:reply, :ok, {:text, message}, %{state | topics: List.delete(state.topics, topic)}}
else
{:subscribed, false} ->
{[
{:text,
StreamerView.render("pleroma_respond.json", %{type: "unsubscribe", result: "ignored"})}
], state}
message =
StreamerView.render("pleroma_respond.json", %{type: "unsubscribe", result: "ignored"})
{:reply, :error, {:text, message}, state}
{:topic, {:error, error}} ->
{[
{:text,
StreamerView.render("pleroma_respond.json", %{
type: "unsubscribe",
result: "error",
error: error
})}
], state}
message =
StreamerView.render("pleroma_respond.json", %{
type: "unsubscribe",
result: "error",
error: error
})
{:reply, :error, {:text, message}, state}
end
end
@ -219,39 +201,47 @@ defmodule Pleroma.Web.MastodonAPI.WebsocketHandler do
state
) do
with {:auth, nil, nil} <- {:auth, state.user, state.oauth_token},
{:ok, user, oauth_token} <- authenticate_request(access_token, nil) do
{[
{:text,
StreamerView.render("pleroma_respond.json", %{
type: "pleroma:authenticate",
result: "success"
})}
], %{state | user: user, oauth_token: oauth_token}}
{:ok, user, oauth_token} <- authenticate_request(access_token) do
message =
StreamerView.render("pleroma_respond.json", %{
type: "pleroma:authenticate",
result: "success"
})
{:reply, :ok, {:text, message}, %{state | user: user, oauth_token: oauth_token}}
else
{:auth, _, _} ->
{[
{:text,
StreamerView.render("pleroma_respond.json", %{
type: "pleroma:authenticate",
result: "error",
error: :already_authenticated
})}
], state}
message =
StreamerView.render("pleroma_respond.json", %{
type: "pleroma:authenticate",
result: "error",
error: :already_authenticated
})
{:reply, :error, {:text, message}, state}
_ ->
{[
{:text,
StreamerView.render("pleroma_respond.json", %{
type: "pleroma:authenticate",
result: "error",
error: :unauthorized
})}
], state}
message =
StreamerView.render("pleroma_respond.json", %{
type: "pleroma:authenticate",
result: "error",
error: :unauthorized
})
{:reply, :error, {:text, message}, state}
end
end
defp handle_client_event(params, state) do
Logger.error("#{__MODULE__} received unknown event: #{inspect(params)}")
{[], state}
{:ok, state}
end
def handle_error(conn, :unauthorized) do
Plug.Conn.send_resp(conn, 401, "Unauthorized")
end
def handle_error(conn, _reason) do
Plug.Conn.send_resp(conn, 404, "Not Found")
end
end

View File

@ -13,7 +13,7 @@
<div class="account-header__avatar" style="background-image: url('<%= Pleroma.User.avatar_url(@user) %>')"></div>
<div class="account-header__meta">
<div class="account-header__display-name"><%= @user.name %></div>
<div class="account-header__nickname">@<%= @user.nickname %>@<%= Pleroma.User.get_host(@user) %></div>
<div class="account-header__nickname">@<%= Pleroma.User.full_nickname(@user.nickname) %></div>
</div>
</div>
<% end %>

View File

@ -28,7 +28,7 @@ defmodule Pleroma.Workers.BackgroundWorker do
def perform(%Job{args: %{"op" => op, "user_id" => user_id, "identifiers" => identifiers}})
when op in ["blocks_import", "follow_import", "mutes_import"] do
user = User.get_cached_by_id(user_id)
{:ok, User.Import.perform(String.to_atom(op), user, identifiers)}
{:ok, User.Import.perform(String.to_existing_atom(op), user, identifiers)}
end
def perform(%Job{

View File

@ -137,7 +137,7 @@ defmodule Pleroma.Mixfile do
{:calendar, "~> 1.0"},
{:cachex, "~> 3.2"},
{:poison, "~> 3.0", override: true},
{:tesla, "~> 1.4.0", override: true},
{:tesla, "~> 1.8.0"},
{:castore, "~> 0.1"},
{:cowlib, "~> 2.9", override: true},
{:gun, "~> 2.0.0-rc.1", override: true},
@ -188,6 +188,7 @@ defmodule Pleroma.Mixfile do
{:exile,
git: "https://git.pleroma.social/pleroma/elixir-libraries/exile.git",
ref: "0d6337cf68e7fbc8a093cae000955aa93b067f91"},
{:bandit, "~> 1.2"},
## dev & test
{:ex_doc, "~> 0.22", only: :dev, runtime: false},

View File

@ -1,5 +1,6 @@
%{
"accept": {:hex, :accept, "0.3.5", "b33b127abca7cc948bbe6caa4c263369abf1347cfa9d8e699c6d214660f10cd1", [:rebar3], [], "hexpm", "11b18c220bcc2eab63b5470c038ef10eb6783bcb1fcdb11aa4137defa5ac1bb8"},
"bandit": {:hex, :bandit, "1.2.1", "aa485b4ac175065b8e0fb5864ddd5dd7b50d52336b36f61c82f484c3718b3d15", [:mix], [{:hpax, "~> 0.1.1", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 1.0", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "27393e590a407f1b7d51c5fee4737f139fe224a30449ce25061eac70f763896b"},
"base62": {:hex, :base62, "1.2.2", "85c6627eb609317b70f555294045895ffaaeb1758666ab9ef9ca38865b11e629", [:mix], [{:custom_base, "~> 0.2.1", [hex: :custom_base, repo: "hexpm", optional: false]}], "hexpm", "d41336bda8eaa5be197f1e4592400513ee60518e5b9f4dcf38f4b4dae6f377bb"},
"bbcode_pleroma": {:hex, :bbcode_pleroma, "0.2.0", "d36f5bca6e2f62261c45be30fa9b92725c0655ad45c99025cb1c3e28e25803ef", [:mix], [{:nimble_parsec, "~> 0.5", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "19851074419a5fedb4ef49e1f01b30df504bb5dbb6d6adfc135238063bebd1c3"},
"bcrypt_elixir": {:hex, :bcrypt_elixir, "2.3.1", "5114d780459a04f2b4aeef52307de23de961b69e13a5cd98a911e39fda13f420", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "42182d5f46764def15bf9af83739e3bf4ad22661b1c34fc3e88558efced07279"},
@ -51,7 +52,7 @@
"fast_html": {:hex, :fast_html, "2.2.0", "6c5ef1be087a4ed613b0379c13f815c4d11742b36b67bb52cee7859847c84520", [:make, :mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}], "hexpm", "064c4f23b4a6168f9187dac8984b056f2c531bb0787f559fd6a8b34b38aefbae"},
"fast_sanitize": {:hex, :fast_sanitize, "0.2.3", "67b93dfb34e302bef49fec3aaab74951e0f0602fd9fa99085987af05bd91c7a5", [:mix], [{:fast_html, "~> 2.0", [hex: :fast_html, repo: "hexpm", optional: false]}, {:plug, "~> 1.8", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "e8ad286d10d0386e15d67d0ee125245ebcfbc7d7290b08712ba9013c8c5e56e2"},
"file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
"finch": {:hex, :finch, "0.17.0", "17d06e1d44d891d20dbd437335eebe844e2426a0cd7e3a3e220b461127c73f70", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.3", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2.6 or ~> 1.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "8d014a661bb6a437263d4b5abf0bcbd3cf0deb26b1e8596f2a271d22e48934c7"},
"finch": {:hex, :finch, "0.18.0", "944ac7d34d0bd2ac8998f79f7a811b21d87d911e77a786bc5810adb75632ada4", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.3", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2.6 or ~> 1.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "69f5045b042e531e53edc2574f15e25e735b522c37e2ddb766e15b979e03aa65"},
"flake_id": {:hex, :flake_id, "0.1.0", "7716b086d2e405d09b647121a166498a0d93d1a623bead243e1f74216079ccb3", [:mix], [{:base62, "~> 1.2", [hex: :base62, repo: "hexpm", optional: false]}, {:ecto, ">= 2.0.0", [hex: :ecto, repo: "hexpm", optional: true]}], "hexpm", "31fc8090fde1acd267c07c36ea7365b8604055f897d3a53dd967658c691bd827"},
"floki": {:hex, :floki, "0.35.2", "87f8c75ed8654b9635b311774308b2760b47e9a579dabf2e4d5f1e1d42c39e0b", [:mix], [], "hexpm", "6b05289a8e9eac475f644f09c2e4ba7e19201fd002b89c28c1293e7bd16773d9"},
"gen_smtp": {:hex, :gen_smtp, "0.15.0", "9f51960c17769b26833b50df0b96123605a8024738b62db747fece14eb2fbfcc", [:rebar3], [], "hexpm", "29bd14a88030980849c7ed2447b8db6d6c9278a28b11a44cafe41b791205440f"},
@ -132,7 +133,8 @@
"telemetry_metrics": {:hex, :telemetry_metrics, "0.6.2", "2caabe9344ec17eafe5403304771c3539f3b6e2f7fb6a6f602558c825d0d0bfb", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9b43db0dc33863930b9ef9d27137e78974756f5f198cae18409970ed6fa5b561"},
"telemetry_metrics_prometheus_core": {:hex, :telemetry_metrics_prometheus_core, "1.2.0", "b583c3f18508f5c5561b674d16cf5d9afd2ea3c04505b7d92baaeac93c1b8260", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "9cba950e1c4733468efbe3f821841f34ac05d28e7af7798622f88ecdbbe63ea3"},
"telemetry_poller": {:hex, :telemetry_poller, "1.0.0", "db91bb424e07f2bb6e73926fcafbfcbcb295f0193e0a00e825e589a0a47e8453", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "b3a24eafd66c3f42da30fc3ca7dda1e9d546c12250a2d60d7b81d264fbec4f6e"},
"tesla": {:hex, :tesla, "1.4.4", "bb89aa0c9745190930366f6a2ac612cdf2d0e4d7fff449861baa7875afd797b2", [:mix], [{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: true]}, {:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:finch, "~> 0.3", [hex: :finch, repo: "hexpm", optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]}, {:gun, "~> 1.3", [hex: :gun, repo: "hexpm", optional: true]}, {:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "4.4.0", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "d5503a49f9dec1b287567ea8712d085947e247cb11b06bc54adb05bfde466457"},
"tesla": {:hex, :tesla, "1.8.0", "d511a4f5c5e42538d97eef7c40ec4f3e44effdc5068206f42ed859e09e51d1fd", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:finch, "~> 0.13", [hex: :finch, repo: "hexpm", optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]}, {:gun, ">= 1.0.0", [hex: :gun, repo: "hexpm", optional: true]}, {:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "4.4.2", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:msgpax, "~> 2.3", [hex: :msgpax, repo: "hexpm", optional: true]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "10501f360cd926a309501287470372af1a6e1cbed0f43949203a4c13300bc79f"},
"thousand_island": {:hex, :thousand_island, "1.3.2", "bc27f9afba6e1a676dd36507d42e429935a142cf5ee69b8e3f90bff1383943cd", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "0e085b93012cd1057b378fce40cbfbf381ff6d957a382bfdd5eca1a98eec2535"},
"timex": {:hex, :timex, "3.7.7", "3ed093cae596a410759104d878ad7b38e78b7c2151c6190340835515d4a46b8a", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.10", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 1.0", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "0ec4b09f25fe311321f9fc04144a7e3affe48eb29481d7a5583849b6c4dfa0a7"},
"toml": {:hex, :toml, "0.7.0", "fbcd773caa937d0c7a02c301a1feea25612720ac3fa1ccb8bfd9d30d822911de", [:mix], [], "hexpm", "0690246a2478c1defd100b0c9b89b4ea280a22be9a7b313a8a058a2408a2fa70"},
"trailing_format_plug": {:hex, :trailing_format_plug, "0.0.7", "64b877f912cf7273bed03379936df39894149e35137ac9509117e59866e10e45", [:mix], [{:plug, "> 0.12.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "bd4fde4c15f3e993a999e019d64347489b91b7a9096af68b2bdadd192afa693f"},

View File

@ -3,16 +3,16 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-09-18 09:07+0000\n"
"PO-Revision-Date: 2021-09-19 09:45+0000\n"
"Last-Translator: Ryo Ueno <r.ueno.nfive@gmail.com>\n"
"PO-Revision-Date: 2024-02-16 11:49+0000\n"
"Last-Translator: SyoBoN <syobon@syobon.net>\n"
"Language-Team: Japanese <https://translate.pleroma.social/projects/pleroma/"
"pleroma/ja/>\n"
"pleroma-backend-domain-errors/ja/>\n"
"Language: ja\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Weblate 4.6.2\n"
"X-Generator: Weblate 4.13.1\n"
## This file is a PO Template file.
##
@ -25,11 +25,11 @@ msgstr ""
## effect: edit them in PO (`.po`) files instead.
## From Ecto.Changeset.cast/4
msgid "can't be blank"
msgstr ""
msgstr "空にすることはできません"
## From Ecto.Changeset.unique_constraint/3
msgid "has already been taken"
msgstr ""
msgstr "すでに使用されています"
## From Ecto.Changeset.put_change/3
msgid "is invalid"
@ -37,7 +37,7 @@ msgstr ""
## From Ecto.Changeset.validate_format/3
msgid "has invalid format"
msgstr ""
msgstr "書式が正しくありません"
## From Ecto.Changeset.validate_subset/3
msgid "has an invalid entry"
@ -45,7 +45,7 @@ msgstr ""
## From Ecto.Changeset.validate_exclusion/3
msgid "is reserved"
msgstr ""
msgstr "予約されています"
## From Ecto.Changeset.validate_confirmation/3
msgid "does not match confirmation"
@ -61,23 +61,23 @@ msgstr ""
## From Ecto.Changeset.validate_length/3
msgid "should be %{count} character(s)"
msgid_plural "should be %{count} character(s)"
msgstr[0] ""
msgstr[0] "%{count}文字である必要があります"
msgid "should have %{count} item(s)"
msgid_plural "should have %{count} item(s)"
msgstr[0] ""
msgstr[0] "%{count}個の要素を含む必要があります"
msgid "should be at least %{count} character(s)"
msgid_plural "should be at least %{count} character(s)"
msgstr[0] ""
msgstr[0] "%{count}文字以上である必要があります"
msgid "should have at least %{count} item(s)"
msgid_plural "should have at least %{count} item(s)"
msgstr[0] ""
msgstr[0] "%{count}個以上の要素を含む必要があります"
msgid "should be at most %{count} character(s)"
msgid_plural "should be at most %{count} character(s)"
msgstr[0] ""
msgstr[0] "%{count}文字以下である必要があります"
msgid "should have at most %{count} item(s)"
msgid_plural "should have at most %{count} item(s)"
@ -102,7 +102,7 @@ msgstr "%{number}でなければなりません"
#: lib/pleroma/web/common_api/common_api.ex:505
#, elixir-format
msgid "Account not found"
msgstr "アカウントがりません"
msgstr "アカウントが見つかりません"
#: lib/pleroma/web/common_api/common_api.ex:339
#, elixir-format
@ -226,7 +226,7 @@ msgstr ""
#: lib/pleroma/web/common_api/utils.ex:414
#, elixir-format
msgid "Invalid password."
msgstr ""
msgstr "パスワードが間違っています。"
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:220
#, elixir-format
@ -236,7 +236,7 @@ msgstr ""
#: lib/pleroma/web/twitter_api/twitter_api.ex:109
#, elixir-format
msgid "Kocaptcha service unavailable"
msgstr ""
msgstr "Kocaptchaが利用できません"
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:112
#, elixir-format
@ -259,12 +259,12 @@ msgstr ""
#: lib/pleroma/web/feed/user_controller.ex:71 lib/pleroma/web/ostatus/ostatus_controller.ex:143
#, elixir-format
msgid "Not found"
msgstr ""
msgstr "見つかりません"
#: lib/pleroma/web/common_api/common_api.ex:331
#, elixir-format
msgid "Poll's author can't vote"
msgstr ""
msgstr "作成者は投票できません"
#: lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:20
#: lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:37 lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:49
@ -284,17 +284,17 @@ msgstr ""
#: lib/pleroma/web/common_api/activity_draft.ex:107
#, elixir-format
msgid "The message visibility must be direct"
msgstr ""
msgstr "公開範囲は「ダイレクト」でなければいけません"
#: lib/pleroma/web/common_api/utils.ex:573
#, elixir-format
msgid "The status is over the character limit"
msgstr ""
msgstr "文字数制限を超過しています"
#: lib/pleroma/plugs/ensure_public_or_authenticated_plug.ex:31
#, elixir-format
msgid "This resource requires authentication."
msgstr ""
msgstr "認証が必要です。"
#: lib/pleroma/plugs/rate_limiter/rate_limiter.ex:206
#, elixir-format
@ -304,7 +304,7 @@ msgstr ""
#: lib/pleroma/web/common_api/common_api.ex:356
#, elixir-format
msgid "Too many choices"
msgstr ""
msgstr "選択肢が多すぎます"
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:443
#, elixir-format
@ -320,7 +320,7 @@ msgstr ""
#: lib/pleroma/web/oauth/oauth_controller.ex:308
#, elixir-format
msgid "Your account is currently disabled"
msgstr ""
msgstr "あなたのアカウントは無効化されています"
#: lib/pleroma/web/oauth/oauth_controller.ex:183
#: lib/pleroma/web/oauth/oauth_controller.ex:331
@ -331,23 +331,23 @@ msgstr ""
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:390
#, elixir-format
msgid "can't read inbox of %{nickname} as %{as_nickname}"
msgstr ""
msgstr "%{nickname}のinboxを%{as_nickname}として閲覧することはできません"
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:473
#, elixir-format
msgid "can't update outbox of %{nickname} as %{as_nickname}"
msgstr ""
msgstr "%{nickname}のoutboxを%{as_nickname}として更新することはできません"
#: lib/pleroma/web/common_api/common_api.ex:471
#, elixir-format
msgid "conversation is already muted"
msgstr ""
msgstr "この会話はミュート済みです"
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:314
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:492
#, elixir-format
msgid "error"
msgstr ""
msgstr "エラー"
#: lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex:32
#, elixir-format
@ -357,7 +357,7 @@ msgstr ""
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:62
#, elixir-format
msgid "not found"
msgstr ""
msgstr "見つかりません"
#: lib/pleroma/web/oauth/oauth_controller.ex:394
#, elixir-format
@ -382,28 +382,28 @@ msgstr ""
#: lib/pleroma/web/oauth/oauth_controller.ex:410
#, elixir-format
msgid "Failed to authenticate: %{message}."
msgstr ""
msgstr "認証に失敗しました: %{message}。"
#: lib/pleroma/web/oauth/oauth_controller.ex:441
#, elixir-format
msgid "Failed to set up user account."
msgstr ""
msgstr "ユーザーアカウントの設定に失敗しました。"
#: lib/pleroma/plugs/oauth_scopes_plug.ex:38
#, elixir-format
msgid "Insufficient permissions: %{permissions}."
msgstr ""
msgstr "%{permissions}の権限が必要です。"
#: lib/pleroma/plugs/uploaded_media.ex:104
#, elixir-format
msgid "Internal Error"
msgstr ""
msgstr "内部エラー"
#: lib/pleroma/web/oauth/fallback_controller.ex:22
#: lib/pleroma/web/oauth/fallback_controller.ex:29
#, elixir-format
msgid "Invalid Username/Password"
msgstr ""
msgstr "ユーザー名/パスワードが間違っています"
#: lib/pleroma/web/twitter_api/twitter_api.ex:118
#, elixir-format
@ -423,7 +423,7 @@ msgstr ""
#: lib/pleroma/web/oauth/fallback_controller.ex:14
#, elixir-format
msgid "Unknown error, please check the details and try again."
msgstr ""
msgstr "不明なエラーです。詳細を確認し、再度試行してください。"
#: lib/pleroma/web/oauth/oauth_controller.ex:119
#: lib/pleroma/web/oauth/oauth_controller.ex:158
@ -449,17 +449,17 @@ msgstr ""
#: lib/pleroma/web/twitter_api/twitter_api.ex:103
#, elixir-format
msgid "CAPTCHA Error"
msgstr ""
msgstr "CAPTCHAエラー"
#: lib/pleroma/web/common_api/common_api.ex:290
#, elixir-format
msgid "Could not add reaction emoji"
msgstr ""
msgstr "リアクションを追加できません"
#: lib/pleroma/web/common_api/common_api.ex:301
#, elixir-format
msgid "Could not remove reaction emoji"
msgstr ""
msgstr "リアクションを解除できません"
#: lib/pleroma/web/twitter_api/twitter_api.ex:129
#, elixir-format
@ -469,7 +469,7 @@ msgstr ""
#: lib/pleroma/web/mastodon_api/controllers/list_controller.ex:92
#, elixir-format
msgid "List not found"
msgstr ""
msgstr "リストが見つかりません"
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:123
#, elixir-format
@ -480,7 +480,7 @@ msgstr ""
#: lib/pleroma/web/oauth/oauth_controller.ex:321
#, elixir-format
msgid "Password reset is required"
msgstr ""
msgstr "パスワードのリセットが必要です"
#: lib/pleroma/tests/auth_test_controller.ex:9
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:6 lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:6
@ -522,7 +522,7 @@ msgstr ""
#: lib/pleroma/plugs/ensure_authenticated_plug.ex:28
#, elixir-format
msgid "Two-factor authentication enabled, you must use a access token."
msgstr ""
msgstr "二段階認証が有効になっています。アクセストークンが必要です。"
#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:210
#, elixir-format
@ -552,7 +552,7 @@ msgstr ""
#: lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex:61
#, elixir-format
msgid "Web push subscription is disabled on this Pleroma instance"
msgstr ""
msgstr "このPleromaインスタンスではプッシュ通知が利用できません"
#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:451
#, elixir-format
@ -562,19 +562,19 @@ msgstr ""
#: lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:126
#, elixir-format
msgid "authorization required for timeline view"
msgstr ""
msgstr "タイムラインを閲覧するには認証が必要です"
#: lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:24
#, elixir-format
msgid "Access denied"
msgstr ""
msgstr "アクセスが拒否されました"
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:282
#, elixir-format
msgid "This API requires an authenticated user"
msgstr ""
msgstr "このAPIを利用するには認証が必要です"
#: lib/pleroma/plugs/user_is_admin_plug.ex:21
#, elixir-format
msgid "User is not an admin."
msgstr ""
msgstr "ユーザーは管理者ではありません。"

View File

@ -0,0 +1 @@
{"@context":"https://www.w3.org/ns/activitystreams","type":"Note","id":"https://cc.mkdir.uk/ap/note/e5d1d0a1-1ab3-4498-9949-588e3fdea286","attributedTo":"https://cc.mkdir.uk/ap/acct/hiira","inReplyTo":"","quoteUrl":"","content":"おはコンー","published":"2024-01-19T22:08:05Z","to":["https://www.w3.org/ns/activitystreams#Public"],"tag":null,"attachment":[],"object":null}

View File

@ -268,17 +268,6 @@ defmodule Pleroma.Integration.MastodonWebsocketTest do
end)
end
test "accepts valid token on Sec-WebSocket-Protocol header", %{token: token} do
assert {:ok, _} = start_socket("?stream=user", [{"Sec-WebSocket-Protocol", token.token}])
capture_log(fn ->
assert {:error, %WebSockex.RequestError{code: 401}} =
start_socket("?stream=user", [{"Sec-WebSocket-Protocol", "I am a friend"}])
Process.sleep(30)
end)
end
test "accepts valid token on client-sent event", %{token: token} do
assert {:ok, pid} = start_socket()

View File

@ -0,0 +1,22 @@
# Pleroma: A lightweight social networking server
# Copyright © 2024 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.MapsTest do
use Pleroma.DataCase, async: true
alias Pleroma.Maps
describe "filter_empty_values/1" do
assert %{"bar" => "b", "ray" => ["foo"], "objs" => %{"a" => "b"}} ==
Maps.filter_empty_values(%{
"foo" => nil,
"fooz" => "",
"bar" => "b",
"rei" => [],
"ray" => ["foo"],
"obj" => %{},
"objs" => %{"a" => "b"}
})
end
end

View File

@ -93,6 +93,17 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidatorTest
%{valid?: true} = ArticleNotePageValidator.cast_and_validate(note)
end
test "a Note from Convergence AP Bridge validates" do
insert(:user, ap_id: "https://cc.mkdir.uk/ap/acct/hiira")
note =
"test/fixtures/ccworld-ap-bridge_note.json"
|> File.read!()
|> Jason.decode!()
%{valid?: true} = ArticleNotePageValidator.cast_and_validate(note)
end
test "a note with an attachment should work", _ do
insert(:user, %{ap_id: "https://owncast.localhost.localdomain/federation/user/streamer"})