diff options
129 files changed, 3469 insertions, 622 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3ac30b13d..844f5888e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -134,6 +134,7 @@ unit-testing-rum: - mix test --preload-modules lint: + image: elixir:1.12 stage: test only: changes: @@ -243,7 +244,7 @@ stop_review_app: amd64: stage: release - image: elixir:1.10.3 + image: elixir:1.10.4 only: &release-only - stable@pleroma/pleroma - develop@pleroma/pleroma @@ -281,7 +282,7 @@ amd64-musl: stage: release artifacts: *release-artifacts only: *release-only - image: elixir:1.10.3-alpine + image: elixir:1.10.4-alpine cache: *release-cache variables: *release-variables before_script: &before-release-musl @@ -297,7 +298,7 @@ arm: only: *release-only tags: - arm32-specified - image: arm32v7/elixir:1.10.3 + image: arm32v7/elixir:1.10.4 cache: *release-cache variables: *release-variables before_script: *before-release @@ -309,7 +310,7 @@ arm-musl: only: *release-only tags: - arm32-specified - image: arm32v7/elixir:1.10.3-alpine + image: arm32v7/elixir:1.10.4-alpine cache: *release-cache variables: *release-variables before_script: *before-release-musl @@ -321,7 +322,7 @@ arm64: only: *release-only tags: - arm - image: arm64v8/elixir:1.10.3 + image: arm64v8/elixir:1.10.4 cache: *release-cache variables: *release-variables before_script: *before-release @@ -333,7 +334,7 @@ arm64-musl: only: *release-only tags: - arm - image: arm64v8/elixir:1.10.3-alpine + image: arm64v8/elixir:1.10.4-alpine cache: *release-cache variables: *release-variables before_script: *before-release-musl @@ -351,8 +352,8 @@ docker: IMAGE_TAG_SLUG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG IMAGE_TAG_LATEST: $CI_REGISTRY_IMAGE:latest IMAGE_TAG_LATEST_STABLE: $CI_REGISTRY_IMAGE:latest-stable - DOCKER_BUILDX_URL: https://github.com/docker/buildx/releases/download/v0.4.1/buildx-v0.4.1.linux-amd64 - DOCKER_BUILDX_HASH: 71a7d01439aa8c165a25b59c44d3f016fddbd98b + DOCKER_BUILDX_URL: https://github.com/docker/buildx/releases/download/v0.6.3/buildx-v0.6.3.linux-amd64 + DOCKER_BUILDX_HASH: 980e6b9655f971991fbbb5fd6cd19f1672386195 before_script: &before-docker - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY - docker pull $IMAGE_TAG_SLUG || true diff --git a/CHANGELOG.md b/CHANGELOG.md index 4758acc57..ecefba381 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,8 +11,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - MastoFE ### Changed +- Allow users to remove their emails if instance does not need email to register ### Added +- `activeMonth` and `activeHalfyear` fields in NodeInfo usage.users object ### Fixed - Subscription(Bell) Notifications: Don't create from Pipeline Ingested replies @@ -58,6 +60,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - MRF (`FollowBotPolicy`): New MRF Policy which makes a designated local Bot account attempt to follow all users in public Notes received by your instance. Users who require approving follower requests or have #nobot in their profile are excluded. - Return OAuth token `id` (primary key) in POST `/oauth/token`. - AdminAPI: return `created_at` date with users. +- AdminAPI: add DELETE `/api/v1/pleroma/admin/instances/:instance` to delete all content from a remote instance. - `AnalyzeMetadata` upload filter for extracting image/video attachment dimensions and generating blurhashes for images. Blurhashes for videos are not generated at this time. - Attachment dimensions and blurhashes are federated when available. - Mastodon API: support `poll` notification. @@ -68,6 +71,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Checking activated Upload Filters for required commands. - Remote users can no longer reappear after being deleted. - Deactivated users may now be deleted. +- Deleting an activity with a lot of likes/boosts no longer causes a database timeout. - Mix task `pleroma.database prune_objects` - Fixed rendering of JSON errors on ActivityPub endpoints. - Linkify: Parsing crash with URLs ending in unbalanced closed paren, no path separator, and no query parameters @@ -132,6 +136,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Support pagination of blocks and mutes. - Account backup. - Configuration: Add `:instance, autofollowing_nicknames` setting to provide a way to make accounts automatically follow new users that register on the local Pleroma instance. +- `[:activitypub, :blockers_visible]` config to control visibility of blockers. - Ability to view remote timelines, with ex. `/api/v1/timelines/public?instance=lain.com` and streams `public:remote` and `public:remote:media`. - The site title is now injected as a `title` tag like preloads or metadata. - Password reset tokens now are not accepted after a certain age. diff --git a/Dockerfile b/Dockerfile index db1a6b457..c51ebbab0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,7 +12,7 @@ RUN apk add git gcc g++ musl-dev make cmake file-dev &&\ mkdir release &&\ mix release --path release -FROM alpine:3.11 +FROM alpine:3.14 ARG BUILD_DATE ARG VCS_REF @@ -31,8 +31,7 @@ LABEL maintainer="ops@pleroma.social" \ ARG HOME=/opt/pleroma ARG DATA=/var/lib/pleroma -RUN echo "http://nl.alpinelinux.org/alpine/latest-stable/community" >> /etc/apk/repositories &&\ - apk update &&\ +RUN apk update &&\ apk add exiftool ffmpeg imagemagick libmagic ncurses postgresql-client &&\ adduser --system --shell /bin/false --home ${HOME} pleroma &&\ mkdir -p ${DATA}/uploads &&\ diff --git a/benchmarks/load_testing/activities.ex b/benchmarks/load_testing/activities.ex index b9f6b24da..7f262d228 100644 --- a/benchmarks/load_testing/activities.ex +++ b/benchmarks/load_testing/activities.ex @@ -394,7 +394,7 @@ defmodule Pleroma.LoadTesting.Activities do defp other_data(actor, content) do %{host: host} = URI.parse(actor.ap_id) - datetime = DateTime.utc_now() + datetime = DateTime.utc_now() |> to_string() context_id = "https://#{host}/contexts/#{UUID.generate()}" activity_id = "https://#{host}/activities/#{UUID.generate()}" object_id = "https://#{host}/objects/#{UUID.generate()}" diff --git a/benchmarks/mix/tasks/pleroma/benchmarks/tags.ex b/benchmarks/mix/tasks/pleroma/benchmarks/tags.ex index c051335a5..a32de2db4 100644 --- a/benchmarks/mix/tasks/pleroma/benchmarks/tags.ex +++ b/benchmarks/mix/tasks/pleroma/benchmarks/tags.ex @@ -99,15 +99,16 @@ defmodule Mix.Tasks.Pleroma.Benchmarks.Tags do |> Enum.map(&String.downcase(&1)) _activities = - params - |> Map.put(:type, "Create") - |> Map.put(:local_only, local_only) - |> Map.put(:blocking_user, user) - |> Map.put(:muting_user, user) - |> Map.put(:user, user) - |> Map.put(:tag, tags) - |> Map.put(:tag_all, tag_all) - |> Map.put(:tag_reject, tag_reject) + %{ + type: "Create", + local_only: local_only, + blocking_user: user, + muting_user: user, + user: user, + tag: tags, + tag_all: tag_all, + tag_reject: tag_reject, + } |> Pleroma.Web.ActivityPub.ActivityPub.fetch_public_activities() end end diff --git a/benchmarks/mix/tasks/pleroma/benchmarks/timelines.ex b/benchmarks/mix/tasks/pleroma/benchmarks/timelines.ex index aed32f194..3770ca163 100644 --- a/benchmarks/mix/tasks/pleroma/benchmarks/timelines.ex +++ b/benchmarks/mix/tasks/pleroma/benchmarks/timelines.ex @@ -17,14 +17,14 @@ defmodule Mix.Tasks.Pleroma.Benchmarks.Timelines do # Let the user make 100 posts 1..100 - |> Enum.each(fn i -> CommonAPI.post(user, %{"status" => to_string(i)}) end) + |> Enum.each(fn i -> CommonAPI.post(user, %{status: to_string(i)}) end) # Let 10 random users post posts = users |> Enum.take_random(10) |> Enum.map(fn {:ok, random_user} -> - {:ok, activity} = CommonAPI.post(random_user, %{"status" => "."}) + {:ok, activity} = CommonAPI.post(random_user, %{status: "."}) activity end) @@ -42,7 +42,7 @@ defmodule Mix.Tasks.Pleroma.Benchmarks.Timelines do |> Conn.assign(:user, reading_user) |> Conn.assign(:skip_link_headers, true) - Pleroma.Web.MastodonAPI.AccountController.statuses(conn, %{"id" => user.id}) + Pleroma.Web.MastodonAPI.AccountController.statuses(conn, %{id: user.id}) end }, inputs: %{"user" => user, "no user" => nil}, @@ -50,7 +50,7 @@ defmodule Mix.Tasks.Pleroma.Benchmarks.Timelines do ) users - |> Enum.each(fn {:ok, follower, user} -> Pleroma.User.follow(follower, user) end) + |> Enum.each(fn {:ok, follower} -> Pleroma.User.follow(follower, user) end) Benchee.run( %{ @@ -60,7 +60,7 @@ defmodule Mix.Tasks.Pleroma.Benchmarks.Timelines do |> Conn.assign(:user, reading_user) |> Conn.assign(:skip_link_headers, true) - Pleroma.Web.MastodonAPI.AccountController.statuses(conn, %{"id" => user.id}) + Pleroma.Web.MastodonAPI.AccountController.statuses(conn, %{id: user.id}) end }, inputs: %{"user" => user, "no user" => nil}, diff --git a/config/benchmark.exs b/config/benchmark.exs index a4d048f1b..9a7ea5669 100644 --- a/config/benchmark.exs +++ b/config/benchmark.exs @@ -4,8 +4,7 @@ import Config # you can enable the server option below. config :pleroma, Pleroma.Web.Endpoint, http: [port: 4001], - url: [port: 4001], - server: true + url: [port: 4001] # Disable captha for tests config :pleroma, Pleroma.Captcha, @@ -44,7 +43,7 @@ config :pleroma, Pleroma.Repo, pool_size: 10 # Reduce hash rounds for testing -config :pbkdf2_elixir, rounds: 1 +config :pleroma, :password, iterations: 1 config :tesla, adapter: Tesla.Mock diff --git a/config/config.exs b/config/config.exs index 66d394655..c9592511f 100644 --- a/config/config.exs +++ b/config/config.exs @@ -139,6 +139,7 @@ config :pleroma, Pleroma.Web.Endpoint, ], protocol: "https", secret_key_base: "aK4Abxf29xU9TTDKre9coZPUgevcVCFQJe/5xP/7Lt4BEif6idBIbjupVbOrbKxl", + live_view: [signing_salt: "U5ELgdEwTD3n1+D5s0rY0AMg8/y1STxZ3Zvsl3bWh+oBcGrYdil0rXqPMRd3Glcq"], signing_salt: "CqaoopA2", render_errors: [view: Pleroma.Web.ErrorView, accepts: ~w(json)], pubsub_server: Pleroma.PubSub, @@ -349,6 +350,7 @@ config :pleroma, :manifest, config :pleroma, :activitypub, unfollow_blocked: true, outgoing_blocks: true, + blockers_visible: true, follow_handshake_timeout: 500, note_replies_output_limit: 5, sign_object_fetches: true, diff --git a/config/description.exs b/config/description.exs index 7d1b29b23..1c8c3b4a0 100644 --- a/config/description.exs +++ b/config/description.exs @@ -1671,6 +1671,11 @@ config :pleroma, :config_description, [ description: "Whether to federate blocks to other instances" }, %{ + key: :blockers_visible, + type: :boolean, + description: "Whether a user can see someone who has blocked them" + }, + %{ key: :sign_object_fetches, type: :boolean, description: "Sign object fetches with HTTP signatures" diff --git a/docs/configuration/cheatsheet.md b/docs/configuration/cheatsheet.md index 251dc24e8..40e81cffb 100644 --- a/docs/configuration/cheatsheet.md +++ b/docs/configuration/cheatsheet.md @@ -230,6 +230,7 @@ Notes: ### :activitypub * `unfollow_blocked`: Whether blocks result in people getting unfollowed * `outgoing_blocks`: Whether to federate blocks to other instances +* `blockers_visible`: Whether a user can see the posts of users who blocked them * `deny_follow_blocked`: Whether to disallow following an account that has blocked the user in question * `sign_object_fetches`: Sign object fetches with HTTP signatures * `authorized_fetch_mode`: Require HTTP signatures for AP fetches diff --git a/docs/development/API/admin_api.md b/docs/development/API/admin_api.md index 8f855d251..f14081893 100644 --- a/docs/development/API/admin_api.md +++ b/docs/development/API/admin_api.md @@ -261,6 +261,46 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret } ``` +## `PATCH /api/v1/pleroma/admin/users/suggest` + +### Suggest a user + +Adds the user(s) to follower recommendations. + +- Params: + - `nicknames`: nicknames array +- Response: + +```json +{ + users: [ + { + // user object + } + ] +} +``` + +## `PATCH /api/v1/pleroma/admin/users/unsuggest` + +### Unsuggest a user + +Removes the user(s) from follower recommendations. + +- Params: + - `nicknames`: nicknames array +- Response: + +```json +{ + users: [ + { + // user object + } + ] +} +``` + ## `GET /api/v1/pleroma/admin/users/:nickname_or_id` ### Retrive the details of a user @@ -319,6 +359,22 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret } ``` +## `DELETE /api/v1/pleroma/admin/instances/:instance` + +### Delete all users and activities from a remote instance + +Note: this will trigger a job to remove instance content in the background. +It may take some time. + +- Params: + - `instance`: remote instance host +- Response: + - The `instance` name as a string + +```json +"lain.com" +``` + ## `GET /api/v1/pleroma/admin/statuses` ### Retrives all latest statuses diff --git a/docs/installation/generic_dependencies.include b/docs/installation/generic_dependencies.include index baed19de0..2dbd93e42 100644 --- a/docs/installation/generic_dependencies.include +++ b/docs/installation/generic_dependencies.include @@ -9,7 +9,7 @@ * GNU make * CMake -## Optionnal dependencies +## Optional dependencies * ImageMagick * FFmpeg diff --git a/lib/mix/tasks/pleroma/config.ex b/lib/mix/tasks/pleroma/config.ex index 22502a522..05ff8076f 100644 --- a/lib/mix/tasks/pleroma/config.ex +++ b/lib/mix/tasks/pleroma/config.ex @@ -286,9 +286,7 @@ defmodule Mix.Tasks.Pleroma.Config do file = File.open!(tmp_config_path) shell_info( - "Saving database configuration settings to #{tmp_config_path}. Copy it to the #{ - Path.dirname(config_path) - } manually." + "Saving database configuration settings to #{tmp_config_path}. Copy it to the #{Path.dirname(config_path)} manually." ) write_config(file, tmp_config_path, opts) diff --git a/lib/mix/tasks/pleroma/instance.ex b/lib/mix/tasks/pleroma/instance.ex index da27a99d0..d98cb8e37 100644 --- a/lib/mix/tasks/pleroma/instance.ex +++ b/lib/mix/tasks/pleroma/instance.ex @@ -199,6 +199,7 @@ defmodule Mix.Tasks.Pleroma.Instance do secret = :crypto.strong_rand_bytes(64) |> Base.encode64() |> binary_part(0, 64) jwt_secret = :crypto.strong_rand_bytes(64) |> Base.encode64() |> binary_part(0, 64) signing_salt = :crypto.strong_rand_bytes(8) |> Base.encode64() |> binary_part(0, 8) + lv_signing_salt = :crypto.strong_rand_bytes(8) |> Base.encode64() |> binary_part(0, 8) {web_push_public_key, web_push_private_key} = :crypto.generate_key(:ecdh, :prime256v1) template_dir = Application.app_dir(:pleroma, "priv") <> "/templates" @@ -217,6 +218,7 @@ defmodule Mix.Tasks.Pleroma.Instance do secret: secret, jwt_secret: jwt_secret, signing_salt: signing_salt, + lv_signing_salt: lv_signing_salt, web_push_public_key: Base.url_encode64(web_push_public_key, padding: false), web_push_private_key: Base.url_encode64(web_push_private_key, padding: false), db_configurable?: db_configurable?, diff --git a/lib/mix/tasks/pleroma/user.ex b/lib/mix/tasks/pleroma/user.ex index 53d5fc6d9..e848222b8 100644 --- a/lib/mix/tasks/pleroma/user.ex +++ b/lib/mix/tasks/pleroma/user.ex @@ -51,9 +51,7 @@ defmodule Mix.Tasks.Pleroma.User do A user will be created with the following information: - nickname: #{nickname} - email: #{email} - - password: #{ - if(generated_password?, do: "[generated; a reset link will be created]", else: password) - } + - password: #{if(generated_password?, do: "[generated; a reset link will be created]", else: password)} - name: #{name} - bio: #{bio} - moderator: #{if(moderator?, do: "true", else: "false")} @@ -114,15 +112,9 @@ defmodule Mix.Tasks.Pleroma.User do {:ok, token} <- Pleroma.PasswordResetToken.create_token(user) do shell_info("Generated password reset token for #{user.nickname}") - IO.puts( - "URL: #{ - Pleroma.Web.Router.Helpers.reset_password_url( - Pleroma.Web.Endpoint, - :reset, - token.token - ) - }" - ) + IO.puts("URL: #{Pleroma.Web.Router.Helpers.reset_password_url(Pleroma.Web.Endpoint, + :reset, + token.token)}") else _ -> shell_error("No local user #{nickname}") @@ -321,9 +313,7 @@ defmodule Mix.Tasks.Pleroma.User do end shell_info( - "ID: #{invite.id} | Token: #{invite.token} | Token type: #{invite.invite_type} | Used: #{ - invite.used - }#{expire_info}#{using_info}" + "ID: #{invite.id} | Token: #{invite.token} | Token type: #{invite.invite_type} | Used: #{invite.used}#{expire_info}#{using_info}" ) end) end @@ -424,9 +414,7 @@ defmodule Mix.Tasks.Pleroma.User do users |> Enum.each(fn user -> shell_info( - "#{user.nickname} moderator: #{user.is_moderator}, admin: #{user.is_admin}, locked: #{ - user.is_locked - }, is_active: #{user.is_active}" + "#{user.nickname} moderator: #{user.is_moderator}, admin: #{user.is_admin}, locked: #{user.is_locked}, is_active: #{user.is_active}" ) end) end) diff --git a/lib/pleroma/activity.ex b/lib/pleroma/activity.ex index 6a991c48e..4106feef6 100644 --- a/lib/pleroma/activity.ex +++ b/lib/pleroma/activity.ex @@ -302,7 +302,7 @@ defmodule Pleroma.Activity do |> Queries.by_object_id() |> Queries.exclude_type("Delete") |> select([u], u) - |> Repo.delete_all() + |> Repo.delete_all(timeout: :infinity) |> elem(1) |> Enum.find(fn %{data: %{"type" => "Create", "object" => ap_id}} when is_binary(ap_id) -> ap_id == id @@ -362,11 +362,9 @@ defmodule Pleroma.Activity do end def restrict_deactivated_users(query) do - deactivated_users = - from(u in User.Query.build(%{deactivated: true}), select: u.ap_id) - |> Repo.all() + deactivated_users_query = from(u in User.Query.build(%{deactivated: true}), select: u.ap_id) - Activity.Queries.exclude_authors(query, deactivated_users) + from(activity in query, where: activity.actor not in subquery(deactivated_users_query)) end defdelegate search(user, query, options \\ []), to: Pleroma.Activity.Search diff --git a/lib/pleroma/bbs/handler.ex b/lib/pleroma/bbs/handler.ex index 4a2e255f7..a38faa5b8 100644 --- a/lib/pleroma/bbs/handler.ex +++ b/lib/pleroma/bbs/handler.ex @@ -19,9 +19,7 @@ defmodule Pleroma.BBS.Handler do def on_connect(username, ip, port, method) do Logger.debug(fn -> """ - Incoming SSH shell #{inspect(self())} requested for #{username} from #{inspect(ip)}:#{ - inspect(port) - } using #{inspect(method)} + Incoming SSH shell #{inspect(self())} requested for #{username} from #{inspect(ip)}:#{inspect(port)} using #{inspect(method)} """ end) end diff --git a/lib/pleroma/config/oban.ex b/lib/pleroma/config/oban.ex index 3e63bca40..53ea7d7be 100644 --- a/lib/pleroma/config/oban.ex +++ b/lib/pleroma/config/oban.ex @@ -21,9 +21,7 @@ defmodule Pleroma.Config.Oban do """ !!!OBAN CONFIG WARNING!!! You are using old workers in Oban crontab settings, which were removed. - Please, remove setting from crontab in your config file (prod.secret.exs): #{ - inspect(setting) - } + Please, remove setting from crontab in your config file (prod.secret.exs): #{inspect(setting)} """ |> Logger.warn() diff --git a/lib/pleroma/config/transfer_task.ex b/lib/pleroma/config/transfer_task.ex index d5c6081a2..5371aae7a 100644 --- a/lib/pleroma/config/transfer_task.ex +++ b/lib/pleroma/config/transfer_task.ex @@ -148,9 +148,7 @@ defmodule Pleroma.Config.TransferTask do rescue error -> error_msg = - "updating env causes error, group: #{inspect(group)}, key: #{inspect(key)}, value: #{ - inspect(value) - } error: #{inspect(error)}" + "updating env causes error, group: #{inspect(group)}, key: #{inspect(key)}, value: #{inspect(value)} error: #{inspect(error)}" Logger.warn(error_msg) diff --git a/lib/pleroma/ecto_enums.ex b/lib/pleroma/ecto_enums.ex index 2a9addabc..0e3e1e5de 100644 --- a/lib/pleroma/ecto_enums.ex +++ b/lib/pleroma/ecto_enums.ex @@ -9,7 +9,8 @@ defenum(Pleroma.UserRelationship.Type, mute: 2, reblog_mute: 3, notification_mute: 4, - inverse_subscription: 5 + inverse_subscription: 5, + suggestion_dismiss: 6 ) defenum(Pleroma.FollowingRelationship.State, diff --git a/lib/pleroma/emoji/loader.ex b/lib/pleroma/emoji/loader.ex index 67acd7069..abc95d902 100644 --- a/lib/pleroma/emoji/loader.ex +++ b/lib/pleroma/emoji/loader.ex @@ -60,9 +60,7 @@ defmodule Pleroma.Emoji.Loader do if not Enum.empty?(files) do Logger.warn( - "Found files in the emoji folder. These will be ignored, please move them to a subdirectory\nFound files: #{ - Enum.join(files, ", ") - }" + "Found files in the emoji folder. These will be ignored, please move them to a subdirectory\nFound files: #{Enum.join(files, ", ")}" ) end @@ -105,6 +103,7 @@ defmodule Pleroma.Emoji.Loader do pack_file = Path.join(pack_dir, "pack.json") if File.exists?(pack_file) do + Logger.info("Loading emoji pack from JSON: #{pack_file}") contents = Jason.decode!(File.read!(pack_file)) contents["files"] @@ -117,14 +116,13 @@ defmodule Pleroma.Emoji.Loader do emoji_txt = Path.join(pack_dir, "emoji.txt") if File.exists?(emoji_txt) do + Logger.info("Loading emoji pack from emoji.txt: #{emoji_txt}") load_from_file(emoji_txt, emoji_groups) else extensions = Config.get([:emoji, :pack_extensions]) Logger.info( - "No emoji.txt found for pack \"#{pack_name}\", assuming all #{ - Enum.join(extensions, ", ") - } files are emoji" + "No emoji.txt found for pack \"#{pack_name}\", assuming all #{Enum.join(extensions, ", ")} files are emoji" ) make_shortcode_to_file_map(pack_dir, extensions) diff --git a/lib/pleroma/gun/conn.ex b/lib/pleroma/gun/conn.ex index a56625699..a1210eabf 100644 --- a/lib/pleroma/gun/conn.ex +++ b/lib/pleroma/gun/conn.ex @@ -57,9 +57,7 @@ defmodule Pleroma.Gun.Conn do else error -> Logger.warn( - "Opening proxied connection to #{compose_uri_log(uri)} failed with error #{ - inspect(error) - }" + "Opening proxied connection to #{compose_uri_log(uri)} failed with error #{inspect(error)}" ) error @@ -93,9 +91,7 @@ defmodule Pleroma.Gun.Conn do else error -> Logger.warn( - "Opening socks proxied connection to #{compose_uri_log(uri)} failed with error #{ - inspect(error) - }" + "Opening socks proxied connection to #{compose_uri_log(uri)} failed with error #{inspect(error)}" ) error diff --git a/lib/pleroma/instances/instance.ex b/lib/pleroma/instances/instance.ex index 4d0e8034d..2f338b3e2 100644 --- a/lib/pleroma/instances/instance.ex +++ b/lib/pleroma/instances/instance.ex @@ -8,6 +8,8 @@ defmodule Pleroma.Instances.Instance do alias Pleroma.Instances alias Pleroma.Instances.Instance alias Pleroma.Repo + alias Pleroma.User + alias Pleroma.Workers.BackgroundWorker use Ecto.Schema @@ -195,4 +197,24 @@ defmodule Pleroma.Instances.Instance do nil end end + + @doc """ + Deletes all users from an instance in a background task, thus also deleting + all of those users' activities and notifications. + """ + def delete_users_and_activities(host) when is_binary(host) do + BackgroundWorker.enqueue("delete_instance", %{"host" => host}) + end + + def perform(:delete_instance, host) when is_binary(host) do + User.Query.build(%{nickname: "@#{host}"}) + |> Repo.chunk_stream(100, :batches) + |> Stream.each(fn users -> + users + |> Enum.each(fn user -> + User.perform(:delete, user) + end) + end) + |> Stream.run() + end end diff --git a/lib/pleroma/maintenance.ex b/lib/pleroma/maintenance.ex index f1058b68a..41c799712 100644 --- a/lib/pleroma/maintenance.ex +++ b/lib/pleroma/maintenance.ex @@ -9,7 +9,7 @@ defmodule Pleroma.Maintenance do def vacuum(args) do case args do "analyze" -> - Logger.info("Runnning VACUUM ANALYZE.") + Logger.info("Running VACUUM ANALYZE.") Repo.query!( "vacuum analyze;", @@ -18,7 +18,7 @@ defmodule Pleroma.Maintenance do ) "full" -> - Logger.info("Runnning VACUUM FULL.") + Logger.info("Running VACUUM FULL.") Logger.warn( "Re-packing your entire database may take a while and will consume extra disk space during the process." diff --git a/lib/pleroma/moderation_log.ex b/lib/pleroma/moderation_log.ex index 1849cacc8..adb51d33a 100644 --- a/lib/pleroma/moderation_log.ex +++ b/lib/pleroma/moderation_log.ex @@ -341,6 +341,26 @@ defmodule Pleroma.ModerationLog do def get_log_entry_message(%ModerationLog{ data: %{ "actor" => %{"nickname" => actor_nickname}, + "action" => "add_suggestion", + "subject" => users + } + }) do + "@#{actor_nickname} added suggested users: #{users_to_nicknames_string(users)}" + end + + def get_log_entry_message(%ModerationLog{ + data: %{ + "actor" => %{"nickname" => actor_nickname}, + "action" => "remove_suggestion", + "subject" => users + } + }) do + "@#{actor_nickname} removed suggested users: #{users_to_nicknames_string(users)}" + end + + def get_log_entry_message(%ModerationLog{ + data: %{ + "actor" => %{"nickname" => actor_nickname}, "nicknames" => nicknames, "tags" => tags, "action" => "tag" @@ -481,9 +501,7 @@ defmodule Pleroma.ModerationLog do "visibility" => visibility } }) do - "@#{actor_nickname} updated status ##{subject_id}, set sensitive: '#{sensitive}', visibility: '#{ - visibility - }'" + "@#{actor_nickname} updated status ##{subject_id}, set sensitive: '#{sensitive}', visibility: '#{visibility}'" end def get_log_entry_message(%ModerationLog{ @@ -523,9 +541,7 @@ defmodule Pleroma.ModerationLog do "subject" => subjects } }) do - "@#{actor_nickname} re-sent confirmation email for users: #{ - users_to_nicknames_string(subjects) - }" + "@#{actor_nickname} re-sent confirmation email for users: #{users_to_nicknames_string(subjects)}" end def get_log_entry_message(%ModerationLog{ diff --git a/lib/pleroma/notification.ex b/lib/pleroma/notification.ex index 32f13df69..9e0ce0329 100644 --- a/lib/pleroma/notification.ex +++ b/lib/pleroma/notification.ex @@ -128,6 +128,7 @@ defmodule Pleroma.Notification do |> where([user_actor: user_actor], user_actor.is_active) |> exclude_notification_muted(user, exclude_notification_muted_opts) |> exclude_blocked(user, exclude_blocked_opts) + |> exclude_blockers(user) |> exclude_filtered(user) |> exclude_visibility(opts) end @@ -141,6 +142,17 @@ defmodule Pleroma.Notification do |> FollowingRelationship.keep_following_or_not_domain_blocked(user) end + defp exclude_blockers(query, user) do + if Pleroma.Config.get([:activitypub, :blockers_visible]) == true do + query + else + blocker_ap_ids = User.incoming_relationships_ungrouped_ap_ids(user, [:block]) + + query + |> where([n, a], a.actor not in ^blocker_ap_ids) + end + end + defp exclude_notification_muted(query, _, %{@include_muted_option => true}) do query end diff --git a/lib/pleroma/telemetry/logger.ex b/lib/pleroma/telemetry/logger.ex index 44d2f48dc..10165c1b2 100644 --- a/lib/pleroma/telemetry/logger.ex +++ b/lib/pleroma/telemetry/logger.ex @@ -29,9 +29,7 @@ defmodule Pleroma.Telemetry.Logger do _ ) do Logger.debug(fn -> - "Connection pool is exhausted (reached #{max_connections} connections). Starting idle connection cleanup to reclaim as much as #{ - reclaim_max - } connections" + "Connection pool is exhausted (reached #{max_connections} connections). Starting idle connection cleanup to reclaim as much as #{reclaim_max} connections" end) end @@ -73,9 +71,7 @@ defmodule Pleroma.Telemetry.Logger do _ ) do Logger.warn(fn -> - "Pool worker for #{key}: Client #{inspect(client_pid)} died before releasing the connection with #{ - inspect(reason) - }" + "Pool worker for #{key}: Client #{inspect(client_pid)} died before releasing the connection with #{inspect(reason)}" end) end diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 455e08c88..c25023dc1 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -148,6 +148,7 @@ defmodule Pleroma.User do field(:last_active_at, :naive_datetime) field(:disclose_client, :boolean, default: true) field(:pinned_objects, :map, default: %{}) + field(:is_suggested, :boolean, default: false) embeds_one( :notification_settings, @@ -1676,6 +1677,22 @@ defmodule Pleroma.User do def confirm(%User{} = user), do: {:ok, user} + def set_suggestion(users, is_suggested) when is_list(users) do + Repo.transaction(fn -> + Enum.map(users, fn user -> + with {:ok, user} <- set_suggestion(user, is_suggested), do: user + end) + end) + end + + def set_suggestion(%User{is_suggested: is_suggested} = user, is_suggested), do: {:ok, user} + + def set_suggestion(%User{} = user, is_suggested) when is_boolean(is_suggested) do + user + |> change(is_suggested: is_suggested) + |> update_and_set_cache() + end + def update_notification_settings(%User{} = user, settings) do user |> cast(%{notification_settings: settings}, []) @@ -2246,7 +2263,7 @@ defmodule Pleroma.User do def change_email(user, email) do user |> cast(%{email: email}, [:email]) - |> validate_required([:email]) + |> maybe_validate_required_email(false) |> unique_constraint(:email) |> validate_format(:email, @email_regex) |> update_and_set_cache() @@ -2474,8 +2491,8 @@ defmodule Pleroma.User do |> update_and_set_cache() end - def active_user_count(weeks \\ 4) do - active_after = Timex.shift(NaiveDateTime.utc_now(), weeks: -weeks) + def active_user_count(days \\ 30) do + active_after = Timex.shift(NaiveDateTime.utc_now(), days: -days) __MODULE__ |> where([u], u.last_active_at >= ^active_after) diff --git a/lib/pleroma/user/query.ex b/lib/pleroma/user/query.ex index ac807fc79..6d4a4ead6 100644 --- a/lib/pleroma/user/query.ex +++ b/lib/pleroma/user/query.ex @@ -46,6 +46,7 @@ defmodule Pleroma.User.Query do unconfirmed: boolean(), is_admin: boolean(), is_moderator: boolean(), + is_suggested: boolean(), super_users: boolean(), invisible: boolean(), internal: boolean(), @@ -167,6 +168,10 @@ defmodule Pleroma.User.Query do where(query, [u], u.is_confirmed == false) end + defp compose_query({:is_suggested, bool}, query) do + where(query, [u], u.is_suggested == ^bool) + end + defp compose_query({:followers, %User{id: id}}, query) do query |> where([u], u.id != ^id) diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 19961a4a5..8324ca22c 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -441,6 +441,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do |> maybe_preload_bookmarks(opts) |> maybe_set_thread_muted_field(opts) |> restrict_blocked(opts) + |> restrict_blockers_visibility(opts) |> restrict_recipients(recipients, opts[:user]) |> restrict_filtered(opts) |> where( @@ -1028,7 +1029,10 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do from( [activity, object: o] in query, + # You don't block the author where: fragment("not (? = ANY(?))", activity.actor, ^blocked_ap_ids), + + # You don't block any recipients, and didn't author the post where: fragment( "((not (? && ?)) or ? = ?)", @@ -1037,12 +1041,18 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do activity.actor, ^user.ap_id ), + + # You don't block the domain of any recipients, and didn't author the post where: fragment( - "recipients_contain_blocked_domains(?, ?) = false", + "(recipients_contain_blocked_domains(?, ?) = false) or ? = ?", activity.recipients, - ^domain_blocks + ^domain_blocks, + activity.actor, + ^user.ap_id ), + + # It's not a boost of a user you block where: fragment( "not (?->>'type' = 'Announce' and ?->'to' \\?| ?)", @@ -1050,6 +1060,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do activity.data, ^blocked_ap_ids ), + + # You don't block the author's domain, and also don't follow the author where: fragment( "(not (split_part(?, '/', 3) = ANY(?))) or ? = ANY(?)", @@ -1058,6 +1070,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do activity.actor, ^following_ap_ids ), + + # Same as above, but checks the Object where: fragment( "(not (split_part(?->>'actor', '/', 3) = ANY(?))) or (?->>'actor') = ANY(?)", @@ -1071,6 +1085,31 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do defp restrict_blocked(query, _), do: query + defp restrict_blockers_visibility(query, %{blocking_user: %User{} = user}) do + if Config.get([:activitypub, :blockers_visible]) == true do + query + else + blocker_ap_ids = User.incoming_relationships_ungrouped_ap_ids(user, [:block]) + + from( + activity in query, + # The author doesn't block you + where: fragment("not (? = ANY(?))", activity.actor, ^blocker_ap_ids), + + # It's not a boost of a user that blocks you + where: + fragment( + "not (?->>'type' = 'Announce' and ?->'to' \\?| ?)", + activity.data, + activity.data, + ^blocker_ap_ids + ) + ) + end + end + + defp restrict_blockers_visibility(query, _), do: query + defp restrict_unlisted(query, %{restrict_unlisted: true}) do from( activity in query, @@ -1297,6 +1336,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do |> restrict_state(opts) |> restrict_favorited_by(opts) |> restrict_blocked(restrict_blocked_opts) + |> restrict_blockers_visibility(opts) |> restrict_muted(restrict_muted_opts) |> restrict_filtered(opts) |> restrict_media(opts) @@ -1597,9 +1637,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do %User{} = old_user <- User.get_by_nickname(nickname), {_, false} <- {:ap_id_comparison, data[:ap_id] == old_user.ap_id} do Logger.info( - "Found an old user for #{nickname}, the old ap id is #{old_user.ap_id}, new one is #{ - data[:ap_id] - }, renaming." + "Found an old user for #{nickname}, the old ap id is #{old_user.ap_id}, new one is #{data[:ap_id]}, renaming." ) old_user diff --git a/lib/pleroma/web/activity_pub/activity_pub_controller.ex b/lib/pleroma/web/activity_pub/activity_pub_controller.ex index 57ac40b42..4a19938f6 100644 --- a/lib/pleroma/web/activity_pub/activity_pub_controller.ex +++ b/lib/pleroma/web/activity_pub/activity_pub_controller.ex @@ -283,15 +283,29 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do json(conn, "ok") end + def inbox(%{assigns: %{valid_signature: false}} = conn, _params) do + conn + |> put_status(:bad_request) + |> json("Invalid HTTP Signature") + end + # POST /relay/inbox -or- POST /internal/fetch/inbox - def inbox(conn, params) do - if params["type"] == "Create" && FederatingPlug.federating?() do + def inbox(conn, %{"type" => "Create"} = params) do + if FederatingPlug.federating?() do post_inbox_relayed_create(conn, params) else - post_inbox_fallback(conn, params) + conn + |> put_status(:bad_request) + |> json("Not federating") end end + def inbox(conn, _params) do + conn + |> put_status(:bad_request) + |> json("error, missing HTTP Signature") + end + defp post_inbox_relayed_create(conn, params) do Logger.debug( "Signature missing or not from author, relayed Create message, fetching object from source" @@ -302,23 +316,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do json(conn, "ok") end - defp post_inbox_fallback(conn, params) do - headers = Enum.into(conn.req_headers, %{}) - - if headers["signature"] && params["actor"] && - String.contains?(headers["signature"], params["actor"]) do - Logger.debug( - "Signature validation error for: #{params["actor"]}, make sure you are forwarding the HTTP Host header!" - ) - - Logger.debug(inspect(conn.req_headers)) - end - - conn - |> put_status(:bad_request) - |> json(dgettext("errors", "error")) - end - defp represent_service_actor(%User{} = user, conn) do with {:ok, user} <- User.ensure_keys_present(user) do conn diff --git a/lib/pleroma/web/activity_pub/mrf.ex b/lib/pleroma/web/activity_pub/mrf.ex index e4ee8fe82..bd6f6777f 100644 --- a/lib/pleroma/web/activity_pub/mrf.ex +++ b/lib/pleroma/web/activity_pub/mrf.ex @@ -157,9 +157,7 @@ defmodule Pleroma.Web.ActivityPub.MRF do [description | acc] else Logger.warn( - "#{policy} config description doesn't have one or all required keys #{ - inspect(@required_description_keys) - }" + "#{policy} config description doesn't have one or all required keys #{inspect(@required_description_keys)}" ) acc diff --git a/lib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex b/lib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex index fbe9795ac..0dd415732 100644 --- a/lib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex +++ b/lib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex @@ -38,9 +38,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.StealEmojiPolicy do end else Logger.debug( - "MRF.StealEmojiPolicy: :#{shortcode}: at #{url} (#{byte_size(response.body)} B) over size limit (#{ - size_limit - } B)" + "MRF.StealEmojiPolicy: :#{shortcode}: at #{url} (#{byte_size(response.body)} B) over size limit (#{size_limit} B)" ) nil diff --git a/lib/pleroma/web/activity_pub/mrf/subchain_policy.ex b/lib/pleroma/web/activity_pub/mrf/subchain_policy.ex index f84d7cc71..11a36aca1 100644 --- a/lib/pleroma/web/activity_pub/mrf/subchain_policy.ex +++ b/lib/pleroma/web/activity_pub/mrf/subchain_policy.ex @@ -23,9 +23,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SubchainPolicy do def filter(%{"actor" => actor} = message) do with {:ok, match, subchain} <- lookup_subchain(actor) do Logger.debug( - "[SubchainPolicy] Matched #{actor} against #{inspect(match)} with subchain #{ - inspect(subchain) - }" + "[SubchainPolicy] Matched #{actor} against #{inspect(match)} with subchain #{inspect(subchain)}" ) MRF.filter(subchain, message) diff --git a/lib/pleroma/web/activity_pub/object_validators/accept_reject_validator.ex b/lib/pleroma/web/activity_pub/object_validators/accept_reject_validator.ex index b577a1044..7c3c8d0fa 100644 --- a/lib/pleroma/web/activity_pub/object_validators/accept_reject_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/accept_reject_validator.ex @@ -6,7 +6,6 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AcceptRejectValidator do use Ecto.Schema alias Pleroma.Activity - alias Pleroma.EctoType.ActivityPub.ObjectValidators import Ecto.Changeset import Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations @@ -14,12 +13,13 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AcceptRejectValidator do @primary_key false embedded_schema do - field(:id, ObjectValidators.ObjectID, primary_key: true) - field(:type, :string) - field(:object, ObjectValidators.ObjectID) - field(:actor, ObjectValidators.ObjectID) - field(:to, ObjectValidators.Recipients, default: []) - field(:cc, ObjectValidators.Recipients, default: []) + quote do + unquote do + import Elixir.Pleroma.Web.ActivityPub.ObjectValidators.CommonFields + message_fields() + activity_fields() + end + end end def cast_data(data) do diff --git a/lib/pleroma/web/activity_pub/object_validators/add_remove_validator.ex b/lib/pleroma/web/activity_pub/object_validators/add_remove_validator.ex index f885aabe4..fc482c9c0 100644 --- a/lib/pleroma/web/activity_pub/object_validators/add_remove_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/add_remove_validator.ex @@ -10,19 +10,20 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AddRemoveValidator do require Pleroma.Constants - alias Pleroma.EctoType.ActivityPub.ObjectValidators alias Pleroma.User @primary_key false embedded_schema do - field(:id, ObjectValidators.ObjectID, primary_key: true) field(:target) - field(:object, ObjectValidators.ObjectID) - field(:actor, ObjectValidators.ObjectID) - field(:type) - field(:to, ObjectValidators.Recipients, default: []) - field(:cc, ObjectValidators.Recipients, default: []) + + quote do + unquote do + import Elixir.Pleroma.Web.ActivityPub.ObjectValidators.CommonFields + message_fields() + activity_fields() + end + end end def cast_and_validate(data) do diff --git a/lib/pleroma/web/activity_pub/object_validators/announce_validator.ex b/lib/pleroma/web/activity_pub/object_validators/announce_validator.ex index 4db76f387..a7f2f6673 100644 --- a/lib/pleroma/web/activity_pub/object_validators/announce_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/announce_validator.ex @@ -20,13 +20,15 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AnnounceValidator do @primary_key false embedded_schema do - field(:id, ObjectValidators.ObjectID, primary_key: true) - field(:type, :string) - field(:object, ObjectValidators.ObjectID) - field(:actor, ObjectValidators.ObjectID) + quote do + unquote do + import Elixir.Pleroma.Web.ActivityPub.ObjectValidators.CommonFields + message_fields() + activity_fields() + end + end + field(:context, :string) - field(:to, ObjectValidators.Recipients, default: []) - field(:cc, ObjectValidators.Recipients, default: []) field(:published, ObjectValidators.DateTime) end diff --git a/lib/pleroma/web/activity_pub/object_validators/answer_validator.ex b/lib/pleroma/web/activity_pub/object_validators/answer_validator.ex index 3451e1ff8..4325e44f7 100644 --- a/lib/pleroma/web/activity_pub/object_validators/answer_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/answer_validator.ex @@ -15,12 +15,13 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AnswerValidator do @derive Jason.Encoder embedded_schema do - field(:id, ObjectValidators.ObjectID, primary_key: true) - field(:to, ObjectValidators.Recipients, default: []) - field(:cc, ObjectValidators.Recipients, default: []) - field(:bto, ObjectValidators.Recipients, default: []) - field(:bcc, ObjectValidators.Recipients, default: []) - field(:type, :string) + quote do + unquote do + import Elixir.Pleroma.Web.ActivityPub.ObjectValidators.CommonFields + message_fields() + end + end + field(:name, :string) field(:inReplyTo, ObjectValidators.ObjectID) field(:attributedTo, ObjectValidators.ObjectID) diff --git a/lib/pleroma/web/activity_pub/object_validators/article_note_page_validator.ex b/lib/pleroma/web/activity_pub/object_validators/article_note_page_validator.ex index 0d987116c..0aa249c4c 100644 --- a/lib/pleroma/web/activity_pub/object_validators/article_note_page_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/article_note_page_validator.ex @@ -6,10 +6,8 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidator do use Ecto.Schema alias Pleroma.EctoType.ActivityPub.ObjectValidators - alias Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator alias Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes alias Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations - alias Pleroma.Web.ActivityPub.ObjectValidators.TagValidator alias Pleroma.Web.ActivityPub.Transmogrifier import Ecto.Changeset @@ -18,38 +16,14 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidator do @derive Jason.Encoder embedded_schema do - field(:id, ObjectValidators.ObjectID, primary_key: true) - field(:to, ObjectValidators.Recipients, default: []) - field(:cc, ObjectValidators.Recipients, default: []) - field(:bto, ObjectValidators.Recipients, default: []) - field(:bcc, ObjectValidators.Recipients, default: []) - embeds_many(:tag, TagValidator) - field(:type, :string) - - field(:name, :string) - field(:summary, :string) - field(:content, :string) - - field(:context, :string) - # short identifier for PleromaFE to group statuses by context - field(:context_id, :integer) - - # TODO: Remove actor on objects - field(:actor, ObjectValidators.ObjectID) - - field(:attributedTo, ObjectValidators.ObjectID) - field(:published, ObjectValidators.DateTime) - field(:emoji, ObjectValidators.Emoji, default: %{}) - field(:sensitive, :boolean, default: false) - embeds_many(:attachment, AttachmentValidator) - field(:replies_count, :integer, default: 0) - field(:like_count, :integer, default: 0) - field(:announcement_count, :integer, default: 0) - field(:inReplyTo, ObjectValidators.ObjectID) - field(:url, ObjectValidators.Uri) - - field(:likes, {:array, ObjectValidators.ObjectID}, default: []) - field(:announcements, {:array, ObjectValidators.ObjectID}, default: []) + quote do + unquote do + import Elixir.Pleroma.Web.ActivityPub.ObjectValidators.CommonFields + message_fields() + object_fields() + status_object_fields() + end + end field(:replies, {:array, ObjectValidators.ObjectID}, default: []) end diff --git a/lib/pleroma/web/activity_pub/object_validators/attachment_validator.ex b/lib/pleroma/web/activity_pub/object_validators/attachment_validator.ex index 837787b9f..59fef42d6 100644 --- a/lib/pleroma/web/activity_pub/object_validators/attachment_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/attachment_validator.ex @@ -68,12 +68,14 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator do end end - defp handle_href(href, mediaType) do + defp handle_href(href, mediaType, data) do [ %{ "href" => href, "type" => "Link", - "mediaType" => mediaType + "mediaType" => mediaType, + "width" => data["width"], + "height" => data["height"] } ] end @@ -81,10 +83,10 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator do defp fix_url(data) do cond do is_binary(data["url"]) -> - Map.put(data, "url", handle_href(data["url"], data["mediaType"])) + Map.put(data, "url", handle_href(data["url"], data["mediaType"], data)) is_binary(data["href"]) and data["url"] == nil -> - Map.put(data, "url", handle_href(data["href"], data["mediaType"])) + Map.put(data, "url", handle_href(data["href"], data["mediaType"], data)) true -> data diff --git a/lib/pleroma/web/activity_pub/object_validators/audio_video_validator.ex b/lib/pleroma/web/activity_pub/object_validators/audio_video_validator.ex index 572687deb..331ec9050 100644 --- a/lib/pleroma/web/activity_pub/object_validators/audio_video_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/audio_video_validator.ex @@ -5,11 +5,8 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AudioVideoValidator do use Ecto.Schema - alias Pleroma.EctoType.ActivityPub.ObjectValidators - alias Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator alias Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes alias Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations - alias Pleroma.Web.ActivityPub.ObjectValidators.TagValidator alias Pleroma.Web.ActivityPub.Transmogrifier import Ecto.Changeset @@ -18,38 +15,14 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AudioVideoValidator do @derive Jason.Encoder embedded_schema do - field(:id, ObjectValidators.ObjectID, primary_key: true) - field(:to, ObjectValidators.Recipients, default: []) - field(:cc, ObjectValidators.Recipients, default: []) - field(:bto, ObjectValidators.Recipients, default: []) - field(:bcc, ObjectValidators.Recipients, default: []) - embeds_many(:tag, TagValidator) - field(:type, :string) - - field(:name, :string) - field(:summary, :string) - field(:content, :string) - - field(:context, :string) - # short identifier for PleromaFE to group statuses by context - field(:context_id, :integer) - - # TODO: Remove actor on objects - field(:actor, ObjectValidators.ObjectID) - - field(:attributedTo, ObjectValidators.ObjectID) - field(:published, ObjectValidators.DateTime) - field(:emoji, ObjectValidators.Emoji, default: %{}) - field(:sensitive, :boolean, default: false) - embeds_many(:attachment, AttachmentValidator) - field(:replies_count, :integer, default: 0) - field(:like_count, :integer, default: 0) - field(:announcement_count, :integer, default: 0) - field(:inReplyTo, ObjectValidators.ObjectID) - field(:url, ObjectValidators.Uri) - - field(:likes, {:array, ObjectValidators.ObjectID}, default: []) - field(:announcements, {:array, ObjectValidators.ObjectID}, default: []) + quote do + unquote do + import Elixir.Pleroma.Web.ActivityPub.ObjectValidators.CommonFields + message_fields() + object_fields() + status_object_fields() + end + end end def cast_and_apply(data) do diff --git a/lib/pleroma/web/activity_pub/object_validators/block_validator.ex b/lib/pleroma/web/activity_pub/object_validators/block_validator.ex index 88948135f..400e5e278 100644 --- a/lib/pleroma/web/activity_pub/object_validators/block_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/block_validator.ex @@ -5,20 +5,21 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.BlockValidator do use Ecto.Schema - alias Pleroma.EctoType.ActivityPub.ObjectValidators + alias Elixir.Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations import Ecto.Changeset - import Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations @primary_key false + @derive Jason.Encoder embedded_schema do - field(:id, ObjectValidators.ObjectID, primary_key: true) - field(:type, :string) - field(:actor, ObjectValidators.ObjectID) - field(:to, ObjectValidators.Recipients, default: []) - field(:cc, ObjectValidators.Recipients, default: []) - field(:object, ObjectValidators.ObjectID) + quote do + unquote do + import Elixir.Pleroma.Web.ActivityPub.ObjectValidators.CommonFields + message_fields() + activity_fields() + end + end end def cast_data(data) do @@ -30,8 +31,8 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.BlockValidator do cng |> validate_required([:id, :type, :actor, :to, :cc, :object]) |> validate_inclusion(:type, ["Block"]) - |> validate_actor_presence() - |> validate_actor_presence(field_name: :object) + |> CommonValidations.validate_actor_presence() + |> CommonValidations.validate_actor_presence(field_name: :object) end def cast_and_validate(data) do diff --git a/lib/pleroma/web/activity_pub/object_validators/common_fields.ex b/lib/pleroma/web/activity_pub/object_validators/common_fields.ex new file mode 100644 index 000000000..872f80ec3 --- /dev/null +++ b/lib/pleroma/web/activity_pub/object_validators/common_fields.ex @@ -0,0 +1,68 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonFields do + alias Pleroma.EctoType.ActivityPub.ObjectValidators + alias Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator + alias Pleroma.Web.ActivityPub.ObjectValidators.TagValidator + + # Activities and Objects, except (Create)ChatMessage + defmacro message_fields do + quote bind_quoted: binding() do + field(:type, :string) + field(:id, ObjectValidators.ObjectID, primary_key: true) + + field(:to, ObjectValidators.Recipients, default: []) + field(:cc, ObjectValidators.Recipients, default: []) + field(:bto, ObjectValidators.Recipients, default: []) + field(:bcc, ObjectValidators.Recipients, default: []) + end + end + + defmacro activity_fields do + quote bind_quoted: binding() do + field(:object, ObjectValidators.ObjectID) + field(:actor, ObjectValidators.ObjectID) + end + end + + # All objects except Answer and CHatMessage + defmacro object_fields do + quote bind_quoted: binding() do + field(:content, :string) + + field(:published, ObjectValidators.DateTime) + field(:emoji, ObjectValidators.Emoji, default: %{}) + embeds_many(:attachment, AttachmentValidator) + end + end + + # Basically objects that aren't ChatMessage and Answer + defmacro status_object_fields do + quote bind_quoted: binding() do + # TODO: Remove actor on objects + field(:actor, ObjectValidators.ObjectID) + field(:attributedTo, ObjectValidators.ObjectID) + + embeds_many(:tag, TagValidator) + + field(:name, :string) + field(:summary, :string) + + field(:context, :string) + # short identifier for PleromaFE to group statuses by context + field(:context_id, :integer) + + field(:sensitive, :boolean, default: false) + field(:replies_count, :integer, default: 0) + field(:like_count, :integer, default: 0) + field(:announcement_count, :integer, default: 0) + field(:inReplyTo, ObjectValidators.ObjectID) + field(:url, ObjectValidators.Uri) + + field(:likes, {:array, ObjectValidators.ObjectID}, default: []) + field(:announcements, {:array, ObjectValidators.ObjectID}, default: []) + end + end +end diff --git a/lib/pleroma/web/activity_pub/object_validators/create_chat_message_validator.ex b/lib/pleroma/web/activity_pub/object_validators/create_chat_message_validator.ex index 7a31a99bf..6551f64ca 100644 --- a/lib/pleroma/web/activity_pub/object_validators/create_chat_message_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/create_chat_message_validator.ex @@ -17,11 +17,16 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CreateChatMessageValidator do @primary_key false embedded_schema do + quote do + unquote do + import Elixir.Pleroma.Web.ActivityPub.ObjectValidators.CommonFields + activity_fields() + end + end + field(:id, ObjectValidators.ObjectID, primary_key: true) - field(:actor, ObjectValidators.ObjectID) field(:type, :string) field(:to, ObjectValidators.Recipients, default: []) - field(:object, ObjectValidators.ObjectID) end def cast_and_apply(data) do diff --git a/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex b/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex index d2de53049..803b5d5a1 100644 --- a/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex @@ -20,14 +20,14 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CreateGenericValidator do @primary_key false embedded_schema do - field(:id, ObjectValidators.ObjectID, primary_key: true) - field(:actor, ObjectValidators.ObjectID) - field(:type, :string) - field(:to, ObjectValidators.Recipients, default: []) - field(:cc, ObjectValidators.Recipients, default: []) - field(:bto, ObjectValidators.Recipients, default: []) - field(:bcc, ObjectValidators.Recipients, default: []) - field(:object, ObjectValidators.ObjectID) + quote do + unquote do + import Elixir.Pleroma.Web.ActivityPub.ObjectValidators.CommonFields + message_fields() + activity_fields() + end + end + field(:expires_at, ObjectValidators.DateTime) # Should be moved to object, done for CommonAPI.Utils.make_context diff --git a/lib/pleroma/web/activity_pub/object_validators/delete_validator.ex b/lib/pleroma/web/activity_pub/object_validators/delete_validator.ex index 05f93da82..f0c99356e 100644 --- a/lib/pleroma/web/activity_pub/object_validators/delete_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/delete_validator.ex @@ -15,13 +15,15 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.DeleteValidator do @primary_key false embedded_schema do - field(:id, ObjectValidators.ObjectID, primary_key: true) - field(:type, :string) - field(:actor, ObjectValidators.ObjectID) - field(:to, ObjectValidators.Recipients, default: []) - field(:cc, ObjectValidators.Recipients, default: []) + quote do + unquote do + import Elixir.Pleroma.Web.ActivityPub.ObjectValidators.CommonFields + message_fields() + activity_fields() + end + end + field(:deleted_activity_id, ObjectValidators.ObjectID) - field(:object, ObjectValidators.ObjectID) end def cast_data(data) do diff --git a/lib/pleroma/web/activity_pub/object_validators/emoji_react_validator.ex b/lib/pleroma/web/activity_pub/object_validators/emoji_react_validator.ex index a18bd7540..9eaaf8319 100644 --- a/lib/pleroma/web/activity_pub/object_validators/emoji_react_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/emoji_react_validator.ex @@ -5,7 +5,6 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.EmojiReactValidator do use Ecto.Schema - alias Pleroma.EctoType.ActivityPub.ObjectValidators alias Pleroma.Object alias Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes @@ -15,14 +14,16 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.EmojiReactValidator do @primary_key false embedded_schema do - field(:id, ObjectValidators.ObjectID, primary_key: true) - field(:type, :string) - field(:object, ObjectValidators.ObjectID) - field(:actor, ObjectValidators.ObjectID) + quote do + unquote do + import Elixir.Pleroma.Web.ActivityPub.ObjectValidators.CommonFields + message_fields() + activity_fields() + end + end + field(:context, :string) field(:content, :string) - field(:to, ObjectValidators.Recipients, default: []) - field(:cc, ObjectValidators.Recipients, default: []) end def cast_and_validate(data) do diff --git a/lib/pleroma/web/activity_pub/object_validators/event_validator.ex b/lib/pleroma/web/activity_pub/object_validators/event_validator.ex index fee2e997a..34a3031c3 100644 --- a/lib/pleroma/web/activity_pub/object_validators/event_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/event_validator.ex @@ -5,11 +5,8 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.EventValidator do use Ecto.Schema - alias Pleroma.EctoType.ActivityPub.ObjectValidators - alias Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator alias Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes alias Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations - alias Pleroma.Web.ActivityPub.ObjectValidators.TagValidator alias Pleroma.Web.ActivityPub.Transmogrifier import Ecto.Changeset @@ -19,38 +16,14 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.EventValidator do # Extends from NoteValidator embedded_schema do - field(:id, ObjectValidators.ObjectID, primary_key: true) - field(:to, ObjectValidators.Recipients, default: []) - field(:cc, ObjectValidators.Recipients, default: []) - field(:bto, ObjectValidators.Recipients, default: []) - field(:bcc, ObjectValidators.Recipients, default: []) - embeds_many(:tag, TagValidator) - field(:type, :string) - - field(:name, :string) - field(:summary, :string) - field(:content, :string) - - field(:context, :string) - # short identifier for PleromaFE to group statuses by context - field(:context_id, :integer) - - # TODO: Remove actor on objects - field(:actor, ObjectValidators.ObjectID) - - field(:attributedTo, ObjectValidators.ObjectID) - field(:published, ObjectValidators.DateTime) - field(:emoji, ObjectValidators.Emoji, default: %{}) - field(:sensitive, :boolean, default: false) - embeds_many(:attachment, AttachmentValidator) - field(:replies_count, :integer, default: 0) - field(:like_count, :integer, default: 0) - field(:announcement_count, :integer, default: 0) - field(:inReplyTo, ObjectValidators.ObjectID) - field(:url, ObjectValidators.Uri) - - field(:likes, {:array, ObjectValidators.ObjectID}, default: []) - field(:announcements, {:array, ObjectValidators.ObjectID}, default: []) + quote do + unquote do + import Elixir.Pleroma.Web.ActivityPub.ObjectValidators.CommonFields + message_fields() + object_fields() + status_object_fields() + end + end end def cast_and_apply(data) do diff --git a/lib/pleroma/web/activity_pub/object_validators/follow_validator.ex b/lib/pleroma/web/activity_pub/object_validators/follow_validator.ex index 239cee5e7..c061ebba9 100644 --- a/lib/pleroma/web/activity_pub/object_validators/follow_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/follow_validator.ex @@ -5,20 +5,20 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.FollowValidator do use Ecto.Schema - alias Pleroma.EctoType.ActivityPub.ObjectValidators - import Ecto.Changeset import Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations @primary_key false embedded_schema do - field(:id, ObjectValidators.ObjectID, primary_key: true) - field(:type, :string) - field(:actor, ObjectValidators.ObjectID) - field(:to, ObjectValidators.Recipients, default: []) - field(:cc, ObjectValidators.Recipients, default: []) - field(:object, ObjectValidators.ObjectID) + quote do + unquote do + import Elixir.Pleroma.Web.ActivityPub.ObjectValidators.CommonFields + message_fields() + activity_fields() + end + end + field(:state, :string, default: "pending") end diff --git a/lib/pleroma/web/activity_pub/object_validators/like_validator.ex b/lib/pleroma/web/activity_pub/object_validators/like_validator.ex index 8b99c89b9..35e000d72 100644 --- a/lib/pleroma/web/activity_pub/object_validators/like_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/like_validator.ex @@ -5,7 +5,6 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator do use Ecto.Schema - alias Pleroma.EctoType.ActivityPub.ObjectValidators alias Pleroma.Object alias Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes alias Pleroma.Web.ActivityPub.Utils @@ -16,13 +15,15 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator do @primary_key false embedded_schema do - field(:id, ObjectValidators.ObjectID, primary_key: true) - field(:type, :string) - field(:object, ObjectValidators.ObjectID) - field(:actor, ObjectValidators.ObjectID) + quote do + unquote do + import Elixir.Pleroma.Web.ActivityPub.ObjectValidators.CommonFields + message_fields() + activity_fields() + end + end + field(:context, :string) - field(:to, ObjectValidators.Recipients, default: []) - field(:cc, ObjectValidators.Recipients, default: []) end def cast_and_validate(data) do diff --git a/lib/pleroma/web/activity_pub/object_validators/question_validator.ex b/lib/pleroma/web/activity_pub/object_validators/question_validator.ex index 083d08ec4..bdddfdaeb 100644 --- a/lib/pleroma/web/activity_pub/object_validators/question_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/question_validator.ex @@ -6,11 +6,9 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.QuestionValidator do use Ecto.Schema alias Pleroma.EctoType.ActivityPub.ObjectValidators - alias Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator alias Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes alias Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations alias Pleroma.Web.ActivityPub.ObjectValidators.QuestionOptionsValidator - alias Pleroma.Web.ActivityPub.ObjectValidators.TagValidator alias Pleroma.Web.ActivityPub.Transmogrifier import Ecto.Changeset @@ -20,35 +18,14 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.QuestionValidator do # Extends from NoteValidator embedded_schema do - field(:id, ObjectValidators.ObjectID, primary_key: true) - field(:to, ObjectValidators.Recipients, default: []) - field(:cc, ObjectValidators.Recipients, default: []) - field(:bto, ObjectValidators.Recipients, default: []) - field(:bcc, ObjectValidators.Recipients, default: []) - embeds_many(:tag, TagValidator) - field(:type, :string) - field(:content, :string) - field(:context, :string) - - # TODO: Remove actor on objects - field(:actor, ObjectValidators.ObjectID) - - field(:attributedTo, ObjectValidators.ObjectID) - field(:summary, :string) - field(:published, ObjectValidators.DateTime) - field(:emoji, ObjectValidators.Emoji, default: %{}) - field(:sensitive, :boolean, default: false) - embeds_many(:attachment, AttachmentValidator) - field(:replies_count, :integer, default: 0) - field(:like_count, :integer, default: 0) - field(:announcement_count, :integer, default: 0) - field(:inReplyTo, ObjectValidators.ObjectID) - field(:url, ObjectValidators.Uri) - # short identifier for PleromaFE to group statuses by context - field(:context_id, :integer) - - field(:likes, {:array, ObjectValidators.ObjectID}, default: []) - field(:announcements, {:array, ObjectValidators.ObjectID}, default: []) + quote do + unquote do + import Elixir.Pleroma.Web.ActivityPub.ObjectValidators.CommonFields + message_fields() + object_fields() + status_object_fields() + end + end field(:closed, ObjectValidators.DateTime) field(:voters, {:array, ObjectValidators.ObjectID}, default: []) diff --git a/lib/pleroma/web/activity_pub/object_validators/undo_validator.ex b/lib/pleroma/web/activity_pub/object_validators/undo_validator.ex index 6ff648c84..703643e3f 100644 --- a/lib/pleroma/web/activity_pub/object_validators/undo_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/undo_validator.ex @@ -6,7 +6,6 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.UndoValidator do use Ecto.Schema alias Pleroma.Activity - alias Pleroma.EctoType.ActivityPub.ObjectValidators alias Pleroma.User import Ecto.Changeset @@ -15,12 +14,13 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.UndoValidator do @primary_key false embedded_schema do - field(:id, ObjectValidators.ObjectID, primary_key: true) - field(:type, :string) - field(:object, ObjectValidators.ObjectID) - field(:actor, ObjectValidators.ObjectID) - field(:to, ObjectValidators.Recipients, default: []) - field(:cc, ObjectValidators.Recipients, default: []) + quote do + unquote do + import Elixir.Pleroma.Web.ActivityPub.ObjectValidators.CommonFields + message_fields() + activity_fields() + end + end end def cast_and_validate(data) do diff --git a/lib/pleroma/web/activity_pub/object_validators/update_validator.ex b/lib/pleroma/web/activity_pub/object_validators/update_validator.ex index 6bb1dc7fa..a1fae47f5 100644 --- a/lib/pleroma/web/activity_pub/object_validators/update_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/update_validator.ex @@ -13,11 +13,14 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.UpdateValidator do @primary_key false embedded_schema do - field(:id, ObjectValidators.ObjectID, primary_key: true) - field(:type, :string) + quote do + unquote do + import Elixir.Pleroma.Web.ActivityPub.ObjectValidators.CommonFields + message_fields() + end + end + field(:actor, ObjectValidators.ObjectID) - field(:to, ObjectValidators.Recipients, default: []) - field(:cc, ObjectValidators.Recipients, default: []) # In this case, we save the full object in this activity instead of just a # reference, so we can always see what was actually changed by this. field(:object, :map) diff --git a/lib/pleroma/web/activity_pub/publisher.ex b/lib/pleroma/web/activity_pub/publisher.ex index 4f29a4411..ed99079e2 100644 --- a/lib/pleroma/web/activity_pub/publisher.ex +++ b/lib/pleroma/web/activity_pub/publisher.ex @@ -63,18 +63,17 @@ defmodule Pleroma.Web.ActivityPub.Publisher do date: date }) - with {:ok, %{status: code}} when code in 200..299 <- - result = - HTTP.post( - inbox, - json, - [ - {"Content-Type", "application/activity+json"}, - {"Date", date}, - {"signature", signature}, - {"digest", digest} - ] - ) do + with {:ok, %{status: code}} = result when code in 200..299 <- + HTTP.post( + inbox, + json, + [ + {"Content-Type", "application/activity+json"}, + {"Date", date}, + {"signature", signature}, + {"digest", digest} + ] + ) do if not Map.has_key?(params, :unreachable_since) || params[:unreachable_since] do Instances.set_reachable(inbox) end diff --git a/lib/pleroma/web/activity_pub/side_effects.ex b/lib/pleroma/web/activity_pub/side_effects.ex index 701181a14..d55a4b340 100644 --- a/lib/pleroma/web/activity_pub/side_effects.ex +++ b/lib/pleroma/web/activity_pub/side_effects.ex @@ -200,7 +200,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do {:ok, notifications} = Notification.create_notifications(activity, do_send: false) {:ok, _user} = ActivityPub.increase_note_count_if_public(user, object) - if in_reply_to = object.data["inReplyTo"] && object.data["type"] != "Answer" do + if in_reply_to = object.data["type"] != "Answer" && object.data["inReplyTo"] do Object.increase_replies_count(in_reply_to) end diff --git a/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex b/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex index 839ac1a8d..50aa294f0 100644 --- a/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex +++ b/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex @@ -49,7 +49,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do plug( OAuthScopesPlug, %{scopes: ["admin:read:statuses"]} - when action in [:list_user_statuses, :list_instance_statuses] + when action in [:list_user_statuses] ) plug( @@ -81,24 +81,6 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do action_fallback(AdminAPI.FallbackController) - def list_instance_statuses(conn, %{"instance" => instance} = params) do - with_reblogs = params["with_reblogs"] == "true" || params["with_reblogs"] == true - {page, page_size} = page_params(params) - - result = - ActivityPub.fetch_statuses(nil, %{ - instance: instance, - limit: page_size, - offset: (page - 1) * page_size, - exclude_reblogs: not with_reblogs, - total: true - }) - - conn - |> put_view(AdminAPI.StatusView) - |> render("index.json", %{total: result[:total], activities: result[:items], as: :activity}) - end - def list_user_statuses(%{assigns: %{user: admin}} = conn, %{"nickname" => nickname} = params) do with_reblogs = params["with_reblogs"] == "true" || params["with_reblogs"] == true godmode = params["godmode"] == "true" || params["godmode"] == true diff --git a/lib/pleroma/web/admin_api/controllers/instance_controller.ex b/lib/pleroma/web/admin_api/controllers/instance_controller.ex new file mode 100644 index 000000000..00857983f --- /dev/null +++ b/lib/pleroma/web/admin_api/controllers/instance_controller.ex @@ -0,0 +1,63 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.AdminAPI.InstanceController do + use Pleroma.Web, :controller + + import Pleroma.Web.ControllerHelper, only: [fetch_integer_param: 3] + + alias Pleroma.Instances.Instance + alias Pleroma.Web.ActivityPub.ActivityPub + alias Pleroma.Web.AdminAPI + alias Pleroma.Web.Plugs.OAuthScopesPlug + + require Logger + + @default_page_size 50 + + plug( + OAuthScopesPlug, + %{scopes: ["admin:read:statuses"]} + when action in [:list_statuses] + ) + + plug( + OAuthScopesPlug, + %{scopes: ["admin:write:accounts", "admin:write:statuses"]} + when action in [:delete] + ) + + action_fallback(AdminAPI.FallbackController) + + def list_statuses(conn, %{"instance" => instance} = params) do + with_reblogs = params["with_reblogs"] == "true" || params["with_reblogs"] == true + {page, page_size} = page_params(params) + + result = + ActivityPub.fetch_statuses(nil, %{ + instance: instance, + limit: page_size, + offset: (page - 1) * page_size, + exclude_reblogs: not with_reblogs, + total: true + }) + + conn + |> put_view(AdminAPI.StatusView) + |> render("index.json", %{total: result[:total], activities: result[:items], as: :activity}) + end + + def delete(conn, %{"instance" => instance}) do + with {:ok, _job} <- Instance.delete_users_and_activities(instance) do + json(conn, instance) + end + end + + defp page_params(params) do + { + fetch_integer_param(params, "page", 1), + fetch_integer_param(params, "page_size", @default_page_size) + } + end +end diff --git a/lib/pleroma/web/admin_api/controllers/user_controller.ex b/lib/pleroma/web/admin_api/controllers/user_controller.ex index 637a0e702..50208a8b7 100644 --- a/lib/pleroma/web/admin_api/controllers/user_controller.ex +++ b/lib/pleroma/web/admin_api/controllers/user_controller.ex @@ -35,7 +35,9 @@ defmodule Pleroma.Web.AdminAPI.UserController do :toggle_activation, :activate, :deactivate, - :approve + :approve, + :suggest, + :unsuggest ] ) @@ -239,6 +241,32 @@ defmodule Pleroma.Web.AdminAPI.UserController do render(conn, "index.json", users: updated_users) end + def suggest(%{assigns: %{user: admin}, body_params: %{nicknames: nicknames}} = conn, _) do + users = Enum.map(nicknames, &User.get_cached_by_nickname/1) + {:ok, updated_users} = User.set_suggestion(users, true) + + ModerationLog.insert_log(%{ + actor: admin, + subject: users, + action: "add_suggestion" + }) + + render(conn, "index.json", users: updated_users) + end + + def unsuggest(%{assigns: %{user: admin}, body_params: %{nicknames: nicknames}} = conn, _) do + users = Enum.map(nicknames, &User.get_cached_by_nickname/1) + {:ok, updated_users} = User.set_suggestion(users, false) + + ModerationLog.insert_log(%{ + actor: admin, + subject: users, + action: "remove_suggestion" + }) + + render(conn, "index.json", users: updated_users) + end + def index(conn, params) do {page, page_size} = page_params(params) filters = maybe_parse_filters(params[:filters]) diff --git a/lib/pleroma/web/admin_api/views/account_view.ex b/lib/pleroma/web/admin_api/views/account_view.ex index fae0c07f0..2f1f7e627 100644 --- a/lib/pleroma/web/admin_api/views/account_view.ex +++ b/lib/pleroma/web/admin_api/views/account_view.ex @@ -80,6 +80,7 @@ defmodule Pleroma.Web.AdminAPI.AccountView do "tags" => user.tags || [], "is_confirmed" => user.is_confirmed, "is_approved" => user.is_approved, + "is_suggested" => user.is_suggested, "url" => user.uri || user.ap_id, "registration_reason" => user.registration_reason, "actor_type" => user.actor_type, diff --git a/lib/pleroma/web/api_spec/operations/admin/user_operation.ex b/lib/pleroma/web/api_spec/operations/admin/user_operation.ex index c9d0bfd7c..57fb1ad65 100644 --- a/lib/pleroma/web/api_spec/operations/admin/user_operation.ex +++ b/lib/pleroma/web/api_spec/operations/admin/user_operation.ex @@ -216,7 +216,71 @@ defmodule Pleroma.Web.ApiSpec.Admin.UserOperation do request_body( "Parameters", %Schema{ - description: "POST body for deleting multiple users", + description: "POST body for approving multiple users", + type: :object, + properties: %{ + nicknames: %Schema{ + type: :array, + items: %Schema{type: :string} + } + } + } + ), + responses: %{ + 200 => + Operation.response("Response", "application/json", %Schema{ + type: :object, + properties: %{user: %Schema{type: :array, items: user()}} + }), + 403 => Operation.response("Forbidden", "application/json", ApiError) + } + } + end + + def suggest_operation do + %Operation{ + tags: ["User administration"], + summary: "Suggest multiple users", + operationId: "AdminAPI.UserController.suggest", + security: [%{"oAuth" => ["admin:write:accounts"]}], + parameters: admin_api_params(), + requestBody: + request_body( + "Parameters", + %Schema{ + description: "POST body for adding multiple suggested users", + type: :object, + properties: %{ + nicknames: %Schema{ + type: :array, + items: %Schema{type: :string} + } + } + } + ), + responses: %{ + 200 => + Operation.response("Response", "application/json", %Schema{ + type: :object, + properties: %{user: %Schema{type: :array, items: user()}} + }), + 403 => Operation.response("Forbidden", "application/json", ApiError) + } + } + end + + def unsuggest_operation do + %Operation{ + tags: ["User administration"], + summary: "Unsuggest multiple users", + operationId: "AdminAPI.UserController.unsuggest", + security: [%{"oAuth" => ["admin:write:accounts"]}], + parameters: admin_api_params(), + requestBody: + request_body( + "Parameters", + %Schema{ + description: "POST body for removing multiple suggested users", type: :object, properties: %{ nicknames: %Schema{ diff --git a/lib/pleroma/web/api_spec/operations/twitter_util_operation.ex b/lib/pleroma/web/api_spec/operations/twitter_util_operation.ex index 879b2227e..5a2b0bc49 100644 --- a/lib/pleroma/web/api_spec/operations/twitter_util_operation.ex +++ b/lib/pleroma/web/api_spec/operations/twitter_util_operation.ex @@ -121,7 +121,10 @@ defmodule Pleroma.Web.ApiSpec.TwitterUtilOperation do type: :object, required: [:email, :password], properties: %{ - email: %Schema{type: :string, description: "New email"}, + email: %Schema{ + type: :string, + description: "New email. Set to blank to remove the user's email." + }, password: %Schema{type: :string, description: "Current password"} } } @@ -188,6 +191,7 @@ defmodule Pleroma.Web.ApiSpec.TwitterUtilOperation do parameters: [ Operation.parameter(:password, :query, :string, "Password") ], + requestBody: request_body("Parameters", delete_account_request(), required: false), responses: %{ 200 => Operation.response("Success", "application/json", %Schema{ @@ -234,4 +238,22 @@ defmodule Pleroma.Web.ApiSpec.TwitterUtilOperation do responses: %{200 => Operation.response("Web Page", "test/html", %Schema{type: :string})} } end + + defp delete_account_request do + %Schema{ + title: "AccountDeleteRequest", + description: "POST body for deleting one's own account", + type: :object, + properties: %{ + password: %Schema{ + type: :string, + description: "The user's own password for confirmation.", + format: :password + } + }, + example: %{ + "password" => "prettyp0ony1313" + } + } + end end diff --git a/lib/pleroma/web/common_api.ex b/lib/pleroma/web/common_api.ex index 1b5f8491e..6f685cb7b 100644 --- a/lib/pleroma/web/common_api.ex +++ b/lib/pleroma/web/common_api.ex @@ -487,9 +487,7 @@ defmodule Pleroma.Web.CommonAPI do else {what, result} = error -> Logger.warn( - "CommonAPI.remove_mute/2 failed. #{what}: #{result}, user_id: #{user_id}, activity_id: #{ - activity_id - }" + "CommonAPI.remove_mute/2 failed. #{what}: #{result}, user_id: #{user_id}, activity_id: #{activity_id}" ) {:error, error} diff --git a/lib/pleroma/web/endpoint.ex b/lib/pleroma/web/endpoint.ex index 8e274de88..75484fac5 100644 --- a/lib/pleroma/web/endpoint.ex +++ b/lib/pleroma/web/endpoint.ex @@ -10,6 +10,7 @@ defmodule Pleroma.Web.Endpoint do alias Pleroma.Config socket("/socket", Pleroma.Web.UserSocket) + socket("/live", Phoenix.LiveView.Socket) plug(Plug.Telemetry, event_prefix: [:phoenix, :endpoint]) diff --git a/lib/pleroma/web/feed/user_controller.ex b/lib/pleroma/web/feed/user_controller.ex index fa7879caf..739b1f026 100644 --- a/lib/pleroma/web/feed/user_controller.ex +++ b/lib/pleroma/web/feed/user_controller.ex @@ -18,6 +18,8 @@ defmodule Pleroma.Web.Feed.UserController do def feed_redirect(%{assigns: %{format: "html"}} = conn, %{"nickname" => nickname}) do with {_, %User{} = user} <- {:fetch_user, User.get_cached_by_nickname_or_id(nickname)} do Pleroma.Web.Fallback.RedirectController.redirector_with_meta(conn, %{user: user}) + else + _ -> Pleroma.Web.Fallback.RedirectController.redirector(conn, nil) end end diff --git a/lib/pleroma/web/manifest_controller.ex b/lib/pleroma/web/manifest_controller.ex new file mode 100644 index 000000000..52589540b --- /dev/null +++ b/lib/pleroma/web/manifest_controller.ex @@ -0,0 +1,14 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ManifestController do + use Pleroma.Web, :controller + + plug(:skip_auth when action == :show) + + @doc "GET /manifest.json" + def show(conn, _params) do + render(conn, "manifest.json") + end +end diff --git a/lib/pleroma/web/mastodon_api/controllers/search_controller.ex b/lib/pleroma/web/mastodon_api/controllers/search_controller.ex index 64b177eb3..1459fc492 100644 --- a/lib/pleroma/web/mastodon_api/controllers/search_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/search_controller.ex @@ -17,6 +17,8 @@ defmodule Pleroma.Web.MastodonAPI.SearchController do require Logger + @search_limit 40 + plug(Pleroma.Web.ApiSpec.CastAndValidate) # Note: Mastodon doesn't allow unauthenticated access (requires read:accounts / read:search) @@ -77,7 +79,7 @@ defmodule Pleroma.Web.MastodonAPI.SearchController do [ resolve: params[:resolve], following: params[:following], - limit: params[:limit], + limit: min(params[:limit], @search_limit), offset: params[:offset], type: params[:type], author: get_author(params), diff --git a/lib/pleroma/web/mastodon_api/controllers/suggestion_controller.ex b/lib/pleroma/web/mastodon_api/controllers/suggestion_controller.ex index 01e122dd9..e913fcf4b 100644 --- a/lib/pleroma/web/mastodon_api/controllers/suggestion_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/suggestion_controller.ex @@ -4,11 +4,16 @@ defmodule Pleroma.Web.MastodonAPI.SuggestionController do use Pleroma.Web, :controller + import Ecto.Query + alias Pleroma.FollowingRelationship + alias Pleroma.User + alias Pleroma.UserRelationship require Logger plug(Pleroma.Web.ApiSpec.CastAndValidate) - plug(Pleroma.Web.Plugs.OAuthScopesPlug, %{scopes: ["read"]} when action == :index) + plug(Pleroma.Web.Plugs.OAuthScopesPlug, %{scopes: ["read"]} when action in [:index, :index2]) + plug(Pleroma.Web.Plugs.OAuthScopesPlug, %{scopes: ["write"]} when action in [:dismiss]) def open_api_operation(action) do operation = String.to_existing_atom("#{action}_operation") @@ -26,7 +31,90 @@ defmodule Pleroma.Web.MastodonAPI.SuggestionController do } end + def index2_operation do + %OpenApiSpex.Operation{ + tags: ["Suggestions"], + summary: "Follow suggestions", + operationId: "SuggestionController.index2", + responses: %{ + 200 => Pleroma.Web.ApiSpec.Helpers.empty_array_response() + } + } + end + + def dismiss_operation do + %OpenApiSpex.Operation{ + tags: ["Suggestions"], + summary: "Remove a suggestion", + operationId: "SuggestionController.dismiss", + parameters: [ + OpenApiSpex.Operation.parameter( + :account_id, + :path, + %OpenApiSpex.Schema{type: :string}, + "Account to dismiss", + required: true + ) + ], + responses: %{ + 200 => Pleroma.Web.ApiSpec.Helpers.empty_object_response() + } + } + end + @doc "GET /api/v1/suggestions" def index(conn, params), do: Pleroma.Web.MastodonAPI.MastodonAPIController.empty_array(conn, params) + + @doc "GET /api/v2/suggestions" + def index2(%{assigns: %{user: user}} = conn, params) do + limit = Map.get(params, :limit, 40) |> min(80) + + users = + %{is_suggested: true, invisible: false, limit: limit} + |> User.Query.build() + |> exclude_user(user) + |> exclude_relationships(user, [:block, :mute, :suggestion_dismiss]) + |> exclude_following(user) + |> Pleroma.Repo.all() + + render(conn, "index.json", %{ + users: users, + source: :staff, + for: user, + skip_visibility_check: true + }) + end + + defp exclude_user(query, %User{id: user_id}) do + where(query, [u], u.id != ^user_id) + end + + defp exclude_relationships(query, %User{id: user_id}, relationship_types) do + query + |> join(:left, [u], r in UserRelationship, + as: :user_relationships, + on: + r.target_id == u.id and r.source_id == ^user_id and + r.relationship_type in ^relationship_types + ) + |> where([user_relationships: r], is_nil(r.target_id)) + end + + defp exclude_following(query, %User{id: user_id}) do + query + |> join(:left, [u], r in FollowingRelationship, + as: :following_relationships, + on: r.following_id == u.id and r.follower_id == ^user_id and r.state == :follow_accept + ) + |> where([following_relationships: r], is_nil(r.following_id)) + end + + @doc "DELETE /api/v1/suggestions/:account_id" + def dismiss(%{assigns: %{user: source}} = conn, %{account_id: user_id}) do + with %User{} = target <- User.get_cached_by_id(user_id), + {:ok, _} <- UserRelationship.create(:suggestion_dismiss, source, target) do + json(conn, %{}) + end + end end diff --git a/lib/pleroma/web/mastodon_api/views/account_view.ex b/lib/pleroma/web/mastodon_api/views/account_view.ex index 9e9de33f6..6114e12b1 100644 --- a/lib/pleroma/web/mastodon_api/views/account_view.ex +++ b/lib/pleroma/web/mastodon_api/views/account_view.ex @@ -269,6 +269,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do ap_id: user.ap_id, also_known_as: user.also_known_as, is_confirmed: user.is_confirmed, + is_suggested: user.is_suggested, tags: user.tags, hide_followers_count: user.hide_followers_count, hide_follows_count: user.hide_follows_count, diff --git a/lib/pleroma/web/mastodon_api/views/instance_view.ex b/lib/pleroma/web/mastodon_api/views/instance_view.ex index 70305b1c1..ec7d150a9 100644 --- a/lib/pleroma/web/mastodon_api/views/instance_view.ex +++ b/lib/pleroma/web/mastodon_api/views/instance_view.ex @@ -59,6 +59,7 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do "mastodon_api", "mastodon_api_streaming", "polls", + "v2_suggestions", "pleroma_explicit_addressing", "shareable_emoji_packs", "multifetch", diff --git a/lib/pleroma/web/mastodon_api/views/suggestion_view.ex b/lib/pleroma/web/mastodon_api/views/suggestion_view.ex new file mode 100644 index 000000000..865229a88 --- /dev/null +++ b/lib/pleroma/web/mastodon_api/views/suggestion_view.ex @@ -0,0 +1,28 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.MastodonAPI.SuggestionView do + use Pleroma.Web, :view + alias Pleroma.Web.MastodonAPI.AccountView + + @source_types [:staff, :global, :past_interactions] + + def render("index.json", %{users: users} = opts) do + Enum.map(users, fn user -> + opts = + opts + |> Map.put(:user, user) + |> Map.delete(:users) + + render("show.json", opts) + end) + end + + def render("show.json", %{source: source, user: _user} = opts) when source in @source_types do + %{ + source: source, + account: AccountView.render("show.json", opts) + } + end +end diff --git a/lib/pleroma/web/mastodon_api/websocket_handler.ex b/lib/pleroma/web/mastodon_api/websocket_handler.ex index 0d1faffbd..b978167b6 100644 --- a/lib/pleroma/web/mastodon_api/websocket_handler.ex +++ b/lib/pleroma/web/mastodon_api/websocket_handler.ex @@ -49,9 +49,7 @@ defmodule Pleroma.Web.MastodonAPI.WebsocketHandler do def websocket_init(state) do Logger.debug( - "#{__MODULE__} accepted websocket connection for user #{ - (state.user || %{id: "anonymous"}).id - }, topic #{state.topic}" + "#{__MODULE__} accepted websocket connection for user #{(state.user || %{id: "anonymous"}).id}, topic #{state.topic}" ) Streamer.add_socket(state.topic, state.user) @@ -106,9 +104,7 @@ defmodule Pleroma.Web.MastodonAPI.WebsocketHandler do def terminate(reason, _req, state) do Logger.debug( - "#{__MODULE__} terminating websocket connection for user #{ - (state.user || %{id: "anonymous"}).id - }, topic #{state.topic || "?"}: #{inspect(reason)}" + "#{__MODULE__} terminating websocket connection for user #{(state.user || %{id: "anonymous"}).id}, topic #{state.topic || "?"}: #{inspect(reason)}" ) Streamer.remove_socket(state.topic) diff --git a/lib/pleroma/web/nodeinfo/nodeinfo.ex b/lib/pleroma/web/nodeinfo/nodeinfo.ex index 6a0112d2a..3781781c8 100644 --- a/lib/pleroma/web/nodeinfo/nodeinfo.ex +++ b/lib/pleroma/web/nodeinfo/nodeinfo.ex @@ -35,7 +35,9 @@ defmodule Pleroma.Web.Nodeinfo.Nodeinfo do openRegistrations: Config.get([:instance, :registrations_open]), usage: %{ users: %{ - total: Map.get(stats, :user_count, 0) + total: Map.get(stats, :user_count, 0), + activeMonth: Pleroma.User.active_user_count(30), + activeHalfyear: Pleroma.User.active_user_count(180) }, localPosts: Map.get(stats, :status_count, 0) }, diff --git a/lib/pleroma/web/pleroma_api/controllers/chat_controller.ex b/lib/pleroma/web/pleroma_api/controllers/chat_controller.ex index dcd54b1af..669d50132 100644 --- a/lib/pleroma/web/pleroma_api/controllers/chat_controller.ex +++ b/lib/pleroma/web/pleroma_api/controllers/chat_controller.ex @@ -151,7 +151,9 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do index_query(user, params) |> Pagination.fetch_paginated(params) - render(conn, "index.json", chats: chats) + conn + |> add_link_headers(chats) + |> render("index.json", chats: chats) end defp index_query(%{id: user_id} = user, params) do diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index 1f84750b9..fa1d1b93f 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -4,6 +4,7 @@ defmodule Pleroma.Web.Router do use Pleroma.Web, :router + import Phoenix.LiveDashboard.Router pipeline :accepts_html do plug(:accepts, ["html"]) @@ -192,6 +193,9 @@ defmodule Pleroma.Web.Router do patch("/users/deactivate", UserController, :deactivate) patch("/users/approve", UserController, :approve) + patch("/users/suggest", UserController, :suggest) + patch("/users/unsuggest", UserController, :unsuggest) + get("/relay", RelayController, :index) post("/relay", RelayController, :follow) delete("/relay", RelayController, :unfollow) @@ -211,7 +215,8 @@ defmodule Pleroma.Web.Router do get("/users/:nickname/statuses", AdminAPIController, :list_user_statuses) get("/users/:nickname/chats", AdminAPIController, :list_user_chats) - get("/instances/:instance/statuses", AdminAPIController, :list_instance_statuses) + get("/instances/:instance/statuses", InstanceController, :list_statuses) + delete("/instances/:instance", InstanceController, :delete) get("/instance_document/:name", InstanceDocumentController, :show) patch("/instance_document/:name", InstanceDocumentController, :update) @@ -534,6 +539,7 @@ defmodule Pleroma.Web.Router do delete("/push/subscription", SubscriptionController, :delete) get("/suggestions", SuggestionController, :index) + delete("/suggestions/:account_id", SuggestionController, :dismiss) get("/timelines/home", TimelineController, :home) get("/timelines/direct", TimelineController, :direct) @@ -585,6 +591,8 @@ defmodule Pleroma.Web.Router do get("/search", SearchController, :search2) post("/media", MediaController, :create2) + + get("/suggestions", SuggestionController, :index2) end scope "/api", Pleroma.Web do @@ -735,6 +743,18 @@ defmodule Pleroma.Web.Router do get("/:version", Nodeinfo.NodeinfoController, :nodeinfo) end + scope "/", Pleroma.Web do + pipe_through(:api) + + get("/manifest.json", ManifestController, :show) + end + + scope "/", Pleroma.Web do + pipe_through(:pleroma_html) + + post("/auth/password", TwitterAPI.PasswordController, :request) + end + scope "/proxy/", Pleroma.Web do get("/preview/:sig/:url", MediaProxy.MediaProxyController, :preview) get("/preview/:sig/:url/:filename", MediaProxy.MediaProxyController, :preview) @@ -750,6 +770,11 @@ defmodule Pleroma.Web.Router do end end + scope "/" do + pipe_through([:pleroma_html, :authenticate, :require_admin]) + live_dashboard("/phoenix/live_dashboard") + end + # Test-only routes needed to test action dispatching and plug chain execution if Pleroma.Config.get(:env) == :test do @test_actions [ diff --git a/lib/pleroma/web/twitter_api/controllers/password_controller.ex b/lib/pleroma/web/twitter_api/controllers/password_controller.ex index bc04a4d49..133a588b0 100644 --- a/lib/pleroma/web/twitter_api/controllers/password_controller.ex +++ b/lib/pleroma/web/twitter_api/controllers/password_controller.ex @@ -11,9 +11,23 @@ defmodule Pleroma.Web.TwitterAPI.PasswordController do require Logger + import Pleroma.Web.ControllerHelper, only: [json_response: 3] + alias Pleroma.PasswordResetToken alias Pleroma.Repo alias Pleroma.User + alias Pleroma.Web.TwitterAPI.TwitterAPI + + plug(Pleroma.Web.Plugs.RateLimiter, [name: :request] when action == :request) + + @doc "POST /auth/password" + def request(conn, params) do + nickname_or_email = params["email"] || params["nickname"] + + TwitterAPI.password_reset(nickname_or_email) + + json_response(conn, :no_content, "") + end def reset(conn, %{"token" => token}) do with %{used: false} = token <- Repo.get_by(PasswordResetToken, %{token: token}), diff --git a/lib/pleroma/web/twitter_api/controllers/util_controller.ex b/lib/pleroma/web/twitter_api/controllers/util_controller.ex index ef43f7682..a4e44efdd 100644 --- a/lib/pleroma/web/twitter_api/controllers/util_controller.ex +++ b/lib/pleroma/web/twitter_api/controllers/util_controller.ex @@ -123,8 +123,10 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do end end - def delete_account(%{assigns: %{user: user}} = conn, params) do - password = params[:password] || "" + def delete_account(%{assigns: %{user: user}, body_params: body_params} = conn, params) do + # This endpoint can accept a query param or JSON body for backwards-compatibility. + # Submitting a JSON body is recommended, so passwords don't end up in server logs. + password = body_params[:password] || params[:password] || "" case CommonAPI.Utils.confirm_current_password(user, password) do {:ok, user} -> diff --git a/lib/pleroma/web/views/manifest_view.ex b/lib/pleroma/web/views/manifest_view.ex new file mode 100644 index 000000000..cc78ea347 --- /dev/null +++ b/lib/pleroma/web/views/manifest_view.ex @@ -0,0 +1,28 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ManifestView do + use Pleroma.Web, :view + alias Pleroma.Config + alias Pleroma.Web.Endpoint + + def render("manifest.json", _params) do + %{ + name: Config.get([:instance, :name]), + description: Config.get([:instance, :description]), + icons: Config.get([:manifest, :icons]), + theme_color: Config.get([:manifest, :theme_color]), + background_color: Config.get([:manifest, :background_color]), + display: "standalone", + scope: Endpoint.url(), + start_url: "/", + categories: [ + "social" + ], + serviceworker: %{ + src: "/sw.js" + } + } + end +end diff --git a/lib/pleroma/workers/background_worker.ex b/lib/pleroma/workers/background_worker.ex index 1e28384cb..4db077232 100644 --- a/lib/pleroma/workers/background_worker.ex +++ b/lib/pleroma/workers/background_worker.ex @@ -3,6 +3,7 @@ # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Workers.BackgroundWorker do + alias Pleroma.Instances.Instance alias Pleroma.User use Pleroma.Workers.WorkerHelper, queue: "background" @@ -38,4 +39,8 @@ defmodule Pleroma.Workers.BackgroundWorker do Pleroma.FollowingRelationship.move_following(origin, target) end + + def perform(%Job{args: %{"op" => "delete_instance", "host" => host}}) do + Instance.perform(:delete_instance, host) + end end @@ -79,6 +79,7 @@ defmodule Pleroma.Mixfile do :comeonin, :quack, :fast_sanitize, + :os_mon, :ssl ], included_applications: [:ex_syslogger] @@ -86,7 +87,7 @@ defmodule Pleroma.Mixfile do end # Specifies which paths to compile per environment. - defp elixirc_paths(:benchmark), do: ["lib", "benchmarks"] + defp elixirc_paths(:benchmark), do: ["lib", "benchmarks", "priv/scrubbers"] defp elixirc_paths(:test), do: ["lib", "test/support"] defp elixirc_paths(_), do: ["lib"] @@ -129,7 +130,7 @@ defmodule Pleroma.Mixfile do {:trailing_format_plug, "~> 0.0.7"}, {:fast_sanitize, "~> 0.2.0"}, {:html_entities, "~> 0.5", override: true}, - {:phoenix_html, "~> 2.14"}, + {:phoenix_html, "~> 3.1", override: true}, {:calendar, "~> 1.0"}, {:cachex, "~> 3.2"}, {:poison, "~> 3.0", override: true}, @@ -138,15 +139,15 @@ defmodule Pleroma.Mixfile do {:cowlib, "~> 2.9", override: true}, {:gun, "~> 2.0.0-rc.1", override: true}, {:jason, "~> 1.2"}, - {:mogrify, "~> 0.7.4"}, + {:mogrify, "~> 0.9.1"}, {:ex_aws, "~> 2.1.6"}, {:ex_aws_s3, "~> 2.0"}, {:sweet_xml, "~> 0.6.6"}, - {:earmark, "1.4.15"}, + {:earmark, "~> 1.4.15"}, {:bbcode_pleroma, "~> 0.2.0"}, {:crypt, - git: "https://git.pleroma.social/pleroma/elixir-libraries/crypt.git", - ref: "cf2aa3f11632e8b0634810a15b3e612c7526f6a3"}, + git: "https://github.com/msantos/crypt.git", + ref: "f75cd55325e33cbea198fb41fe41871392f8fb76"}, {:cors_plug, "~> 2.0"}, {:web_push_encryption, git: "https://github.com/lanodan/elixir-web-push-encryption.git", branch: "bugfix/otp-24"}, @@ -158,7 +159,7 @@ defmodule Pleroma.Mixfile do {:timex, "~> 3.6"}, {:ueberauth, "~> 0.4"}, {:linkify, "~> 0.5.1"}, - {:http_signatures, "~> 0.1.0"}, + {:http_signatures, "~> 0.1.1"}, {:telemetry, "~> 0.3"}, {:poolboy, "~> 1.5"}, {:prometheus, "~> 4.6"}, @@ -197,6 +198,8 @@ defmodule Pleroma.Mixfile do ref: "289cda1b6d0d70ccb2ba508a2b0bd24638db2880"}, {:eblurhash, "~> 1.1.0"}, {:open_api_spex, "~> 3.10"}, + {:phoenix_live_dashboard, "~> 0.6.2"}, + {:ecto_psql_extras, "~> 0.6"}, # indirect dependency version override {:plug, "~> 1.10.4", override: true}, @@ -208,7 +211,7 @@ defmodule Pleroma.Mixfile do {:mock, "~> 0.3.5", only: :test}, # temporary downgrade for excoveralls, hackney until hackney max_connections bug will be fixed {:excoveralls, "0.12.3", only: :test}, - {:hackney, "~> 1.17.0", override: true}, + {:hackney, "~> 1.18.0", override: true}, {:mox, "~> 1.0", only: :test}, {:websocket_client, git: "https://github.com/jeremyong/websocket_client.git", only: :test} ] ++ oauth_deps() @@ -11,7 +11,7 @@ "calendar": {:hex, :calendar, "1.0.0", "f52073a708528482ec33d0a171954ca610fe2bd28f1e871f247dc7f1565fa807", [:mix], [{:tzdata, "~> 0.5.20 or ~> 0.1.201603 or ~> 1.0", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "990e9581920c82912a5ee50e62ff5ef96da6b15949a2ee4734f935fdef0f0a6f"}, "captcha": {:git, "https://git.pleroma.social/pleroma/elixir-libraries/elixir-captcha.git", "e0f16822d578866e186a0974d65ad58cddc1e2ab", [ref: "e0f16822d578866e186a0974d65ad58cddc1e2ab"]}, "castore": {:hex, :castore, "0.1.10", "b01a007416a0ae4188e70b3b306236021b16c11474038ead7aff79dd75538c23", [:mix], [], "hexpm", "a48314e0cb45682db2ea27b8ebfa11bd6fa0a6e21a65e5772ad83ca136ff2665"}, - "certifi": {:hex, :certifi, "2.6.1", "dbab8e5e155a0763eea978c913ca280a6b544bfa115633fa20249c3d396d9493", [:rebar3], [], "hexpm", "524c97b4991b3849dd5c17a631223896272c6b0af446778ba4675a1dff53bb7e"}, + "certifi": {:hex, :certifi, "2.8.0", "d4fb0a6bb20b7c9c3643e22507e42f356ac090a1dcea9ab99e27e0376d695eba", [:rebar3], [], "hexpm", "6ac7efc1c6f8600b08d625292d4bbf584e14847ce1b6b5c44d983d273e1097ea"}, "combine": {:hex, :combine, "0.10.0", "eff8224eeb56498a2af13011d142c5e7997a80c8f5b97c499f84c841032e429f", [:mix], [], "hexpm", "1b1dbc1790073076580d0d1d64e42eae2366583e7aecd455d1215b0d16f2451b"}, "comeonin": {:hex, :comeonin, "5.3.2", "5c2f893d05c56ae3f5e24c1b983c2d5dfb88c6d979c9287a76a7feb1e1d8d646", [:mix], [], "hexpm", "d0993402844c49539aeadb3fe46a3c9bd190f1ecf86b6f9ebd71957534c95f04"}, "concurrent_limiter": {:git, "https://git.pleroma.social/pleroma/elixir-libraries/concurrent_limiter.git", "d81be41024569330f296fc472e24198d7499ba78", [ref: "d81be41024569330f296fc472e24198d7499ba78"]}, @@ -22,16 +22,17 @@ "cowlib": {:hex, :cowlib, "2.11.0", "0b9ff9c346629256c42ebe1eeb769a83c6cb771a6ee5960bd110ab0b9b872063", [:make, :rebar3], [], "hexpm", "2b3e9da0b21c4565751a6d4901c20d1b4cc25cbb7fd50d91d2ab6dd287bc86a9"}, "credo": {:hex, :credo, "1.5.5", "e8f422026f553bc3bebb81c8e8bf1932f498ca03339856c7fec63d3faac8424b", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "dd8623ab7091956a855dc9f3062486add9c52d310dfd62748779c4315d8247de"}, "crontab": {:hex, :crontab, "1.1.8", "2ce0e74777dfcadb28a1debbea707e58b879e6aa0ffbf9c9bb540887bce43617", [:mix], [{:ecto, "~> 1.0 or ~> 2.0 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}], "hexpm"}, - "crypt": {:git, "https://git.pleroma.social/pleroma/elixir-libraries/crypt.git", "cf2aa3f11632e8b0634810a15b3e612c7526f6a3", [ref: "cf2aa3f11632e8b0634810a15b3e612c7526f6a3"]}, + "crypt": {:git, "https://github.com/msantos/crypt.git", "f75cd55325e33cbea198fb41fe41871392f8fb76", [ref: "f75cd55325e33cbea198fb41fe41871392f8fb76"]}, "custom_base": {:hex, :custom_base, "0.2.1", "4a832a42ea0552299d81652aa0b1f775d462175293e99dfbe4d7dbaab785a706", [:mix], [], "hexpm", "8df019facc5ec9603e94f7270f1ac73ddf339f56ade76a721eaa57c1493ba463"}, "db_connection": {:hex, :db_connection, "2.4.0", "d04b1b73795dae60cead94189f1b8a51cc9e1f911c234cc23074017c43c031e5", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ad416c21ad9f61b3103d254a71b63696ecadb6a917b36f563921e0de00d7d7c8"}, "decimal": {:hex, :decimal, "2.0.0", "a78296e617b0f5dd4c6caf57c714431347912ffb1d0842e998e9792b5642d697", [:mix], [], "hexpm", "34666e9c55dea81013e77d9d87370fe6cb6291d1ef32f46a1600230b1d44f577"}, "deep_merge": {:hex, :deep_merge, "1.0.0", "b4aa1a0d1acac393bdf38b2291af38cb1d4a52806cf7a4906f718e1feb5ee961", [:mix], [], "hexpm", "ce708e5f094b9cd4e8f2be4f00d2f4250c4095be93f8cd6d018c753894885430"}, - "earmark": {:hex, :earmark, "1.4.15", "2c7f924bf495ec1f65bd144b355d0949a05a254d0ec561740308a54946a67888", [:mix], [{:earmark_parser, ">= 1.4.13", [hex: :earmark_parser, repo: "hexpm", optional: false]}], "hexpm", "3b1209b85bc9f3586f370f7c363f6533788fb4e51db23aa79565875e7f9999ee"}, - "earmark_parser": {:hex, :earmark_parser, "1.4.13", "0c98163e7d04a15feb62000e1a891489feb29f3d10cb57d4f845c405852bbef8", [:mix], [], "hexpm", "d602c26af3a0af43d2f2645613f65841657ad6efc9f0e361c3b6c06b578214ba"}, + "earmark": {:hex, :earmark, "1.4.18", "618c4ff1563450d1832b7fb41dc6755e470f91a6fd4c70f350a58b14f64a7db8", [:mix], [{:earmark_parser, ">= 1.4.17", [hex: :earmark_parser, repo: "hexpm", optional: false]}], "hexpm", "57ac3b6da3958ed09c669a9b159e86377fcccda56bacde8a209fa4dcdef52560"}, + "earmark_parser": {:hex, :earmark_parser, "1.4.17", "6f3c7e94170377ba45241d394389e800fb15adc5de51d0a3cd52ae766aafd63f", [:mix], [], "hexpm", "f93ac89c9feca61c165b264b5837bf82344d13bebc634cd575cb711e2e342023"}, "eblurhash": {:hex, :eblurhash, "1.1.0", "e10ccae762598507ebfacf0b645ed49520f2afa3e7e9943e73a91117dffce415", [:rebar3], [], "hexpm", "2e6b889d09fddd374e3c5ac57c486138768763264e99ac1074ae5fa7fc9ab51d"}, "ecto": {:hex, :ecto, "3.6.2", "efdf52acfc4ce29249bab5417415bd50abd62db7b0603b8bab0d7b996548c2bc", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "efad6dfb04e6f986b8a3047822b0f826d9affe8e4ebdd2aeedbfcb14fd48884e"}, "ecto_enum": {:hex, :ecto_enum, "1.4.0", "d14b00e04b974afc69c251632d1e49594d899067ee2b376277efd8233027aec8", [:mix], [{:ecto, ">= 3.0.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:ecto_sql, "> 3.0.0", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:mariaex, ">= 0.0.0", [hex: :mariaex, repo: "hexpm", optional: true]}, {:postgrex, ">= 0.0.0", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm", "8fb55c087181c2b15eee406519dc22578fa60dd82c088be376d0010172764ee4"}, + "ecto_psql_extras": {:hex, :ecto_psql_extras, "0.7.4", "5d43fd088d39a158c860b17e8d210669587f63ec89ea122a4654861c8c6e2db4", [:mix], [{:ecto_sql, "~> 3.4", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:postgrex, ">= 0.15.7", [hex: :postgrex, repo: "hexpm", optional: false]}, {:table_rex, "~> 3.1.1", [hex: :table_rex, repo: "hexpm", optional: false]}], "hexpm", "311db02f1b772e3d0dc7f56a05044b5e1499d78ed6abf38885e1ca70059449e5"}, "ecto_sql": {:hex, :ecto_sql, "3.6.2", "9526b5f691701a5181427634c30655ac33d11e17e4069eff3ae1176c764e0ba3", [:mix], [{:db_connection, "~> 2.2", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.6.2", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.4.0 or ~> 0.5.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.15.0 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "5ec9d7e6f742ea39b63aceaea9ac1d1773d574ea40df5a53ef8afbd9242fdb6b"}, "eimp": {:hex, :eimp, "1.0.14", "fc297f0c7e2700457a95a60c7010a5f1dcb768a083b6d53f49cd94ab95a28f22", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "501133f3112079b92d9e22da8b88bf4f0e13d4d67ae9c15c42c30bd25ceb83b6"}, "elixir_make": {:hex, :elixir_make, "0.6.2", "7dffacd77dec4c37b39af867cedaabb0b59f6a871f89722c25b28fcd4bd70530", [:mix], [], "hexpm", "03e49eadda22526a7e5279d53321d1cced6552f344ba4e03e619063de75348d9"}, @@ -55,10 +56,10 @@ "gen_state_machine": {:hex, :gen_state_machine, "2.0.5", "9ac15ec6e66acac994cc442dcc2c6f9796cf380ec4b08267223014be1c728a95", [:mix], [], "hexpm"}, "gettext": {:hex, :gettext, "0.18.2", "7df3ea191bb56c0309c00a783334b288d08a879f53a7014341284635850a6e55", [:mix], [], "hexpm", "f9f537b13d4fdd30f3039d33cb80144c3aa1f8d9698e47d7bcbcc8df93b1f5c5"}, "gun": {:hex, :gun, "2.0.0-rc.2", "7c489a32dedccb77b6e82d1f3c5a7dadfbfa004ec14e322cdb5e579c438632d2", [:make, :rebar3], [{:cowlib, "2.11.0", [hex: :cowlib, repo: "hexpm", optional: false]}], "hexpm", "6b9d1eae146410d727140dbf8b404b9631302ecc2066d1d12f22097ad7d254fc"}, - "hackney": {:hex, :hackney, "1.17.4", "99da4674592504d3fb0cfef0db84c3ba02b4508bae2dff8c0108baa0d6e0977c", [:rebar3], [{:certifi, "~>2.6.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~>6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~>1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.3.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~>1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "de16ff4996556c8548d512f4dbe22dd58a587bf3332e7fd362430a7ef3986b16"}, + "hackney": {:hex, :hackney, "1.18.0", "c4443d960bb9fba6d01161d01cd81173089686717d9490e5d3606644c48d121f", [:rebar3], [{:certifi, "~>2.8.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~>6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~>1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.3.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~>1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "9afcda620704d720db8c6a3123e9848d09c87586dc1c10479c42627b905b5c5e"}, "html_entities": {:hex, :html_entities, "0.5.2", "9e47e70598da7de2a9ff6af8758399251db6dbb7eebe2b013f2bbd2515895c3c", [:mix], [], "hexpm", "c53ba390403485615623b9531e97696f076ed415e8d8058b1dbaa28181f4fdcc"}, "html_sanitize_ex": {:hex, :html_sanitize_ex, "1.3.0", "f005ad692b717691203f940c686208aa3d8ffd9dd4bb3699240096a51fa9564e", [:mix], [{:mochiweb, "~> 2.15", [hex: :mochiweb, repo: "hexpm", optional: false]}], "hexpm"}, - "http_signatures": {:hex, :http_signatures, "0.1.0", "4e4b501a936dbf4cb5222597038a89ea10781776770d2e185849fa829686b34c", [:mix], [], "hexpm", "f8a7b3731e3fd17d38fa6e343fcad7b03d6874a3b0a108c8568a71ed9c2cf824"}, + "http_signatures": {:hex, :http_signatures, "0.1.1", "ca7ebc1b61542b163644c8c3b1f0e0f41037d35f2395940d3c6c7deceab41fd8", [:mix], [], "hexpm", "cc3b8a007322cc7b624c0c15eec49ee58ac977254ff529a3c482f681465942a3"}, "httpoison": {:hex, :httpoison, "1.8.0", "6b85dea15820b7804ef607ff78406ab449dd78bed923a49c7160e1886e987a3d", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "28089eaa98cf90c66265b6b5ad87c59a3729bea2e74e9d08f9b51eb9729b3c3a"}, "idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"}, "inet_cidr": {:hex, :inet_cidr, "1.0.4", "a05744ab7c221ca8e395c926c3919a821eb512e8f36547c062f62c4ca0cf3d6e", [:mix], [], "hexpm", "64a2d30189704ae41ca7dbdd587f5291db5d1dda1414e0774c29ffc81088c1bc"}, @@ -78,7 +79,7 @@ "mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"}, "mochiweb": {:hex, :mochiweb, "2.18.0", "eb55f1db3e6e960fac4e6db4e2db9ec3602cc9f30b86cd1481d56545c3145d2e", [:rebar3], [], "hexpm"}, "mock": {:hex, :mock, "0.3.7", "75b3bbf1466d7e486ea2052a73c6e062c6256fb429d6797999ab02fa32f29e03", [:mix], [{:meck, "~> 0.9.2", [hex: :meck, repo: "hexpm", optional: false]}], "hexpm", "4da49a4609e41fd99b7836945c26f373623ea968cfb6282742bcb94440cf7e5c"}, - "mogrify": {:hex, :mogrify, "0.7.4", "9b2496dde44b1ce12676f85d7dc531900939e6367bc537c7243a1b089435b32d", [:mix], [], "hexpm", "50d79e337fba6bc95bfbef918058c90f50b17eed9537771e61d4619488f099c3"}, + "mogrify": {:hex, :mogrify, "0.9.1", "a26f107c4987477769f272bd0f7e3ac4b7b75b11ba597fd001b877beffa9c068", [:mix], [], "hexpm", "134edf189337d2125c0948bf0c228fdeef975c594317452d536224069a5b7f05"}, "mox": {:hex, :mox, "1.0.0", "4b3c7005173f47ff30641ba044eb0fe67287743eec9bd9545e37f3002b0a9f8b", [:mix], [], "hexpm", "201b0a20b7abdaaab083e9cf97884950f8a30a1350a1da403b3145e213c6f4df"}, "myhtmlex": {:git, "https://git.pleroma.social/pleroma/myhtmlex.git", "ad0097e2f61d4953bfef20fb6abddf23b87111e6", [ref: "ad0097e2f61d4953bfef20fb6abddf23b87111e6", submodules: true]}, "nimble_parsec": {:hex, :nimble_parsec, "0.5.0", "90e2eca3d0266e5c53f8fbe0079694740b9c91b6747f2b7e3c5d21966bba8300", [:mix], [], "hexpm", "5c040b8469c1ff1b10093d3186e2e10dbe483cd73d79ec017993fb3985b8a9b3"}, @@ -91,7 +92,9 @@ "pbkdf2_elixir": {:hex, :pbkdf2_elixir, "1.2.1", "9cbe354b58121075bd20eb83076900a3832324b7dd171a6895fab57b6bb2752c", [:mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}], "hexpm", "d3b40a4a4630f0b442f19eca891fcfeeee4c40871936fed2f68e1c4faa30481f"}, "phoenix": {:hex, :phoenix, "1.5.9", "a6368d36cfd59d917b37c44386e01315bc89f7609a10a45a22f47c007edf2597", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_html, "~> 2.13 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.10", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.2", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.1.2 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7e4bce20a67c012f1fbb0af90e5da49fa7bf0d34e3a067795703b74aef75427d"}, "phoenix_ecto": {:hex, :phoenix_ecto, "4.2.1", "13f124cf0a3ce0f1948cf24654c7b9f2347169ff75c1123f44674afee6af3b03", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 2.15", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "478a1bae899cac0a6e02be1deec7e2944b7754c04e7d4107fc5a517f877743c0"}, - "phoenix_html": {:hex, :phoenix_html, "2.14.3", "51f720d0d543e4e157ff06b65de38e13303d5778a7919bcc696599e5934271b8", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "efd697a7fff35a13eeeb6b43db884705cba353a1a41d127d118fda5f90c8e80f"}, + "phoenix_html": {:hex, :phoenix_html, "3.1.0", "0b499df05aad27160d697a9362f0e89fa0e24d3c7a9065c2bd9d38b4d1416c09", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "0c0a98a2cefa63433657983a2a594c7dee5927e4391e0f1bfd3a151d1def33fc"}, + "phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.6.2", "0769470265eb13af01b5001b29cb935f4710d6adaa1ffc18417a570a337a2f0f", [:mix], [{:ecto, "~> 3.6.2 or ~> 3.7", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_mysql_extras, "~> 0.3", [hex: :ecto_mysql_extras, repo: "hexpm", optional: true]}, {:ecto_psql_extras, "~> 0.7", [hex: :ecto_psql_extras, repo: "hexpm", optional: true]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.17.1", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "5bc6c6b38a2ca8b5020b442322fcee6afd5e641637a0b1fb059d4bd89bc58e7b"}, + "phoenix_live_view": {:hex, :phoenix_live_view, "0.17.5", "63f52a6f9f6983f04e424586ff897c016ecc5e4f8d1e2c22c2887af1c57215d8", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.5.9 or ~> 1.6.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.1", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c5586e6a3d4df71b8214c769d4f5eb8ece2b4001711a7ca0f97323c36958b0e3"}, "phoenix_pubsub": {:hex, :phoenix_pubsub, "2.0.0", "a1ae76717bb168cdeb10ec9d92d1480fec99e3080f011402c0a2d68d47395ffb", [:mix], [], "hexpm", "c52d948c4f261577b9c6fa804be91884b381a7f8f18450c5045975435350f771"}, "phoenix_swoosh": {:hex, :phoenix_swoosh, "0.3.3", "039435dd975f7e55953525b88f1d596f26c6141412584c16f4db109708a8ee68", [:mix], [{:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:swoosh, "~> 1.0", [hex: :swoosh, repo: "hexpm", optional: false]}], "hexpm", "4a540cea32e05356541737033d666ee7fea7700eb2101bf76783adbfe06601cd"}, "plug": {:hex, :plug, "1.10.4", "41eba7d1a2d671faaf531fa867645bd5a3dce0957d8e2a3f398ccff7d2ef017f", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ad1e233fe73d2eec56616568d260777b67f53148a999dc2d048f4eb9778fe4a0"}, @@ -117,7 +120,9 @@ "sweet_xml": {:hex, :sweet_xml, "0.6.6", "fc3e91ec5dd7c787b6195757fbcf0abc670cee1e4172687b45183032221b66b8", [:mix], [], "hexpm", "2e1ec458f892ffa81f9f8386e3f35a1af6db7a7a37748a64478f13163a1f3573"}, "swoosh": {:hex, :swoosh, "1.3.11", "34f79c57f19892b43bd2168de9ff5de478a721a26328ef59567aad4243e7a77b", [:mix], [{:cowboy, "~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:finch, "~> 0.6", [hex: :finch, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.13 or ~> 1.0", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mail, "~> 0.2", [hex: :mail, repo: "hexpm", optional: true]}, {:mime, "~> 1.1", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}], "hexpm", "f1e2a048db454f9982b9cf840f75e7399dd48be31ecc2a7dc10012a803b913af"}, "syslog": {:hex, :syslog, "1.1.0", "6419a232bea84f07b56dc575225007ffe34d9fdc91abe6f1b2f254fd71d8efc2", [:rebar3], [], "hexpm", "4c6a41373c7e20587be33ef841d3de6f3beba08519809329ecc4d27b15b659e1"}, + "table_rex": {:hex, :table_rex, "3.1.1", "0c67164d1714b5e806d5067c1e96ff098ba7ae79413cc075973e17c38a587caa", [:mix], [], "hexpm", "678a23aba4d670419c23c17790f9dcd635a4a89022040df7d5d772cb21012490"}, "telemetry": {:hex, :telemetry, "0.4.3", "a06428a514bdbc63293cd9a6263aad00ddeb66f608163bdec7c8995784080818", [:rebar3], [], "hexpm", "eb72b8365ffda5bed68a620d1da88525e326cb82a75ee61354fc24b844768041"}, + "telemetry_metrics": {:hex, :telemetry_metrics, "0.6.1", "315d9163a1d4660aedc3fee73f33f1d355dcc76c5c3ab3d59e76e3edf80eef1f", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7be9e0871c41732c233be71e4be11b96e56177bf15dde64a8ac9ce72ac9834c6"}, "tesla": {:hex, :tesla, "1.4.1", "ff855f1cac121e0d16281b49e8f066c4a0d89965f98864515713878cca849ac8", [: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", [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", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "95f5de35922c8c4b3945bee7406f66eb680b0955232f78f5fb7e853aa1ce201a"}, "timex": {:hex, :timex, "3.7.5", "3eca56e23bfa4e0848f0b0a29a92fa20af251a975116c6d504966e8a90516dfd", [: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", "a15608dca680f2ef663d71c95842c67f0af08a0f3b1d00e17bbd22872e2874e4"}, "trailing_format_plug": {:hex, :trailing_format_plug, "0.0.7", "64b877f912cf7273bed03379936df39894149e35137ac9509117e59866e10e45", [:mix], [{:plug, "> 0.12.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "bd4fde4c15f3e993a999e019d64347489b91b7a9096af68b2bdadd192afa693f"}, diff --git a/priv/gettext/id/LC_MESSAGES/errors.po b/priv/gettext/id/LC_MESSAGES/errors.po new file mode 100644 index 000000000..bc98273be --- /dev/null +++ b/priv/gettext/id/LC_MESSAGES/errors.po @@ -0,0 +1,580 @@ +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-08-15 15:40+0000\n" +"PO-Revision-Date: 2021-09-03 06:45+0000\n" +"Last-Translator: @liimee <alt3753.7@gmail.com>\n" +"Language-Team: Indonesian <https://translate.pleroma.social/projects/pleroma/" +"pleroma/id/>\n" +"Language: id\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" + +## This file is a PO Template file. +## +## `msgid`s here are often extracted from source code. +## Add new translations manually only if they're dynamic +## translations that can't be statically extracted. +## +## Run `mix gettext.extract` to bring this file up to +## date. Leave `msgstr`s empty as changing them here as no +## effect: edit them in PO (`.po`) files instead. +## From Ecto.Changeset.cast/4 +msgid "can't be blank" +msgstr "tidak boleh kosong" + +## From Ecto.Changeset.unique_constraint/3 +msgid "has already been taken" +msgstr "sudah diambil" + +## From Ecto.Changeset.put_change/3 +msgid "is invalid" +msgstr "tidak valid" + +## From Ecto.Changeset.validate_format/3 +msgid "has invalid format" +msgstr "memiliki format yang tidak valid" + +## From Ecto.Changeset.validate_subset/3 +msgid "has an invalid entry" +msgstr "" + +## From Ecto.Changeset.validate_exclusion/3 +msgid "is reserved" +msgstr "" + +## From Ecto.Changeset.validate_confirmation/3 +msgid "does not match confirmation" +msgstr "" + +## From Ecto.Changeset.no_assoc_constraint/3 +msgid "is still associated with this entry" +msgstr "" + +msgid "are still associated with this entry" +msgstr "" + +## From Ecto.Changeset.validate_length/3 +msgid "should be %{count} character(s)" +msgid_plural "should be %{count} character(s)" +msgstr[0] "harus memiliki %{count} karakter" + +msgid "should have %{count} item(s)" +msgid_plural "should have %{count} item(s)" +msgstr[0] "harus memiliki %{count} item" + +msgid "should be at least %{count} character(s)" +msgid_plural "should be at least %{count} character(s)" +msgstr[0] "harus memiliki sekurang-kurangnya %{count} karakter" + +msgid "should have at least %{count} item(s)" +msgid_plural "should have at least %{count} item(s)" +msgstr[0] "harus memiliki sekurang-kurangnya %{count} item" + +msgid "should be at most %{count} character(s)" +msgid_plural "should be at most %{count} character(s)" +msgstr[0] "" + +msgid "should have at most %{count} item(s)" +msgid_plural "should have at most %{count} item(s)" +msgstr[0] "" + +## From Ecto.Changeset.validate_number/3 +msgid "must be less than %{number}" +msgstr "harus kurang dari %{number}" + +msgid "must be greater than %{number}" +msgstr "harus lebih dari %{number}" + +msgid "must be less than or equal to %{number}" +msgstr "harus kurang dari atau sama dengan %{number}" + +msgid "must be greater than or equal to %{number}" +msgstr "harus lebih dari atau sama dengan %{number}" + +msgid "must be equal to %{number}" +msgstr "harus sama dengan %{number}" + +#: lib/pleroma/web/common_api/common_api.ex:505 +#, elixir-format +msgid "Account not found" +msgstr "Akun tidak ditemukan" + +#: lib/pleroma/web/common_api/common_api.ex:339 +#, elixir-format +msgid "Already voted" +msgstr "Sudah memilih" + +#: lib/pleroma/web/oauth/oauth_controller.ex:359 +#, elixir-format +msgid "Bad request" +msgstr "Permintaan buruk (bad request)" + +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:426 +#, elixir-format +msgid "Can't delete object" +msgstr "Tidak dapat menghapus objek" + +#: lib/pleroma/web/controller_helper.ex:105 +#: lib/pleroma/web/controller_helper.ex:111 +#, elixir-format +msgid "Can't display this activity" +msgstr "Tidak dapat menampilkan aktivitas ini" + +#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:285 +#, elixir-format +msgid "Can't find user" +msgstr "Tidak dapat mencari pengguna" + +#: lib/pleroma/web/pleroma_api/controllers/account_controller.ex:61 +#, elixir-format +msgid "Can't get favorites" +msgstr "Tidak dapat mendapatkan favorit" + +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:438 +#, elixir-format +msgid "Can't like object" +msgstr "Tidak dapat menyukai objek" + +#: lib/pleroma/web/common_api/utils.ex:563 +#, elixir-format +msgid "Cannot post an empty status without attachments" +msgstr "Tidak dapat memposting status kosong tanpa lampiran" + +#: lib/pleroma/web/common_api/utils.ex:511 +#, elixir-format +msgid "Comment must be up to %{max_size} characters" +msgstr "Komentar tidak boleh lebih dari %{max_size} karakter" + +#: lib/pleroma/config/config_db.ex:191 +#, elixir-format +msgid "Config with params %{params} not found" +msgstr "" + +#: lib/pleroma/web/common_api/common_api.ex:181 +#: lib/pleroma/web/common_api/common_api.ex:185 +#, elixir-format +msgid "Could not delete" +msgstr "Tidak dapat menghapus" + +#: lib/pleroma/web/common_api/common_api.ex:231 +#, elixir-format +msgid "Could not favorite" +msgstr "Tidak dapat memfavoritkan" + +#: lib/pleroma/web/common_api/common_api.ex:453 +#, elixir-format +msgid "Could not pin" +msgstr "Tidak dapat menyematkan" + +#: lib/pleroma/web/common_api/common_api.ex:278 +#, elixir-format +msgid "Could not unfavorite" +msgstr "" + +#: lib/pleroma/web/common_api/common_api.ex:463 +#, elixir-format +msgid "Could not unpin" +msgstr "Tidak dapat berhenti menyematkan" + +#: lib/pleroma/web/common_api/common_api.ex:216 +#, elixir-format +msgid "Could not unrepeat" +msgstr "" + +#: lib/pleroma/web/common_api/common_api.ex:512 +#: lib/pleroma/web/common_api/common_api.ex:521 +#, elixir-format +msgid "Could not update state" +msgstr "" + +#: lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:207 +#, elixir-format +msgid "Error." +msgstr "Kesalahan." + +#: lib/pleroma/web/twitter_api/twitter_api.ex:106 +#, elixir-format +msgid "Invalid CAPTCHA" +msgstr "CAPTCHA tidak valid" + +#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:116 +#: lib/pleroma/web/oauth/oauth_controller.ex:568 +#, elixir-format +msgid "Invalid credentials" +msgstr "Kredensian tidak valid" + +#: lib/pleroma/plugs/ensure_authenticated_plug.ex:38 +#, elixir-format +msgid "Invalid credentials." +msgstr "Kredensial tidak valid." + +#: lib/pleroma/web/common_api/common_api.ex:355 +#, elixir-format +msgid "Invalid indices" +msgstr "" + +#: lib/pleroma/web/admin_api/controllers/fallback_controller.ex:29 +#, elixir-format +msgid "Invalid parameters" +msgstr "Parameter tidak valid" + +#: lib/pleroma/web/common_api/utils.ex:414 +#, elixir-format +msgid "Invalid password." +msgstr "Kata sandi tidak valid." + +#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:220 +#, elixir-format +msgid "Invalid request" +msgstr "Permintaan tidak valid" + +#: lib/pleroma/web/twitter_api/twitter_api.ex:109 +#, elixir-format +msgid "Kocaptcha service unavailable" +msgstr "Layanan Kocaptcha tidak tersedia" + +#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:112 +#, elixir-format +msgid "Missing parameters" +msgstr "Parameter kurang" + +#: lib/pleroma/web/common_api/utils.ex:547 +#, elixir-format +msgid "No such conversation" +msgstr "Tidak ada percakapan ini" + +#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:388 +#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:414 lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:456 +#, elixir-format +msgid "No such permission_group" +msgstr "" + +#: lib/pleroma/plugs/uploaded_media.ex:84 +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:486 lib/pleroma/web/admin_api/controllers/fallback_controller.ex:11 +#: lib/pleroma/web/feed/user_controller.ex:71 lib/pleroma/web/ostatus/ostatus_controller.ex:143 +#, elixir-format +msgid "Not found" +msgstr "Tidak ditemukan" + +#: lib/pleroma/web/common_api/common_api.ex:331 +#, elixir-format +msgid "Poll's author can't vote" +msgstr "Pembuat japat tidak boleh memilih" + +#: 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 +#: lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:50 lib/pleroma/web/mastodon_api/controllers/status_controller.ex:306 +#: lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex:71 +#, elixir-format +msgid "Record not found" +msgstr "" + +#: lib/pleroma/web/admin_api/controllers/fallback_controller.ex:35 +#: lib/pleroma/web/feed/user_controller.ex:77 lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:36 +#: lib/pleroma/web/ostatus/ostatus_controller.ex:149 +#, elixir-format +msgid "Something went wrong" +msgstr "Sesuatu yang salah terjadi" + +#: lib/pleroma/web/common_api/activity_draft.ex:107 +#, elixir-format +msgid "The message visibility must be direct" +msgstr "Visibilitas pesan harus langsung" + +#: lib/pleroma/web/common_api/utils.ex:573 +#, elixir-format +msgid "The status is over the character limit" +msgstr "Status lebih dari batas karakter" + +#: lib/pleroma/plugs/ensure_public_or_authenticated_plug.ex:31 +#, elixir-format +msgid "This resource requires authentication." +msgstr "" + +#: lib/pleroma/plugs/rate_limiter/rate_limiter.ex:206 +#, elixir-format +msgid "Throttled" +msgstr "" + +#: lib/pleroma/web/common_api/common_api.ex:356 +#, elixir-format +msgid "Too many choices" +msgstr "Terlalu banyak pilihan" + +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:443 +#, elixir-format +msgid "Unhandled activity type" +msgstr "" + +#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:485 +#, elixir-format +msgid "You can't revoke your own admin status." +msgstr "" + +#: lib/pleroma/web/oauth/oauth_controller.ex:221 +#: lib/pleroma/web/oauth/oauth_controller.ex:308 +#, elixir-format +msgid "Your account is currently disabled" +msgstr "Akun Anda saat ini dinonaktifkan" + +#: lib/pleroma/web/oauth/oauth_controller.ex:183 +#: lib/pleroma/web/oauth/oauth_controller.ex:331 +#, elixir-format +msgid "Your login is missing a confirmed e-mail address" +msgstr "" + +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:390 +#, elixir-format +msgid "can't read inbox of %{nickname} as %{as_nickname}" +msgstr "" + +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:473 +#, elixir-format +msgid "can't update outbox of %{nickname} as %{as_nickname}" +msgstr "" + +#: lib/pleroma/web/common_api/common_api.ex:471 +#, elixir-format +msgid "conversation is already muted" +msgstr "percakapan sudah dibisukan" + +#: 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 "kesalahan" + +#: lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex:32 +#, elixir-format +msgid "mascots can only be images" +msgstr "maskot hanya dapat berbentuk gambar" + +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:62 +#, elixir-format +msgid "not found" +msgstr "tidak ditemukan" + +#: lib/pleroma/web/oauth/oauth_controller.ex:394 +#, elixir-format +msgid "Bad OAuth request." +msgstr "Permintaan OAuth buruk." + +#: lib/pleroma/web/twitter_api/twitter_api.ex:115 +#, elixir-format +msgid "CAPTCHA already used" +msgstr "CAPTCHA sudah digunakan" + +#: lib/pleroma/web/twitter_api/twitter_api.ex:112 +#, elixir-format +msgid "CAPTCHA expired" +msgstr "CAPTCHA kedaluwarsa" + +#: lib/pleroma/plugs/uploaded_media.ex:57 +#, elixir-format +msgid "Failed" +msgstr "Gagal" + +#: lib/pleroma/web/oauth/oauth_controller.ex:410 +#, elixir-format +msgid "Failed to authenticate: %{message}." +msgstr "Gagal mengotentikasi: %{message}." + +#: lib/pleroma/web/oauth/oauth_controller.ex:441 +#, elixir-format +msgid "Failed to set up user account." +msgstr "Gagal menyiapkan akun pengguna." + +#: lib/pleroma/plugs/oauth_scopes_plug.ex:38 +#, elixir-format +msgid "Insufficient permissions: %{permissions}." +msgstr "" + +#: lib/pleroma/plugs/uploaded_media.ex:104 +#, elixir-format +msgid "Internal Error" +msgstr "Kesalahan Internal" + +#: lib/pleroma/web/oauth/fallback_controller.ex:22 +#: lib/pleroma/web/oauth/fallback_controller.ex:29 +#, elixir-format +msgid "Invalid Username/Password" +msgstr "Nama Pengguna/Kata Sandi Tidak Valid" + +#: lib/pleroma/web/twitter_api/twitter_api.ex:118 +#, elixir-format +msgid "Invalid answer data" +msgstr "" + +#: lib/pleroma/web/nodeinfo/nodeinfo_controller.ex:33 +#, elixir-format +msgid "Nodeinfo schema version not handled" +msgstr "" + +#: lib/pleroma/web/oauth/oauth_controller.ex:172 +#, elixir-format +msgid "This action is outside the authorized scopes" +msgstr "" + +#: lib/pleroma/web/oauth/fallback_controller.ex:14 +#, elixir-format +msgid "Unknown error, please check the details and try again." +msgstr "Kesalahan tidak dikenal, harap periksa keterangannya dan coba lagi." + +#: lib/pleroma/web/oauth/oauth_controller.ex:119 +#: lib/pleroma/web/oauth/oauth_controller.ex:158 +#, elixir-format +msgid "Unlisted redirect_uri." +msgstr "" + +#: lib/pleroma/web/oauth/oauth_controller.ex:390 +#, elixir-format +msgid "Unsupported OAuth provider: %{provider}." +msgstr "Penyedia OAuth tidak didukung: %{provider}." + +#: lib/pleroma/uploaders/uploader.ex:72 +#, elixir-format +msgid "Uploader callback timeout" +msgstr "" + +#: lib/pleroma/web/uploader_controller.ex:23 +#, elixir-format +msgid "bad request" +msgstr "permintaan buruk (bad request)" + +#: lib/pleroma/web/twitter_api/twitter_api.ex:103 +#, elixir-format +msgid "CAPTCHA Error" +msgstr "Kesalahan CAPTCHA" + +#: lib/pleroma/web/common_api/common_api.ex:290 +#, elixir-format +msgid "Could not add reaction emoji" +msgstr "Tidak dapat menambahkan emoji reaksi" + +#: lib/pleroma/web/common_api/common_api.ex:301 +#, elixir-format +msgid "Could not remove reaction emoji" +msgstr "Tidak dapat menghapus reaksi emoji" + +#: lib/pleroma/web/twitter_api/twitter_api.ex:129 +#, elixir-format +msgid "Invalid CAPTCHA (Missing parameter: %{name})" +msgstr "CAPTCHA Tidak Valid (Parameter kurang: %{name})" + +#: lib/pleroma/web/mastodon_api/controllers/list_controller.ex:92 +#, elixir-format +msgid "List not found" +msgstr "" + +#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:123 +#, elixir-format +msgid "Missing parameter: %{name}" +msgstr "Parameter kurang: %{name}" + +#: lib/pleroma/web/oauth/oauth_controller.ex:210 +#: lib/pleroma/web/oauth/oauth_controller.ex:321 +#, elixir-format +msgid "Password reset is required" +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 +#: lib/pleroma/web/admin_api/controllers/config_controller.ex:6 lib/pleroma/web/admin_api/controllers/fallback_controller.ex:6 +#: lib/pleroma/web/admin_api/controllers/invite_controller.ex:6 lib/pleroma/web/admin_api/controllers/media_proxy_cache_controller.ex:6 +#: lib/pleroma/web/admin_api/controllers/oauth_app_controller.ex:6 lib/pleroma/web/admin_api/controllers/relay_controller.ex:6 +#: lib/pleroma/web/admin_api/controllers/report_controller.ex:6 lib/pleroma/web/admin_api/controllers/status_controller.ex:6 +#: lib/pleroma/web/controller_helper.ex:6 lib/pleroma/web/embed_controller.ex:6 +#: lib/pleroma/web/fallback_redirect_controller.ex:6 lib/pleroma/web/feed/tag_controller.ex:6 +#: lib/pleroma/web/feed/user_controller.ex:6 lib/pleroma/web/mailer/subscription_controller.ex:2 +#: lib/pleroma/web/masto_fe_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/account_controller.ex:6 +#: lib/pleroma/web/mastodon_api/controllers/app_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/auth_controller.ex:6 +#: lib/pleroma/web/mastodon_api/controllers/conversation_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/custom_emoji_controller.ex:6 +#: lib/pleroma/web/mastodon_api/controllers/domain_block_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:6 +#: lib/pleroma/web/mastodon_api/controllers/filter_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/follow_request_controller.ex:6 +#: lib/pleroma/web/mastodon_api/controllers/instance_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/list_controller.ex:6 +#: lib/pleroma/web/mastodon_api/controllers/marker_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex:14 +#: lib/pleroma/web/mastodon_api/controllers/media_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/notification_controller.ex:6 +#: lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/report_controller.ex:8 +#: lib/pleroma/web/mastodon_api/controllers/scheduled_activity_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/search_controller.ex:6 +#: lib/pleroma/web/mastodon_api/controllers/status_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex:7 +#: lib/pleroma/web/mastodon_api/controllers/suggestion_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:6 +#: lib/pleroma/web/media_proxy/media_proxy_controller.ex:6 lib/pleroma/web/mongooseim/mongoose_im_controller.ex:6 +#: lib/pleroma/web/nodeinfo/nodeinfo_controller.ex:6 lib/pleroma/web/oauth/fallback_controller.ex:6 +#: lib/pleroma/web/oauth/mfa_controller.ex:10 lib/pleroma/web/oauth/oauth_controller.ex:6 +#: lib/pleroma/web/ostatus/ostatus_controller.ex:6 lib/pleroma/web/pleroma_api/controllers/account_controller.ex:6 +#: lib/pleroma/web/pleroma_api/controllers/chat_controller.ex:5 lib/pleroma/web/pleroma_api/controllers/conversation_controller.ex:6 +#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:2 lib/pleroma/web/pleroma_api/controllers/emoji_reaction_controller.ex:6 +#: lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex:6 lib/pleroma/web/pleroma_api/controllers/notification_controller.ex:6 +#: lib/pleroma/web/pleroma_api/controllers/scrobble_controller.ex:6 +#: lib/pleroma/web/pleroma_api/controllers/two_factor_authentication_controller.ex:7 lib/pleroma/web/static_fe/static_fe_controller.ex:6 +#: lib/pleroma/web/twitter_api/controllers/password_controller.ex:10 lib/pleroma/web/twitter_api/controllers/remote_follow_controller.ex:6 +#: lib/pleroma/web/twitter_api/controllers/util_controller.ex:6 lib/pleroma/web/twitter_api/twitter_api_controller.ex:6 +#: lib/pleroma/web/uploader_controller.ex:6 lib/pleroma/web/web_finger/web_finger_controller.ex:6 +#, elixir-format +msgid "Security violation: OAuth scopes check was neither handled nor explicitly skipped." +msgstr "" + +#: lib/pleroma/plugs/ensure_authenticated_plug.ex:28 +#, elixir-format +msgid "Two-factor authentication enabled, you must use a access token." +msgstr "Otentikasi dua-faktor diaktifkan, Anda harus menggunakan token akses." + +#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:210 +#, elixir-format +msgid "Unexpected error occurred while adding file to pack." +msgstr "" + +#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:138 +#, elixir-format +msgid "Unexpected error occurred while creating pack." +msgstr "" + +#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:278 +#, elixir-format +msgid "Unexpected error occurred while removing file from pack." +msgstr "" + +#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:250 +#, elixir-format +msgid "Unexpected error occurred while updating file in pack." +msgstr "" + +#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:179 +#, elixir-format +msgid "Unexpected error occurred while updating pack metadata." +msgstr "" + +#: lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex:61 +#, elixir-format +msgid "Web push subscription is disabled on this Pleroma instance" +msgstr "" + +#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:451 +#, elixir-format +msgid "You can't revoke your own admin/moderator status." +msgstr "Anda tidak bisa mencabut status admin/moderator Anda sendiri." + +#: lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:126 +#, elixir-format +msgid "authorization required for timeline view" +msgstr "" + +#: lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:24 +#, elixir-format +msgid "Access denied" +msgstr "Akses ditolak" + +#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:282 +#, elixir-format +msgid "This API requires an authenticated user" +msgstr "" + +#: lib/pleroma/plugs/user_is_admin_plug.ex:21 +#, elixir-format +msgid "User is not an admin." +msgstr "Pengguna bukan seorang admin." diff --git a/priv/gettext/ja/LC_MESSAGES/errors.po b/priv/gettext/ja/LC_MESSAGES/errors.po new file mode 100644 index 000000000..5d9986485 --- /dev/null +++ b/priv/gettext/ja/LC_MESSAGES/errors.po @@ -0,0 +1,580 @@ +msgid "" +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" +"Language-Team: Japanese <https://translate.pleroma.social/projects/pleroma/" +"pleroma/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" + +## This file is a PO Template file. +## +## `msgid`s here are often extracted from source code. +## Add new translations manually only if they're dynamic +## translations that can't be statically extracted. +## +## Run `mix gettext.extract` to bring this file up to +## date. Leave `msgstr`s empty as changing them here as no +## effect: edit them in PO (`.po`) files instead. +## From Ecto.Changeset.cast/4 +msgid "can't be blank" +msgstr "" + +## From Ecto.Changeset.unique_constraint/3 +msgid "has already been taken" +msgstr "" + +## From Ecto.Changeset.put_change/3 +msgid "is invalid" +msgstr "" + +## From Ecto.Changeset.validate_format/3 +msgid "has invalid format" +msgstr "" + +## From Ecto.Changeset.validate_subset/3 +msgid "has an invalid entry" +msgstr "" + +## From Ecto.Changeset.validate_exclusion/3 +msgid "is reserved" +msgstr "" + +## From Ecto.Changeset.validate_confirmation/3 +msgid "does not match confirmation" +msgstr "" + +## From Ecto.Changeset.no_assoc_constraint/3 +msgid "is still associated with this entry" +msgstr "" + +msgid "are still associated with this entry" +msgstr "" + +## From Ecto.Changeset.validate_length/3 +msgid "should be %{count} character(s)" +msgid_plural "should be %{count} character(s)" +msgstr[0] "" + +msgid "should have %{count} item(s)" +msgid_plural "should have %{count} item(s)" +msgstr[0] "" + +msgid "should be at least %{count} character(s)" +msgid_plural "should be at least %{count} character(s)" +msgstr[0] "" + +msgid "should have at least %{count} item(s)" +msgid_plural "should have at least %{count} item(s)" +msgstr[0] "" + +msgid "should be at most %{count} character(s)" +msgid_plural "should be at most %{count} character(s)" +msgstr[0] "" + +msgid "should have at most %{count} item(s)" +msgid_plural "should have at most %{count} item(s)" +msgstr[0] "" + +## From Ecto.Changeset.validate_number/3 +msgid "must be less than %{number}" +msgstr "%{number}未満でなければなりません" + +msgid "must be greater than %{number}" +msgstr "%{number}より大きくなければなりません" + +msgid "must be less than or equal to %{number}" +msgstr "%{number}以下でなければなりません" + +msgid "must be greater than or equal to %{number}" +msgstr "%{number}以上でなければなりません" + +msgid "must be equal to %{number}" +msgstr "%{number}でなければなりません" + +#: lib/pleroma/web/common_api/common_api.ex:505 +#, elixir-format +msgid "Account not found" +msgstr "アカウントがありません" + +#: lib/pleroma/web/common_api/common_api.ex:339 +#, elixir-format +msgid "Already voted" +msgstr "投票済みです" + +#: lib/pleroma/web/oauth/oauth_controller.ex:359 +#, elixir-format +msgid "Bad request" +msgstr "" + +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:426 +#, elixir-format +msgid "Can't delete object" +msgstr "オブジェクトを削除できません" + +#: lib/pleroma/web/controller_helper.ex:105 +#: lib/pleroma/web/controller_helper.ex:111 +#, elixir-format +msgid "Can't display this activity" +msgstr "このアクティビティを表示できません" + +#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:285 +#, elixir-format +msgid "Can't find user" +msgstr "ユーザーが見つかりません" + +#: lib/pleroma/web/pleroma_api/controllers/account_controller.ex:61 +#, elixir-format +msgid "Can't get favorites" +msgstr "お気に入りを取得できません" + +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:438 +#, elixir-format +msgid "Can't like object" +msgstr "" + +#: lib/pleroma/web/common_api/utils.ex:563 +#, elixir-format +msgid "Cannot post an empty status without attachments" +msgstr "本文または添付ファイルを追加してください" + +#: lib/pleroma/web/common_api/utils.ex:511 +#, elixir-format +msgid "Comment must be up to %{max_size} characters" +msgstr "" + +#: lib/pleroma/config/config_db.ex:191 +#, elixir-format +msgid "Config with params %{params} not found" +msgstr "" + +#: lib/pleroma/web/common_api/common_api.ex:181 +#: lib/pleroma/web/common_api/common_api.ex:185 +#, elixir-format +msgid "Could not delete" +msgstr "削除できません" + +#: lib/pleroma/web/common_api/common_api.ex:231 +#, elixir-format +msgid "Could not favorite" +msgstr "お気に入り登録できません" + +#: lib/pleroma/web/common_api/common_api.ex:453 +#, elixir-format +msgid "Could not pin" +msgstr "ピン留めできません" + +#: lib/pleroma/web/common_api/common_api.ex:278 +#, elixir-format +msgid "Could not unfavorite" +msgstr "お気に入り解除できません" + +#: lib/pleroma/web/common_api/common_api.ex:463 +#, elixir-format +msgid "Could not unpin" +msgstr "ピン留め解除できません" + +#: lib/pleroma/web/common_api/common_api.ex:216 +#, elixir-format +msgid "Could not unrepeat" +msgstr "リピート解除できません" + +#: lib/pleroma/web/common_api/common_api.ex:512 +#: lib/pleroma/web/common_api/common_api.ex:521 +#, elixir-format +msgid "Could not update state" +msgstr "状態を更新できません" + +#: lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:207 +#, elixir-format +msgid "Error." +msgstr "エラー。" + +#: lib/pleroma/web/twitter_api/twitter_api.ex:106 +#, elixir-format +msgid "Invalid CAPTCHA" +msgstr "CAPTCHAが間違っています" + +#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:116 +#: lib/pleroma/web/oauth/oauth_controller.ex:568 +#, elixir-format +msgid "Invalid credentials" +msgstr "認証情報が間違っています" + +#: lib/pleroma/plugs/ensure_authenticated_plug.ex:38 +#, elixir-format +msgid "Invalid credentials." +msgstr "認証情報が間違っています。" + +#: lib/pleroma/web/common_api/common_api.ex:355 +#, elixir-format +msgid "Invalid indices" +msgstr "" + +#: lib/pleroma/web/admin_api/controllers/fallback_controller.ex:29 +#, elixir-format +msgid "Invalid parameters" +msgstr "" + +#: lib/pleroma/web/common_api/utils.ex:414 +#, elixir-format +msgid "Invalid password." +msgstr "" + +#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:220 +#, elixir-format +msgid "Invalid request" +msgstr "" + +#: lib/pleroma/web/twitter_api/twitter_api.ex:109 +#, elixir-format +msgid "Kocaptcha service unavailable" +msgstr "" + +#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:112 +#, elixir-format +msgid "Missing parameters" +msgstr "" + +#: lib/pleroma/web/common_api/utils.ex:547 +#, elixir-format +msgid "No such conversation" +msgstr "" + +#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:388 +#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:414 lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:456 +#, elixir-format +msgid "No such permission_group" +msgstr "" + +#: lib/pleroma/plugs/uploaded_media.ex:84 +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:486 lib/pleroma/web/admin_api/controllers/fallback_controller.ex:11 +#: lib/pleroma/web/feed/user_controller.ex:71 lib/pleroma/web/ostatus/ostatus_controller.ex:143 +#, elixir-format +msgid "Not found" +msgstr "" + +#: lib/pleroma/web/common_api/common_api.ex:331 +#, elixir-format +msgid "Poll's author can't vote" +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 +#: lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:50 lib/pleroma/web/mastodon_api/controllers/status_controller.ex:306 +#: lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex:71 +#, elixir-format +msgid "Record not found" +msgstr "" + +#: lib/pleroma/web/admin_api/controllers/fallback_controller.ex:35 +#: lib/pleroma/web/feed/user_controller.ex:77 lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:36 +#: lib/pleroma/web/ostatus/ostatus_controller.ex:149 +#, elixir-format +msgid "Something went wrong" +msgstr "" + +#: lib/pleroma/web/common_api/activity_draft.ex:107 +#, elixir-format +msgid "The message visibility must be direct" +msgstr "" + +#: lib/pleroma/web/common_api/utils.ex:573 +#, elixir-format +msgid "The status is over the character limit" +msgstr "" + +#: lib/pleroma/plugs/ensure_public_or_authenticated_plug.ex:31 +#, elixir-format +msgid "This resource requires authentication." +msgstr "" + +#: lib/pleroma/plugs/rate_limiter/rate_limiter.ex:206 +#, elixir-format +msgid "Throttled" +msgstr "" + +#: lib/pleroma/web/common_api/common_api.ex:356 +#, elixir-format +msgid "Too many choices" +msgstr "" + +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:443 +#, elixir-format +msgid "Unhandled activity type" +msgstr "" + +#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:485 +#, elixir-format +msgid "You can't revoke your own admin status." +msgstr "" + +#: lib/pleroma/web/oauth/oauth_controller.ex:221 +#: lib/pleroma/web/oauth/oauth_controller.ex:308 +#, elixir-format +msgid "Your account is currently disabled" +msgstr "" + +#: lib/pleroma/web/oauth/oauth_controller.ex:183 +#: lib/pleroma/web/oauth/oauth_controller.ex:331 +#, elixir-format +msgid "Your login is missing a confirmed e-mail address" +msgstr "" + +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:390 +#, elixir-format +msgid "can't read inbox of %{nickname} as %{as_nickname}" +msgstr "" + +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:473 +#, elixir-format +msgid "can't update outbox of %{nickname} as %{as_nickname}" +msgstr "" + +#: lib/pleroma/web/common_api/common_api.ex:471 +#, elixir-format +msgid "conversation is already muted" +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 "" + +#: lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex:32 +#, elixir-format +msgid "mascots can only be images" +msgstr "" + +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:62 +#, elixir-format +msgid "not found" +msgstr "" + +#: lib/pleroma/web/oauth/oauth_controller.ex:394 +#, elixir-format +msgid "Bad OAuth request." +msgstr "" + +#: lib/pleroma/web/twitter_api/twitter_api.ex:115 +#, elixir-format +msgid "CAPTCHA already used" +msgstr "" + +#: lib/pleroma/web/twitter_api/twitter_api.ex:112 +#, elixir-format +msgid "CAPTCHA expired" +msgstr "" + +#: lib/pleroma/plugs/uploaded_media.ex:57 +#, elixir-format +msgid "Failed" +msgstr "" + +#: lib/pleroma/web/oauth/oauth_controller.ex:410 +#, elixir-format +msgid "Failed to authenticate: %{message}." +msgstr "" + +#: lib/pleroma/web/oauth/oauth_controller.ex:441 +#, elixir-format +msgid "Failed to set up user account." +msgstr "" + +#: lib/pleroma/plugs/oauth_scopes_plug.ex:38 +#, elixir-format +msgid "Insufficient permissions: %{permissions}." +msgstr "" + +#: lib/pleroma/plugs/uploaded_media.ex:104 +#, elixir-format +msgid "Internal Error" +msgstr "" + +#: lib/pleroma/web/oauth/fallback_controller.ex:22 +#: lib/pleroma/web/oauth/fallback_controller.ex:29 +#, elixir-format +msgid "Invalid Username/Password" +msgstr "" + +#: lib/pleroma/web/twitter_api/twitter_api.ex:118 +#, elixir-format +msgid "Invalid answer data" +msgstr "" + +#: lib/pleroma/web/nodeinfo/nodeinfo_controller.ex:33 +#, elixir-format +msgid "Nodeinfo schema version not handled" +msgstr "" + +#: lib/pleroma/web/oauth/oauth_controller.ex:172 +#, elixir-format +msgid "This action is outside the authorized scopes" +msgstr "" + +#: lib/pleroma/web/oauth/fallback_controller.ex:14 +#, elixir-format +msgid "Unknown error, please check the details and try again." +msgstr "" + +#: lib/pleroma/web/oauth/oauth_controller.ex:119 +#: lib/pleroma/web/oauth/oauth_controller.ex:158 +#, elixir-format +msgid "Unlisted redirect_uri." +msgstr "" + +#: lib/pleroma/web/oauth/oauth_controller.ex:390 +#, elixir-format +msgid "Unsupported OAuth provider: %{provider}." +msgstr "" + +#: lib/pleroma/uploaders/uploader.ex:72 +#, elixir-format +msgid "Uploader callback timeout" +msgstr "" + +#: lib/pleroma/web/uploader_controller.ex:23 +#, elixir-format +msgid "bad request" +msgstr "" + +#: lib/pleroma/web/twitter_api/twitter_api.ex:103 +#, elixir-format +msgid "CAPTCHA Error" +msgstr "" + +#: lib/pleroma/web/common_api/common_api.ex:290 +#, elixir-format +msgid "Could not add reaction emoji" +msgstr "" + +#: lib/pleroma/web/common_api/common_api.ex:301 +#, elixir-format +msgid "Could not remove reaction emoji" +msgstr "" + +#: lib/pleroma/web/twitter_api/twitter_api.ex:129 +#, elixir-format +msgid "Invalid CAPTCHA (Missing parameter: %{name})" +msgstr "" + +#: lib/pleroma/web/mastodon_api/controllers/list_controller.ex:92 +#, elixir-format +msgid "List not found" +msgstr "" + +#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:123 +#, elixir-format +msgid "Missing parameter: %{name}" +msgstr "" + +#: lib/pleroma/web/oauth/oauth_controller.ex:210 +#: lib/pleroma/web/oauth/oauth_controller.ex:321 +#, elixir-format +msgid "Password reset is required" +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 +#: lib/pleroma/web/admin_api/controllers/config_controller.ex:6 lib/pleroma/web/admin_api/controllers/fallback_controller.ex:6 +#: lib/pleroma/web/admin_api/controllers/invite_controller.ex:6 lib/pleroma/web/admin_api/controllers/media_proxy_cache_controller.ex:6 +#: lib/pleroma/web/admin_api/controllers/oauth_app_controller.ex:6 lib/pleroma/web/admin_api/controllers/relay_controller.ex:6 +#: lib/pleroma/web/admin_api/controllers/report_controller.ex:6 lib/pleroma/web/admin_api/controllers/status_controller.ex:6 +#: lib/pleroma/web/controller_helper.ex:6 lib/pleroma/web/embed_controller.ex:6 +#: lib/pleroma/web/fallback_redirect_controller.ex:6 lib/pleroma/web/feed/tag_controller.ex:6 +#: lib/pleroma/web/feed/user_controller.ex:6 lib/pleroma/web/mailer/subscription_controller.ex:2 +#: lib/pleroma/web/masto_fe_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/account_controller.ex:6 +#: lib/pleroma/web/mastodon_api/controllers/app_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/auth_controller.ex:6 +#: lib/pleroma/web/mastodon_api/controllers/conversation_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/custom_emoji_controller.ex:6 +#: lib/pleroma/web/mastodon_api/controllers/domain_block_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:6 +#: lib/pleroma/web/mastodon_api/controllers/filter_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/follow_request_controller.ex:6 +#: lib/pleroma/web/mastodon_api/controllers/instance_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/list_controller.ex:6 +#: lib/pleroma/web/mastodon_api/controllers/marker_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex:14 +#: lib/pleroma/web/mastodon_api/controllers/media_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/notification_controller.ex:6 +#: lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/report_controller.ex:8 +#: lib/pleroma/web/mastodon_api/controllers/scheduled_activity_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/search_controller.ex:6 +#: lib/pleroma/web/mastodon_api/controllers/status_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex:7 +#: lib/pleroma/web/mastodon_api/controllers/suggestion_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:6 +#: lib/pleroma/web/media_proxy/media_proxy_controller.ex:6 lib/pleroma/web/mongooseim/mongoose_im_controller.ex:6 +#: lib/pleroma/web/nodeinfo/nodeinfo_controller.ex:6 lib/pleroma/web/oauth/fallback_controller.ex:6 +#: lib/pleroma/web/oauth/mfa_controller.ex:10 lib/pleroma/web/oauth/oauth_controller.ex:6 +#: lib/pleroma/web/ostatus/ostatus_controller.ex:6 lib/pleroma/web/pleroma_api/controllers/account_controller.ex:6 +#: lib/pleroma/web/pleroma_api/controllers/chat_controller.ex:5 lib/pleroma/web/pleroma_api/controllers/conversation_controller.ex:6 +#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:2 lib/pleroma/web/pleroma_api/controllers/emoji_reaction_controller.ex:6 +#: lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex:6 lib/pleroma/web/pleroma_api/controllers/notification_controller.ex:6 +#: lib/pleroma/web/pleroma_api/controllers/scrobble_controller.ex:6 +#: lib/pleroma/web/pleroma_api/controllers/two_factor_authentication_controller.ex:7 lib/pleroma/web/static_fe/static_fe_controller.ex:6 +#: lib/pleroma/web/twitter_api/controllers/password_controller.ex:10 lib/pleroma/web/twitter_api/controllers/remote_follow_controller.ex:6 +#: lib/pleroma/web/twitter_api/controllers/util_controller.ex:6 lib/pleroma/web/twitter_api/twitter_api_controller.ex:6 +#: lib/pleroma/web/uploader_controller.ex:6 lib/pleroma/web/web_finger/web_finger_controller.ex:6 +#, elixir-format +msgid "Security violation: OAuth scopes check was neither handled nor explicitly skipped." +msgstr "" + +#: lib/pleroma/plugs/ensure_authenticated_plug.ex:28 +#, elixir-format +msgid "Two-factor authentication enabled, you must use a access token." +msgstr "" + +#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:210 +#, elixir-format +msgid "Unexpected error occurred while adding file to pack." +msgstr "" + +#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:138 +#, elixir-format +msgid "Unexpected error occurred while creating pack." +msgstr "" + +#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:278 +#, elixir-format +msgid "Unexpected error occurred while removing file from pack." +msgstr "" + +#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:250 +#, elixir-format +msgid "Unexpected error occurred while updating file in pack." +msgstr "" + +#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:179 +#, elixir-format +msgid "Unexpected error occurred while updating pack metadata." +msgstr "" + +#: lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex:61 +#, elixir-format +msgid "Web push subscription is disabled on this Pleroma instance" +msgstr "" + +#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:451 +#, elixir-format +msgid "You can't revoke your own admin/moderator status." +msgstr "" + +#: lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:126 +#, elixir-format +msgid "authorization required for timeline view" +msgstr "" + +#: lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:24 +#, elixir-format +msgid "Access denied" +msgstr "" + +#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:282 +#, elixir-format +msgid "This API requires an authenticated user" +msgstr "" + +#: lib/pleroma/plugs/user_is_admin_plug.ex:21 +#, elixir-format +msgid "User is not an admin." +msgstr "" diff --git a/priv/gettext/pl/LC_MESSAGES/errors.po b/priv/gettext/pl/LC_MESSAGES/errors.po index 4d689902f..4acb1b54b 100644 --- a/priv/gettext/pl/LC_MESSAGES/errors.po +++ b/priv/gettext/pl/LC_MESSAGES/errors.po @@ -3,7 +3,7 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2020-05-13 16:37+0000\n" -"PO-Revision-Date: 2021-08-13 15:42+0000\n" +"PO-Revision-Date: 2021-08-15 08:45+0000\n" "Last-Translator: marcin mikołajczak <me@mkljczk.pl>\n" "Language-Team: Polish <https://translate.pleroma.social/projects/pleroma/" "pleroma/pl/>\n" @@ -453,7 +453,7 @@ msgstr "Nieznany błąd, sprawdź szczegóły i spróbuj ponownie." #: lib/pleroma/web/oauth/oauth_controller.ex:155 #, elixir-format msgid "Unlisted redirect_uri." -msgstr "" +msgstr "Niewypisany redirect_uri." #: lib/pleroma/web/oauth/oauth_controller.ex:391 #, elixir-format @@ -463,7 +463,7 @@ msgstr "Nieobsługiwany dostawca OAuth: %{provider}." #: lib/pleroma/uploaders/uploader.ex:72 #, elixir-format msgid "Uploader callback timeout" -msgstr "" +msgstr "Przekroczono czas wysyłania pliku" #: lib/pleroma/web/uploader_controller.ex:23 #, elixir-format diff --git a/priv/gettext/vi/LC_MESSAGES/errors.po b/priv/gettext/vi/LC_MESSAGES/errors.po new file mode 100644 index 000000000..3fce2675f --- /dev/null +++ b/priv/gettext/vi/LC_MESSAGES/errors.po @@ -0,0 +1,580 @@ +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-09-06 11:13+0000\n" +"PO-Revision-Date: 2021-09-07 16:42+0000\n" +"Last-Translator: Hồ Nhất Duy <kantcer@gmail.com>\n" +"Language-Team: Vietnamese <https://translate.pleroma.social/projects/pleroma/" +"pleroma/vi/>\n" +"Language: vi\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" + +## This file is a PO Template file. +## +## `msgid`s here are often extracted from source code. +## Add new translations manually only if they're dynamic +## translations that can't be statically extracted. +## +## Run `mix gettext.extract` to bring this file up to +## date. Leave `msgstr`s empty as changing them here as no +## effect: edit them in PO (`.po`) files instead. +## From Ecto.Changeset.cast/4 +msgid "can't be blank" +msgstr "không được để trống" + +## From Ecto.Changeset.unique_constraint/3 +msgid "has already been taken" +msgstr "đã có người sử dụng" + +## From Ecto.Changeset.put_change/3 +msgid "is invalid" +msgstr "không khớp" + +## From Ecto.Changeset.validate_format/3 +msgid "has invalid format" +msgstr "định dạng không hợp lệ" + +## From Ecto.Changeset.validate_subset/3 +msgid "has an invalid entry" +msgstr "có mục sai" + +## From Ecto.Changeset.validate_exclusion/3 +msgid "is reserved" +msgstr "đảo ngược" + +## From Ecto.Changeset.validate_confirmation/3 +msgid "does not match confirmation" +msgstr "không trùng khớp" + +## From Ecto.Changeset.no_assoc_constraint/3 +msgid "is still associated with this entry" +msgstr "vẫn liên kết với mục này" + +msgid "are still associated with this entry" +msgstr "vẫn liên kết với mục này" + +## From Ecto.Changeset.validate_length/3 +msgid "should be %{count} character(s)" +msgid_plural "should be %{count} character(s)" +msgstr[0] "tối thiểu %{count} ký tự" + +msgid "should have %{count} item(s)" +msgid_plural "should have %{count} item(s)" +msgstr[0] "tối thiểu %{count} mục" + +msgid "should be at least %{count} character(s)" +msgid_plural "should be at least %{count} character(s)" +msgstr[0] "tối thiểu %{count} ký tự" + +msgid "should have at least %{count} item(s)" +msgid_plural "should have at least %{count} item(s)" +msgstr[0] "tối thiểu %{count} mục" + +msgid "should be at most %{count} character(s)" +msgid_plural "should be at most %{count} character(s)" +msgstr[0] "tối đa %{count} ký tự" + +msgid "should have at most %{count} item(s)" +msgid_plural "should have at most %{count} item(s)" +msgstr[0] "tối đa %{count} mục" + +## From Ecto.Changeset.validate_number/3 +msgid "must be less than %{number}" +msgstr "phải nhỏ hơn %{number}" + +msgid "must be greater than %{number}" +msgstr "phải lớn hơn %{number}" + +msgid "must be less than or equal to %{number}" +msgstr "phải nhỏ hơn hoặc bằng %{number}" + +msgid "must be greater than or equal to %{number}" +msgstr "phải lớn hơn hoặc bằng %{number}" + +msgid "must be equal to %{number}" +msgstr "phải là %{number}" + +#: lib/pleroma/web/common_api/common_api.ex:505 +#, elixir-format +msgid "Account not found" +msgstr "Không tìm thấy tài khoản" + +#: lib/pleroma/web/common_api/common_api.ex:339 +#, elixir-format +msgid "Already voted" +msgstr "Đã bình chọn" + +#: lib/pleroma/web/oauth/oauth_controller.ex:359 +#, elixir-format +msgid "Bad request" +msgstr "Lỗi truy vấn" + +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:426 +#, elixir-format +msgid "Can't delete object" +msgstr "Không thể xóa đối tượng" + +#: lib/pleroma/web/controller_helper.ex:105 +#: lib/pleroma/web/controller_helper.ex:111 +#, elixir-format +msgid "Can't display this activity" +msgstr "Không thể hiển thị hoạt động này" + +#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:285 +#, elixir-format +msgid "Can't find user" +msgstr "Không tìm thấy người dùng" + +#: lib/pleroma/web/pleroma_api/controllers/account_controller.ex:61 +#, elixir-format +msgid "Can't get favorites" +msgstr "Không thể tải lượt thích" + +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:438 +#, elixir-format +msgid "Can't like object" +msgstr "Không thể thích đối tượng" + +#: lib/pleroma/web/common_api/utils.ex:563 +#, elixir-format +msgid "Cannot post an empty status without attachments" +msgstr "Không thể đăng một tút trống trơn" + +#: lib/pleroma/web/common_api/utils.ex:511 +#, elixir-format +msgid "Comment must be up to %{max_size} characters" +msgstr "Bình luận tối đa %{max_size} ký tự" + +#: lib/pleroma/config/config_db.ex:191 +#, elixir-format +msgid "Config with params %{params} not found" +msgstr "Không tìm thấy cấu hình %{params}" + +#: lib/pleroma/web/common_api/common_api.ex:181 +#: lib/pleroma/web/common_api/common_api.ex:185 +#, elixir-format +msgid "Could not delete" +msgstr "Không thể xóa" + +#: lib/pleroma/web/common_api/common_api.ex:231 +#, elixir-format +msgid "Could not favorite" +msgstr "Không thể thích" + +#: lib/pleroma/web/common_api/common_api.ex:453 +#, elixir-format +msgid "Could not pin" +msgstr "Không thể ghim" + +#: lib/pleroma/web/common_api/common_api.ex:278 +#, elixir-format +msgid "Could not unfavorite" +msgstr "Không thể bỏ thích" + +#: lib/pleroma/web/common_api/common_api.ex:463 +#, elixir-format +msgid "Could not unpin" +msgstr "Không thể bỏ ghim" + +#: lib/pleroma/web/common_api/common_api.ex:216 +#, elixir-format +msgid "Could not unrepeat" +msgstr "Không thể hủy chia sẻ" + +#: lib/pleroma/web/common_api/common_api.ex:512 +#: lib/pleroma/web/common_api/common_api.ex:521 +#, elixir-format +msgid "Could not update state" +msgstr "Không thể cập nhật trạng thái" + +#: lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:207 +#, elixir-format +msgid "Error." +msgstr "Lỗi." + +#: lib/pleroma/web/twitter_api/twitter_api.ex:106 +#, elixir-format +msgid "Invalid CAPTCHA" +msgstr "CAPTCHA không hợp lệ" + +#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:116 +#: lib/pleroma/web/oauth/oauth_controller.ex:568 +#, elixir-format +msgid "Invalid credentials" +msgstr "Danh tính không hợp lệ" + +#: lib/pleroma/plugs/ensure_authenticated_plug.ex:38 +#, elixir-format +msgid "Invalid credentials." +msgstr "Danh tính không hợp lệ." + +#: lib/pleroma/web/common_api/common_api.ex:355 +#, elixir-format +msgid "Invalid indices" +msgstr "Sai dấu hiệu" + +#: lib/pleroma/web/admin_api/controllers/fallback_controller.ex:29 +#, elixir-format +msgid "Invalid parameters" +msgstr "Sai tham số" + +#: lib/pleroma/web/common_api/utils.ex:414 +#, elixir-format +msgid "Invalid password." +msgstr "Sai mật khẩu." + +#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:220 +#, elixir-format +msgid "Invalid request" +msgstr "Yêu cầu không hợp lệ" + +#: lib/pleroma/web/twitter_api/twitter_api.ex:109 +#, elixir-format +msgid "Kocaptcha service unavailable" +msgstr "Dịch vụ Kocaptcha chưa sẵn sàng" + +#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:112 +#, elixir-format +msgid "Missing parameters" +msgstr "Thiếu tham số" + +#: lib/pleroma/web/common_api/utils.ex:547 +#, elixir-format +msgid "No such conversation" +msgstr "Không chuyển đổi" + +#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:388 +#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:414 lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:456 +#, elixir-format +msgid "No such permission_group" +msgstr "Không permission_group" + +#: lib/pleroma/plugs/uploaded_media.ex:84 +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:486 lib/pleroma/web/admin_api/controllers/fallback_controller.ex:11 +#: lib/pleroma/web/feed/user_controller.ex:71 lib/pleroma/web/ostatus/ostatus_controller.ex:143 +#, elixir-format +msgid "Not found" +msgstr "Không tìm thấy" + +#: lib/pleroma/web/common_api/common_api.ex:331 +#, elixir-format +msgid "Poll's author can't vote" +msgstr "Người tạo bình chọn không thể bình chọn" + +#: 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 +#: lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:50 lib/pleroma/web/mastodon_api/controllers/status_controller.ex:306 +#: lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex:71 +#, elixir-format +msgid "Record not found" +msgstr "Không tìm thấy gì hết" + +#: lib/pleroma/web/admin_api/controllers/fallback_controller.ex:35 +#: lib/pleroma/web/feed/user_controller.ex:77 lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:36 +#: lib/pleroma/web/ostatus/ostatus_controller.ex:149 +#, elixir-format +msgid "Something went wrong" +msgstr "Có lỗi xảy ra" + +#: lib/pleroma/web/common_api/activity_draft.ex:107 +#, elixir-format +msgid "The message visibility must be direct" +msgstr "Tin nhắn phải là trực tiếp" + +#: lib/pleroma/web/common_api/utils.ex:573 +#, elixir-format +msgid "The status is over the character limit" +msgstr "Tút vượt quá giới hạn ký tự" + +#: lib/pleroma/plugs/ensure_public_or_authenticated_plug.ex:31 +#, elixir-format +msgid "This resource requires authentication." +msgstr "Tài nguyên này yêu cầu xác thực." + +#: lib/pleroma/plugs/rate_limiter/rate_limiter.ex:206 +#, elixir-format +msgid "Throttled" +msgstr "Đã điều tiết" + +#: lib/pleroma/web/common_api/common_api.ex:356 +#, elixir-format +msgid "Too many choices" +msgstr "Quá nhiều lựa chọn" + +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:443 +#, elixir-format +msgid "Unhandled activity type" +msgstr "Không thể xử lý loại hoạt động" + +#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:485 +#, elixir-format +msgid "You can't revoke your own admin status." +msgstr "Không thể tự gỡ chức vụ quản trị viên" + +#: lib/pleroma/web/oauth/oauth_controller.ex:221 +#: lib/pleroma/web/oauth/oauth_controller.ex:308 +#, elixir-format +msgid "Your account is currently disabled" +msgstr "Tài khoản của bạn bị ẩn" + +#: lib/pleroma/web/oauth/oauth_controller.ex:183 +#: lib/pleroma/web/oauth/oauth_controller.ex:331 +#, elixir-format +msgid "Your login is missing a confirmed e-mail address" +msgstr "Bạn chưa xác thực địa chỉ email" + +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:390 +#, elixir-format +msgid "can't read inbox of %{nickname} as %{as_nickname}" +msgstr "không thể đọc hộp thư đến của %{nickname} như %{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 "không thể cập nhật hộp thư đi của %{nickname} như %{as_nickname}" + +#: lib/pleroma/web/common_api/common_api.ex:471 +#, elixir-format +msgid "conversation is already muted" +msgstr "bạn đã bỏ quan tâm cuộc đối thoại này" + +#: 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 "lỗi" + +#: lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex:32 +#, elixir-format +msgid "mascots can only be images" +msgstr "linh vật chỉ được là hình ảnh" + +#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:62 +#, elixir-format +msgid "not found" +msgstr "không tìm thấy" + +#: lib/pleroma/web/oauth/oauth_controller.ex:394 +#, elixir-format +msgid "Bad OAuth request." +msgstr "Không thể kết nối OAuth." + +#: lib/pleroma/web/twitter_api/twitter_api.ex:115 +#, elixir-format +msgid "CAPTCHA already used" +msgstr "CAPTCHA đã dùng rồi" + +#: lib/pleroma/web/twitter_api/twitter_api.ex:112 +#, elixir-format +msgid "CAPTCHA expired" +msgstr "CAPTCHA đã hết hạn" + +#: lib/pleroma/plugs/uploaded_media.ex:57 +#, elixir-format +msgid "Failed" +msgstr "Thất bại" + +#: lib/pleroma/web/oauth/oauth_controller.ex:410 +#, elixir-format +msgid "Failed to authenticate: %{message}." +msgstr "Xác thực thất bại: %{message}." + +#: lib/pleroma/web/oauth/oauth_controller.ex:441 +#, elixir-format +msgid "Failed to set up user account." +msgstr "Tạo tài khoản không thành công." + +#: lib/pleroma/plugs/oauth_scopes_plug.ex:38 +#, elixir-format +msgid "Insufficient permissions: %{permissions}." +msgstr "Không có quyền: %{permissions}." + +#: lib/pleroma/plugs/uploaded_media.ex:104 +#, elixir-format +msgid "Internal Error" +msgstr "Lỗi nội bộ" + +#: lib/pleroma/web/oauth/fallback_controller.ex:22 +#: lib/pleroma/web/oauth/fallback_controller.ex:29 +#, elixir-format +msgid "Invalid Username/Password" +msgstr "Tên người dùng/mật khẩu không đúng" + +#: lib/pleroma/web/twitter_api/twitter_api.ex:118 +#, elixir-format +msgid "Invalid answer data" +msgstr "sai dữ liệu trả lời" + +#: lib/pleroma/web/nodeinfo/nodeinfo_controller.ex:33 +#, elixir-format +msgid "Nodeinfo schema version not handled" +msgstr "Chưa nạp Nodeinfo" + +#: lib/pleroma/web/oauth/oauth_controller.ex:172 +#, elixir-format +msgid "This action is outside the authorized scopes" +msgstr "Hành động này nằm ngoài phạm vi cho phép" + +#: lib/pleroma/web/oauth/fallback_controller.ex:14 +#, elixir-format +msgid "Unknown error, please check the details and try again." +msgstr "Lỗi chưa biết, xin kiểm tra chi tiết và thử lại sau." + +#: lib/pleroma/web/oauth/oauth_controller.ex:119 +#: lib/pleroma/web/oauth/oauth_controller.ex:158 +#, elixir-format +msgid "Unlisted redirect_uri." +msgstr "Hạn chế redirect_uri." + +#: lib/pleroma/web/oauth/oauth_controller.ex:390 +#, elixir-format +msgid "Unsupported OAuth provider: %{provider}." +msgstr "Không hỗ trợ nhà cung cấp OAuth: %{provider}." + +#: lib/pleroma/uploaders/uploader.ex:72 +#, elixir-format +msgid "Uploader callback timeout" +msgstr "Hết hạn tải lên" + +#: lib/pleroma/web/uploader_controller.ex:23 +#, elixir-format +msgid "bad request" +msgstr "lỗi kết nối" + +#: lib/pleroma/web/twitter_api/twitter_api.ex:103 +#, elixir-format +msgid "CAPTCHA Error" +msgstr "Lỗi CAPTCHA" + +#: lib/pleroma/web/common_api/common_api.ex:290 +#, elixir-format +msgid "Could not add reaction emoji" +msgstr "Không thể thêm tương tác emoji" + +#: lib/pleroma/web/common_api/common_api.ex:301 +#, elixir-format +msgid "Could not remove reaction emoji" +msgstr "Không thể xóa tương tác emoji" + +#: lib/pleroma/web/twitter_api/twitter_api.ex:129 +#, elixir-format +msgid "Invalid CAPTCHA (Missing parameter: %{name})" +msgstr "CAPTCHA sai (Thiếu tham số: %{name})" + +#: lib/pleroma/web/mastodon_api/controllers/list_controller.ex:92 +#, elixir-format +msgid "List not found" +msgstr "Không tìm thấy danh sách" + +#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:123 +#, elixir-format +msgid "Missing parameter: %{name}" +msgstr "Thiếu tham số: %{name}" + +#: lib/pleroma/web/oauth/oauth_controller.ex:210 +#: lib/pleroma/web/oauth/oauth_controller.ex:321 +#, elixir-format +msgid "Password reset is required" +msgstr "Yêu cầu đổi mật khẩu" + +#: 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 +#: lib/pleroma/web/admin_api/controllers/config_controller.ex:6 lib/pleroma/web/admin_api/controllers/fallback_controller.ex:6 +#: lib/pleroma/web/admin_api/controllers/invite_controller.ex:6 lib/pleroma/web/admin_api/controllers/media_proxy_cache_controller.ex:6 +#: lib/pleroma/web/admin_api/controllers/oauth_app_controller.ex:6 lib/pleroma/web/admin_api/controllers/relay_controller.ex:6 +#: lib/pleroma/web/admin_api/controllers/report_controller.ex:6 lib/pleroma/web/admin_api/controllers/status_controller.ex:6 +#: lib/pleroma/web/controller_helper.ex:6 lib/pleroma/web/embed_controller.ex:6 +#: lib/pleroma/web/fallback_redirect_controller.ex:6 lib/pleroma/web/feed/tag_controller.ex:6 +#: lib/pleroma/web/feed/user_controller.ex:6 lib/pleroma/web/mailer/subscription_controller.ex:2 +#: lib/pleroma/web/masto_fe_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/account_controller.ex:6 +#: lib/pleroma/web/mastodon_api/controllers/app_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/auth_controller.ex:6 +#: lib/pleroma/web/mastodon_api/controllers/conversation_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/custom_emoji_controller.ex:6 +#: lib/pleroma/web/mastodon_api/controllers/domain_block_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:6 +#: lib/pleroma/web/mastodon_api/controllers/filter_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/follow_request_controller.ex:6 +#: lib/pleroma/web/mastodon_api/controllers/instance_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/list_controller.ex:6 +#: lib/pleroma/web/mastodon_api/controllers/marker_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex:14 +#: lib/pleroma/web/mastodon_api/controllers/media_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/notification_controller.ex:6 +#: lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/report_controller.ex:8 +#: lib/pleroma/web/mastodon_api/controllers/scheduled_activity_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/search_controller.ex:6 +#: lib/pleroma/web/mastodon_api/controllers/status_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex:7 +#: lib/pleroma/web/mastodon_api/controllers/suggestion_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:6 +#: lib/pleroma/web/media_proxy/media_proxy_controller.ex:6 lib/pleroma/web/mongooseim/mongoose_im_controller.ex:6 +#: lib/pleroma/web/nodeinfo/nodeinfo_controller.ex:6 lib/pleroma/web/oauth/fallback_controller.ex:6 +#: lib/pleroma/web/oauth/mfa_controller.ex:10 lib/pleroma/web/oauth/oauth_controller.ex:6 +#: lib/pleroma/web/ostatus/ostatus_controller.ex:6 lib/pleroma/web/pleroma_api/controllers/account_controller.ex:6 +#: lib/pleroma/web/pleroma_api/controllers/chat_controller.ex:5 lib/pleroma/web/pleroma_api/controllers/conversation_controller.ex:6 +#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:2 lib/pleroma/web/pleroma_api/controllers/emoji_reaction_controller.ex:6 +#: lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex:6 lib/pleroma/web/pleroma_api/controllers/notification_controller.ex:6 +#: lib/pleroma/web/pleroma_api/controllers/scrobble_controller.ex:6 +#: lib/pleroma/web/pleroma_api/controllers/two_factor_authentication_controller.ex:7 lib/pleroma/web/static_fe/static_fe_controller.ex:6 +#: lib/pleroma/web/twitter_api/controllers/password_controller.ex:10 lib/pleroma/web/twitter_api/controllers/remote_follow_controller.ex:6 +#: lib/pleroma/web/twitter_api/controllers/util_controller.ex:6 lib/pleroma/web/twitter_api/twitter_api_controller.ex:6 +#: lib/pleroma/web/uploader_controller.ex:6 lib/pleroma/web/web_finger/web_finger_controller.ex:6 +#, elixir-format +msgid "Security violation: OAuth scopes check was neither handled nor explicitly skipped." +msgstr "Vi phạm bảo mật: phạm vi OAuth bị bỏ qua hoặc vượt quá giới hạn." + +#: lib/pleroma/plugs/ensure_authenticated_plug.ex:28 +#, elixir-format +msgid "Two-factor authentication enabled, you must use a access token." +msgstr "Đã bật xác thực hai bước, bạn phải sử dụng token truy cập." + +#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:210 +#, elixir-format +msgid "Unexpected error occurred while adding file to pack." +msgstr "Xảy ra lỗi chưa biết khi nén tập tin." + +#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:138 +#, elixir-format +msgid "Unexpected error occurred while creating pack." +msgstr "Xảy ra lỗi chưa biết khi tạo tập tin." + +#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:278 +#, elixir-format +msgid "Unexpected error occurred while removing file from pack." +msgstr "Xảy ra lỗi chưa biết khi giải nén tập tin." + +#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:250 +#, elixir-format +msgid "Unexpected error occurred while updating file in pack." +msgstr "Xảy ra lỗi chưa biết khi cập nhật tập tin." + +#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:179 +#, elixir-format +msgid "Unexpected error occurred while updating pack metadata." +msgstr "Xảy ra lỗi chưa biết khi cập nhật metadata tập tin." + +#: lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex:61 +#, elixir-format +msgid "Web push subscription is disabled on this Pleroma instance" +msgstr "Máy chủ Pleroma này tắt thông báo đẩy trên web" + +#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:451 +#, elixir-format +msgid "You can't revoke your own admin/moderator status." +msgstr "Bạn không thể tự gỡ chức vụ." + +#: lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:126 +#, elixir-format +msgid "authorization required for timeline view" +msgstr "yêu cầu xác thực để xem bảng tin" + +#: lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:24 +#, elixir-format +msgid "Access denied" +msgstr "Truy cập bị từ chối" + +#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:282 +#, elixir-format +msgid "This API requires an authenticated user" +msgstr "API yêu cầu một người dùng đã xác thực" + +#: lib/pleroma/plugs/user_is_admin_plug.ex:21 +#, elixir-format +msgid "User is not an admin." +msgstr "Người này không phải quản trị viên." diff --git a/priv/repo/migrations/20171212164525_fill_recipients_in_activities.exs b/priv/repo/migrations/20171212164525_fill_recipients_in_activities.exs index 6dfa93716..77a09781c 100644 --- a/priv/repo/migrations/20171212164525_fill_recipients_in_activities.exs +++ b/priv/repo/migrations/20171212164525_fill_recipients_in_activities.exs @@ -14,9 +14,7 @@ defmodule Pleroma.Repo.Migrations.FillRecipientsInActivities do max = min + 10_000 execute(""" - update activities set recipients = array(select jsonb_array_elements_text(data->'to')) where id > #{ - min - } and id <= #{max}; + update activities set recipients = array(select jsonb_array_elements_text(data->'to')) where id > #{min} and id <= #{max}; """) |> IO.inspect() end) diff --git a/priv/repo/migrations/20200428221338_insert_skeletons_for_deleted_users.exs b/priv/repo/migrations/20200428221338_insert_skeletons_for_deleted_users.exs index 2adc38186..81f941198 100644 --- a/priv/repo/migrations/20200428221338_insert_skeletons_for_deleted_users.exs +++ b/priv/repo/migrations/20200428221338_insert_skeletons_for_deleted_users.exs @@ -28,9 +28,7 @@ defmodule Pleroma.Repo.Migrations.InsertSkeletonsForDeletedUsers do {:ok, %{rows: ap_ids}} = Ecto.Adapters.SQL.query( Repo, - "select distinct unnest(nonexistent_locals.recipients) from activities, lateral (select array_agg(recipient) as recipients from unnest(activities.recipients) as recipient where recipient similar to '#{ - instance_uri - }/users/[A-Za-z0-9]*' and not(recipient in (select ap_id from users))) nonexistent_locals;", + "select distinct unnest(nonexistent_locals.recipients) from activities, lateral (select array_agg(recipient) as recipients from unnest(activities.recipients) as recipient where recipient similar to '#{instance_uri}/users/[A-Za-z0-9]*' and not(recipient in (select ap_id from users))) nonexistent_locals;", [], timeout: :infinity ) diff --git a/priv/repo/migrations/20211125110126_force_pinned_objects_to_exist.exs b/priv/repo/migrations/20211125110126_force_pinned_objects_to_exist.exs new file mode 100644 index 000000000..1fe9271f0 --- /dev/null +++ b/priv/repo/migrations/20211125110126_force_pinned_objects_to_exist.exs @@ -0,0 +1,11 @@ +defmodule Pleroma.Repo.Migrations.ForcePinnedObjectsToExist do + use Ecto.Migration + + def change do + execute("UPDATE users SET pinned_objects = '{}' WHERE pinned_objects IS NULL") + + alter table("users") do + modify(:pinned_objects, :map, null: false, default: %{}) + end + end +end diff --git a/priv/repo/migrations/20211126191138_add_suggestions.exs b/priv/repo/migrations/20211126191138_add_suggestions.exs new file mode 100644 index 000000000..7cc67d8ef --- /dev/null +++ b/priv/repo/migrations/20211126191138_add_suggestions.exs @@ -0,0 +1,11 @@ +defmodule Pleroma.Repo.Migrations.AddSuggestions do + use Ecto.Migration + + def change do + alter table(:users) do + add(:is_suggested, :boolean, default: false, null: false) + end + + create_if_not_exists(index(:users, [:is_suggested])) + end +end diff --git a/priv/templates/sample_config.eex b/priv/templates/sample_config.eex index 42f496ded..0068969ac 100644 --- a/priv/templates/sample_config.eex +++ b/priv/templates/sample_config.eex @@ -13,6 +13,7 @@ config :pleroma, Pleroma.Web.Endpoint, url: [host: "<%= domain %>", scheme: "https", port: <%= port %>], http: [ip: {<%= String.replace(listen_ip, ".", ", ") %>}, port: <%= listen_port %>], secret_key_base: "<%= secret %>", + live_view: [signing_salt: "<%= lv_signing_salt %>"], signing_salt: "<%= signing_salt %>" config :pleroma, :instance, diff --git a/test/pleroma/emails/admin_email_test.exs b/test/pleroma/emails/admin_email_test.exs index 04c907697..e65752c23 100644 --- a/test/pleroma/emails/admin_email_test.exs +++ b/test/pleroma/emails/admin_email_test.exs @@ -27,11 +27,7 @@ defmodule Pleroma.Emails.AdminEmailTest do assert res.subject == "#{config[:name]} Report" assert res.html_body == - "<p>Reported by: <a href=\"#{reporter_url}\">#{reporter.nickname}</a></p>\n<p>Reported Account: <a href=\"#{ - account_url - }\">#{account.nickname}</a></p>\n<p>Comment: Test comment\n<p> Statuses:\n <ul>\n <li><a href=\"#{ - status_url - }\">#{status_url}</li>\n </ul>\n</p>\n\n<p>\n<a href=\"http://localhost:4001/pleroma/admin/#/reports/index\">View Reports in AdminFE</a>\n" + "<p>Reported by: <a href=\"#{reporter_url}\">#{reporter.nickname}</a></p>\n<p>Reported Account: <a href=\"#{account_url}\">#{account.nickname}</a></p>\n<p>Comment: Test comment\n<p> Statuses:\n <ul>\n <li><a href=\"#{status_url}\">#{status_url}</li>\n </ul>\n</p>\n\n<p>\n<a href=\"http://localhost:4001/pleroma/admin/#/reports/index\">View Reports in AdminFE</a>\n" end test "it works when the reporter is a remote user without email" do diff --git a/test/pleroma/formatter_test.exs b/test/pleroma/formatter_test.exs index 7f54638fb..b0f9f41b1 100644 --- a/test/pleroma/formatter_test.exs +++ b/test/pleroma/formatter_test.exs @@ -151,13 +151,7 @@ defmodule Pleroma.FormatterTest do assert length(mentions) == 3 expected_text = - ~s(<span class="h-card"><a class="u-url mention" data-user="#{gsimg.id}" href="#{ - gsimg.ap_id - }" rel="ugc">@<span>gsimg</span></a></span> According to <span class="h-card"><a class="u-url mention" data-user="#{ - archaeme.id - }" href="#{"https://archeme/@archa_eme_"}" rel="ugc">@<span>archa_eme_</span></a></span>, that is @daggsy. Also hello <span class="h-card"><a class="u-url mention" data-user="#{ - archaeme_remote.id - }" href="#{archaeme_remote.ap_id}" rel="ugc">@<span>archaeme</span></a></span>) + ~s(<span class="h-card"><a class="u-url mention" data-user="#{gsimg.id}" href="#{gsimg.ap_id}" rel="ugc">@<span>gsimg</span></a></span> According to <span class="h-card"><a class="u-url mention" data-user="#{archaeme.id}" href="#{"https://archeme/@archa_eme_"}" rel="ugc">@<span>archa_eme_</span></a></span>, that is @daggsy. Also hello <span class="h-card"><a class="u-url mention" data-user="#{archaeme_remote.id}" href="#{archaeme_remote.ap_id}" rel="ugc">@<span>archaeme</span></a></span>) assert expected_text == text end @@ -172,9 +166,7 @@ defmodule Pleroma.FormatterTest do assert length(mentions) == 1 expected_text = - ~s(<span class="h-card"><a class="u-url mention" data-user="#{mike.id}" href="#{ - mike.ap_id - }" rel="ugc">@<span>mike</span></a></span> test) + ~s(<span class="h-card"><a class="u-url mention" data-user="#{mike.id}" href="#{mike.ap_id}" rel="ugc">@<span>mike</span></a></span> test) assert expected_text == text end @@ -210,13 +202,7 @@ defmodule Pleroma.FormatterTest do assert mentions == [{"@#{user.nickname}", user}, {"@#{other_user.nickname}", other_user}] assert expected_text == - ~s(<span class="h-card"><a class="u-url mention" data-user="#{user.id}" href="#{ - user.ap_id - }" rel="ugc">@<span>#{user.nickname}</span></a></span> <span class="h-card"><a class="u-url mention" data-user="#{ - other_user.id - }" href="#{other_user.ap_id}" rel="ugc">@<span>#{other_user.nickname}</span></a></span> hey dudes i hate <span class="h-card"><a class="u-url mention" data-user="#{ - third_user.id - }" href="#{third_user.ap_id}" rel="ugc">@<span>#{third_user.nickname}</span></a></span>) + ~s(<span class="h-card"><a class="u-url mention" data-user="#{user.id}" href="#{user.ap_id}" rel="ugc">@<span>#{user.nickname}</span></a></span> <span class="h-card"><a class="u-url mention" data-user="#{other_user.id}" href="#{other_user.ap_id}" rel="ugc">@<span>#{other_user.nickname}</span></a></span> hey dudes i hate <span class="h-card"><a class="u-url mention" data-user="#{third_user.id}" href="#{third_user.ap_id}" rel="ugc">@<span>#{third_user.nickname}</span></a></span>) end test "given the 'safe_mention' option, it will still work without any mention" do diff --git a/test/pleroma/instances/instance_test.exs b/test/pleroma/instances/instance_test.exs index bacc0b19b..e49922724 100644 --- a/test/pleroma/instances/instance_test.exs +++ b/test/pleroma/instances/instance_test.exs @@ -6,6 +6,8 @@ defmodule Pleroma.Instances.InstanceTest do alias Pleroma.Instances alias Pleroma.Instances.Instance alias Pleroma.Repo + alias Pleroma.Tests.ObanHelpers + alias Pleroma.Web.CommonAPI use Pleroma.DataCase @@ -158,4 +160,33 @@ defmodule Pleroma.Instances.InstanceTest do "Instance.scrape_favicon(\"#{url}\") ignored unreachable host" end end + + test "delete_users_and_activities/1 deletes remote instance users and activities" do + [mario, luigi, _peach, wario] = + users = [ + insert(:user, nickname: "mario@mushroom.kingdom", name: "Mario"), + insert(:user, nickname: "luigi@mushroom.kingdom", name: "Luigi"), + insert(:user, nickname: "peach@mushroom.kingdom", name: "Peach"), + insert(:user, nickname: "wario@greedville.biz", name: "Wario") + ] + + {:ok, post1} = CommonAPI.post(mario, %{status: "letsa go!"}) + {:ok, post2} = CommonAPI.post(luigi, %{status: "itsa me... luigi"}) + {:ok, post3} = CommonAPI.post(wario, %{status: "WHA-HA-HA!"}) + + {:ok, job} = Instance.delete_users_and_activities("mushroom.kingdom") + :ok = ObanHelpers.perform(job) + + [mario, luigi, peach, wario] = Repo.reload(users) + + refute mario.is_active + refute luigi.is_active + refute peach.is_active + refute peach.name == "Peach" + + assert wario.is_active + assert wario.name == "Wario" + + assert [nil, nil, %{}] = Repo.reload([post1, post2, post3]) + end end diff --git a/test/pleroma/moderation_log_test.exs b/test/pleroma/moderation_log_test.exs index c6c170c45..607301815 100644 --- a/test/pleroma/moderation_log_test.exs +++ b/test/pleroma/moderation_log_test.exs @@ -236,9 +236,7 @@ defmodule Pleroma.ModerationLogTest do log = Repo.get(ModerationLog, log2.id) assert log.data["message"] == - "@#{moderator.nickname} added note 'look at this' to report ##{report.id} on user @#{ - user.nickname - }" + "@#{moderator.nickname} added note 'look at this' to report ##{report.id} on user @#{user.nickname}" end test "logging status sensitivity update", %{moderator: moderator} do diff --git a/test/pleroma/user/query_test.exs b/test/pleroma/user/query_test.exs index 357016e3e..363da7665 100644 --- a/test/pleroma/user/query_test.exs +++ b/test/pleroma/user/query_test.exs @@ -34,4 +34,14 @@ defmodule Pleroma.User.QueryTest do assert %{internal: true} |> Query.build() |> Repo.aggregate(:count) == 2 end end + + test "is_suggested param" do + _user1 = insert(:user, is_suggested: false) + user2 = insert(:user, is_suggested: true) + + assert [^user2] = + %{is_suggested: true} + |> User.Query.build() + |> Repo.all() + end end diff --git a/test/pleroma/user_test.exs b/test/pleroma/user_test.exs index 9922c8b56..6cd93c34c 100644 --- a/test/pleroma/user_test.exs +++ b/test/pleroma/user_test.exs @@ -1718,6 +1718,38 @@ defmodule Pleroma.UserTest do assert user.banner == %{} end + describe "set_suggestion" do + test "suggests a user" do + user = insert(:user, is_suggested: false) + refute user.is_suggested + {:ok, user} = User.set_suggestion(user, true) + assert user.is_suggested + end + + test "suggests a list of users" do + unsuggested_users = [ + insert(:user, is_suggested: false), + insert(:user, is_suggested: false), + insert(:user, is_suggested: false) + ] + + {:ok, users} = User.set_suggestion(unsuggested_users, true) + + assert Enum.count(users) == 3 + + Enum.each(users, fn user -> + assert user.is_suggested + end) + end + + test "unsuggests a user" do + user = insert(:user, is_suggested: true) + assert user.is_suggested + {:ok, user} = User.set_suggestion(user, false) + refute user.is_suggested + end + end + test "get_public_key_for_ap_id fetches a user that's not in the db" do assert {:ok, _key} = User.get_public_key_for_ap_id("http://mastodon.example.org/users/admin") end @@ -1886,9 +1918,7 @@ defmodule Pleroma.UserTest do bio = "A.k.a. @nick@domain.com" expected_text = - ~s(A.k.a. <span class="h-card"><a class="u-url mention" data-user="#{remote_user.id}" href="#{ - remote_user.ap_id - }" rel="ugc">@<span>nick@domain.com</span></a></span>) + ~s(A.k.a. <span class="h-card"><a class="u-url mention" data-user="#{remote_user.id}" href="#{remote_user.ap_id}" rel="ugc">@<span>nick@domain.com</span></a></span>) assert expected_text == User.parse_bio(bio, user) end @@ -2197,11 +2227,40 @@ defmodule Pleroma.UserTest do [user: insert(:user)] end - test "blank email returns error", %{user: user} do + test "blank email returns error if we require an email on registration", %{user: user} do + orig_account_activation_required = + Pleroma.Config.get([:instance, :account_activation_required]) + + Pleroma.Config.put([:instance, :account_activation_required], true) + + on_exit(fn -> + Pleroma.Config.put( + [:instance, :account_activation_required], + orig_account_activation_required + ) + end) + assert {:error, %{errors: [email: {"can't be blank", _}]}} = User.change_email(user, "") assert {:error, %{errors: [email: {"can't be blank", _}]}} = User.change_email(user, nil) end + test "blank email should be fine if we do not require an email on registration", %{user: user} do + orig_account_activation_required = + Pleroma.Config.get([:instance, :account_activation_required]) + + Pleroma.Config.put([:instance, :account_activation_required], false) + + on_exit(fn -> + Pleroma.Config.put( + [:instance, :account_activation_required], + orig_account_activation_required + ) + end) + + assert {:ok, %User{email: nil}} = User.change_email(user, "") + assert {:ok, %User{email: nil}} = User.change_email(user, nil) + end + test "non unique email returns error", %{user: user} do %{email: email} = insert(:user) @@ -2217,6 +2276,25 @@ defmodule Pleroma.UserTest do test "changes email", %{user: user} do assert {:ok, %User{email: "cofe@cofe.party"}} = User.change_email(user, "cofe@cofe.party") end + + test "adds email", %{user: user} do + orig_account_activation_required = + Pleroma.Config.get([:instance, :account_activation_required]) + + Pleroma.Config.put([:instance, :account_activation_required], false) + + on_exit(fn -> + Pleroma.Config.put( + [:instance, :account_activation_required], + orig_account_activation_required + ) + end) + + assert {:ok, _} = User.change_email(user, "") + Pleroma.Config.put([:instance, :account_activation_required], true) + + assert {:ok, %User{email: "cofe2@cofe.party"}} = User.change_email(user, "cofe2@cofe.party") + end end describe "get_cached_by_nickname_or_id" do @@ -2364,13 +2442,16 @@ defmodule Pleroma.UserTest do test "active_user_count/1" do insert(:user) insert(:user, %{local: false}) - insert(:user, %{last_active_at: Timex.shift(NaiveDateTime.utc_now(), weeks: -5)}) - insert(:user, %{last_active_at: Timex.shift(NaiveDateTime.utc_now(), weeks: -3)}) insert(:user, %{last_active_at: NaiveDateTime.utc_now()}) + insert(:user, %{last_active_at: Timex.shift(NaiveDateTime.utc_now(), days: -15)}) + insert(:user, %{last_active_at: Timex.shift(NaiveDateTime.utc_now(), weeks: -6)}) + insert(:user, %{last_active_at: Timex.shift(NaiveDateTime.utc_now(), months: -7)}) + insert(:user, %{last_active_at: Timex.shift(NaiveDateTime.utc_now(), years: -2)}) assert User.active_user_count() == 2 - assert User.active_user_count(6) == 3 - assert User.active_user_count(1) == 1 + assert User.active_user_count(180) == 3 + assert User.active_user_count(365) == 4 + assert User.active_user_count(1000) == 5 end describe "pins" do diff --git a/test/pleroma/web/activity_pub/activity_pub_test.exs b/test/pleroma/web/activity_pub/activity_pub_test.exs index 64e12066e..574ef0d71 100644 --- a/test/pleroma/web/activity_pub/activity_pub_test.exs +++ b/test/pleroma/web/activity_pub/activity_pub_test.exs @@ -776,6 +776,32 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do assert Enum.member?(activities, activity_one) end + test "doesn't return activities from deactivated users" do + _user = insert(:user) + deactivated = insert(:user) + active = insert(:user) + {:ok, activity_one} = CommonAPI.post(deactivated, %{status: "hey!"}) + {:ok, activity_two} = CommonAPI.post(active, %{status: "yay!"}) + {:ok, _updated_user} = User.set_activation(deactivated, false) + + activities = ActivityPub.fetch_activities([], %{}) + + refute Enum.member?(activities, activity_one) + assert Enum.member?(activities, activity_two) + end + + test "always see your own posts even when they address people you block" do + user = insert(:user) + blockee = insert(:user) + + {:ok, _} = User.block(user, blockee) + {:ok, activity} = CommonAPI.post(user, %{status: "hey! @#{blockee.nickname}"}) + + activities = ActivityPub.fetch_activities([], %{blocking_user: user}) + + assert Enum.member?(activities, activity) + end + test "doesn't return transitive interactions concerning blocked users" do blocker = insert(:user) blockee = insert(:user) @@ -875,6 +901,21 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do refute repeat_activity in activities end + test "see your own posts even when they adress actors from blocked domains" do + user = insert(:user) + + domain = "dogwhistle.zone" + domain_user = insert(:user, %{ap_id: "https://#{domain}/@pundit"}) + + {:ok, user} = User.block_domain(user, domain) + + {:ok, activity} = CommonAPI.post(user, %{status: "hey! @#{domain_user.nickname}"}) + + activities = ActivityPub.fetch_activities([], %{blocking_user: user}) + + assert Enum.member?(activities, activity) + end + test "does return activities from followed users on blocked domains" do domain = "meanies.social" domain_user = insert(:user, %{ap_id: "https://#{domain}/@pundit"}) diff --git a/test/pleroma/web/activity_pub/mrf/steal_emoji_policy_test.exs b/test/pleroma/web/activity_pub/mrf/steal_emoji_policy_test.exs index bae57f29a..1b37e4c26 100644 --- a/test/pleroma/web/activity_pub/mrf/steal_emoji_policy_test.exs +++ b/test/pleroma/web/activity_pub/mrf/steal_emoji_policy_test.exs @@ -9,11 +9,6 @@ defmodule Pleroma.Web.ActivityPub.MRF.StealEmojiPolicyTest do alias Pleroma.Emoji alias Pleroma.Web.ActivityPub.MRF.StealEmojiPolicy - setup_all do - Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) - :ok - end - setup do emoji_path = [:instance, :static_dir] |> Config.get() |> Path.join("emoji/stolen") @@ -49,6 +44,10 @@ defmodule Pleroma.Web.ActivityPub.MRF.StealEmojiPolicyTest do refute "firedfox" in installed() refute File.exists?(path) + Tesla.Mock.mock(fn %{method: :get, url: "https://example.org/emoji/firedfox.png"} -> + %Tesla.Env{status: 200, body: File.read!("test/fixtures/image.jpg")} + end) + clear_config(:mrf_steal_emoji, hosts: ["example.org"], size_limit: 284_468) assert {:ok, _message} = StealEmojiPolicy.filter(message) @@ -78,6 +77,10 @@ defmodule Pleroma.Web.ActivityPub.MRF.StealEmojiPolicyTest do test "reject if size is above the limit", %{message: message} do refute "firedfox" in installed() + Tesla.Mock.mock(fn %{method: :get, url: "https://example.org/emoji/firedfox.png"} -> + %Tesla.Env{status: 200, body: File.read!("test/fixtures/image.jpg")} + end) + clear_config(:mrf_steal_emoji, hosts: ["example.org"], size_limit: 50_000) assert {:ok, _message} = StealEmojiPolicy.filter(message) diff --git a/test/pleroma/web/activity_pub/object_validators/attachment_validator_test.exs b/test/pleroma/web/activity_pub/object_validators/attachment_validator_test.exs index 0e49fda99..9150b8d41 100644 --- a/test/pleroma/web/activity_pub/object_validators/attachment_validator_test.exs +++ b/test/pleroma/web/activity_pub/object_validators/attachment_validator_test.exs @@ -105,5 +105,37 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidatorTest do assert attachment.mediaType == "image/jpeg" end + + test "it transforms image dimentions to our internal format" do + attachment = %{ + "type" => "Document", + "name" => "Hello world", + "url" => "https://media.example.tld/1.jpg", + "width" => 880, + "height" => 960, + "mediaType" => "image/jpeg", + "blurhash" => "eTKL26+HDjcEIBVl;ds+K6t301W.t7nit7y1E,R:v}ai4nXSt7V@of" + } + + expected = %AttachmentValidator{ + type: "Document", + name: "Hello world", + mediaType: "image/jpeg", + blurhash: "eTKL26+HDjcEIBVl;ds+K6t301W.t7nit7y1E,R:v}ai4nXSt7V@of", + url: [ + %AttachmentValidator.UrlObjectValidator{ + type: "Link", + mediaType: "image/jpeg", + href: "https://media.example.tld/1.jpg", + width: 880, + height: 960 + } + ] + } + + {:ok, ^expected} = + AttachmentValidator.cast_and_validate(attachment) + |> Ecto.Changeset.apply_action(:insert) + end end end diff --git a/test/pleroma/web/activity_pub/transmogrifier/add_remove_handling_test.exs b/test/pleroma/web/activity_pub/transmogrifier/add_remove_handling_test.exs index fc7757125..b17c0e7bf 100644 --- a/test/pleroma/web/activity_pub/transmogrifier/add_remove_handling_test.exs +++ b/test/pleroma/web/activity_pub/transmogrifier/add_remove_handling_test.exs @@ -67,7 +67,9 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.AddRemoveHandlingTest do "target" => "https://example.com/users/lain/collections/featured", "type" => "Add", "to" => [Pleroma.Constants.as_public()], - "cc" => ["https://example.com/users/lain/followers"] + "cc" => ["https://example.com/users/lain/followers"], + "bcc" => [], + "bto" => [] } assert {:ok, activity} = Transmogrifier.handle_incoming(message) @@ -82,7 +84,9 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.AddRemoveHandlingTest do "target" => "https://example.com/users/lain/collections/featured", "type" => "Remove", "to" => [Pleroma.Constants.as_public()], - "cc" => ["https://example.com/users/lain/followers"] + "cc" => ["https://example.com/users/lain/followers"], + "bcc" => [], + "bto" => [] } assert {:ok, activity} = Transmogrifier.handle_incoming(remove) @@ -161,7 +165,9 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.AddRemoveHandlingTest do "target" => "https://#{host}/users/#{user.nickname}/collections/featured", "type" => "Add", "to" => [Pleroma.Constants.as_public()], - "cc" => ["https://#{host}/users/#{user.nickname}/followers"] + "cc" => ["https://#{host}/users/#{user.nickname}/followers"], + "bcc" => [], + "bto" => [] } assert {:ok, activity} = Transmogrifier.handle_incoming(message) diff --git a/test/pleroma/web/activity_pub/transmogrifier/video_handling_test.exs b/test/pleroma/web/activity_pub/transmogrifier/video_handling_test.exs index fc3ec7450..87c53ebf4 100644 --- a/test/pleroma/web/activity_pub/transmogrifier/video_handling_test.exs +++ b/test/pleroma/web/activity_pub/transmogrifier/video_handling_test.exs @@ -58,7 +58,8 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.VideoHandlingTest do "href" => "https://peertube.moe/static/webseed/df5f464b-be8d-46fb-ad81-2d4c2d1630e3-480.mp4", "mediaType" => "video/mp4", - "type" => "Link" + "type" => "Link", + "width" => 480 } ] } @@ -79,7 +80,8 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.VideoHandlingTest do "href" => "https://framatube.org/static/webseed/6050732a-8a7a-43d4-a6cd-809525a1d206-1080.mp4", "mediaType" => "video/mp4", - "type" => "Link" + "type" => "Link", + "height" => 1080 } ] } @@ -107,7 +109,8 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.VideoHandlingTest do "href" => "https://peertube.stream/static/streaming-playlists/hls/abece3c3-b9c6-47f4-8040-f3eed8c602e6/abece3c3-b9c6-47f4-8040-f3eed8c602e6-1080-fragmented.mp4", "mediaType" => "video/mp4", - "type" => "Link" + "type" => "Link", + "height" => 1080 } ] } diff --git a/test/pleroma/web/activity_pub/transmogrifier_test.exs b/test/pleroma/web/activity_pub/transmogrifier_test.exs index 5a3b57acb..06daf6a9f 100644 --- a/test/pleroma/web/activity_pub/transmogrifier_test.exs +++ b/test/pleroma/web/activity_pub/transmogrifier_test.exs @@ -524,4 +524,44 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do ) end end + + describe "fix_attachments/1" do + test "puts dimensions into attachment url field" do + object = %{ + "attachment" => [ + %{ + "type" => "Document", + "name" => "Hello world", + "url" => "https://media.example.tld/1.jpg", + "width" => 880, + "height" => 960, + "mediaType" => "image/jpeg", + "blurhash" => "eTKL26+HDjcEIBVl;ds+K6t301W.t7nit7y1E,R:v}ai4nXSt7V@of" + } + ] + } + + expected = %{ + "attachment" => [ + %{ + "type" => "Document", + "name" => "Hello world", + "url" => [ + %{ + "type" => "Link", + "mediaType" => "image/jpeg", + "href" => "https://media.example.tld/1.jpg", + "width" => 880, + "height" => 960 + } + ], + "mediaType" => "image/jpeg", + "blurhash" => "eTKL26+HDjcEIBVl;ds+K6t301W.t7nit7y1E,R:v}ai4nXSt7V@of" + } + ] + } + + assert Transmogrifier.fix_attachments(object) == expected + end + end end diff --git a/test/pleroma/web/admin_api/controllers/admin_api_controller_test.exs b/test/pleroma/web/admin_api/controllers/admin_api_controller_test.exs index 8cd9f939b..f8cd103c6 100644 --- a/test/pleroma/web/admin_api/controllers/admin_api_controller_test.exs +++ b/test/pleroma/web/admin_api/controllers/admin_api_controller_test.exs @@ -267,9 +267,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do log_entry = Repo.one(ModerationLog) assert ModerationLog.get_log_entry_message(log_entry) == - "@#{admin.nickname} revoked admin role from @#{user_one.nickname}, @#{ - user_two.nickname - }" + "@#{admin.nickname} revoked admin role from @#{user_one.nickname}, @#{user_two.nickname}" end end @@ -800,40 +798,6 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do end end - describe "instances" do - test "GET /instances/:instance/statuses", %{conn: conn} do - user = insert(:user, local: false, ap_id: "https://archae.me/users/archaeme") - user2 = insert(:user, local: false, ap_id: "https://test.com/users/test") - insert_pair(:note_activity, user: user) - activity = insert(:note_activity, user: user2) - - %{"total" => 2, "activities" => activities} = - conn |> get("/api/pleroma/admin/instances/archae.me/statuses") |> json_response(200) - - assert length(activities) == 2 - - %{"total" => 1, "activities" => [_]} = - conn |> get("/api/pleroma/admin/instances/test.com/statuses") |> json_response(200) - - %{"total" => 0, "activities" => []} = - conn |> get("/api/pleroma/admin/instances/nonexistent.com/statuses") |> json_response(200) - - CommonAPI.repeat(activity.id, user) - - %{"total" => 2, "activities" => activities} = - conn |> get("/api/pleroma/admin/instances/archae.me/statuses") |> json_response(200) - - assert length(activities) == 2 - - %{"total" => 3, "activities" => activities} = - conn - |> get("/api/pleroma/admin/instances/archae.me/statuses?with_reblogs=true") - |> json_response(200) - - assert length(activities) == 3 - end - end - describe "PATCH /confirm_email" do test "it confirms emails of two users", %{conn: conn, admin: admin} do [first_user, second_user] = insert_pair(:user, is_confirmed: false) @@ -860,9 +824,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do log_entry = Repo.one(ModerationLog) assert ModerationLog.get_log_entry_message(log_entry) == - "@#{admin.nickname} confirmed email for users: @#{first_user.nickname}, @#{ - second_user.nickname - }" + "@#{admin.nickname} confirmed email for users: @#{first_user.nickname}, @#{second_user.nickname}" end end @@ -883,9 +845,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do log_entry = Repo.one(ModerationLog) assert ModerationLog.get_log_entry_message(log_entry) == - "@#{admin.nickname} re-sent confirmation email for users: @#{first_user.nickname}, @#{ - second_user.nickname - }" + "@#{admin.nickname} re-sent confirmation email for users: @#{first_user.nickname}, @#{second_user.nickname}" ObanHelpers.perform_all() diff --git a/test/pleroma/web/admin_api/controllers/instance_controller_test.exs b/test/pleroma/web/admin_api/controllers/instance_controller_test.exs new file mode 100644 index 000000000..c78307fc8 --- /dev/null +++ b/test/pleroma/web/admin_api/controllers/instance_controller_test.exs @@ -0,0 +1,80 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.AdminAPI.InstanceControllerTest do + use Pleroma.Web.ConnCase + use Oban.Testing, repo: Pleroma.Repo + + import Pleroma.Factory + + alias Pleroma.Repo + alias Pleroma.Tests.ObanHelpers + alias Pleroma.Web.CommonAPI + + setup_all do + Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) + + :ok + end + + setup do + admin = insert(:user, is_admin: true) + token = insert(:oauth_admin_token, user: admin) + + conn = + build_conn() + |> assign(:user, admin) + |> assign(:token, token) + + {:ok, %{admin: admin, token: token, conn: conn}} + end + + test "GET /instances/:instance/statuses", %{conn: conn} do + user = insert(:user, local: false, ap_id: "https://archae.me/users/archaeme") + user2 = insert(:user, local: false, ap_id: "https://test.com/users/test") + insert_pair(:note_activity, user: user) + activity = insert(:note_activity, user: user2) + + %{"total" => 2, "activities" => activities} = + conn |> get("/api/pleroma/admin/instances/archae.me/statuses") |> json_response(200) + + assert length(activities) == 2 + + %{"total" => 1, "activities" => [_]} = + conn |> get("/api/pleroma/admin/instances/test.com/statuses") |> json_response(200) + + %{"total" => 0, "activities" => []} = + conn |> get("/api/pleroma/admin/instances/nonexistent.com/statuses") |> json_response(200) + + CommonAPI.repeat(activity.id, user) + + %{"total" => 2, "activities" => activities} = + conn |> get("/api/pleroma/admin/instances/archae.me/statuses") |> json_response(200) + + assert length(activities) == 2 + + %{"total" => 3, "activities" => activities} = + conn + |> get("/api/pleroma/admin/instances/archae.me/statuses?with_reblogs=true") + |> json_response(200) + + assert length(activities) == 3 + end + + test "DELETE /instances/:instance", %{conn: conn} do + user = insert(:user, nickname: "lain@lain.com") + post = insert(:note_activity, user: user) + + response = + conn + |> delete("/api/pleroma/admin/instances/lain.com") + |> json_response(200) + + [:ok] = ObanHelpers.perform_all() + + assert response == "lain.com" + refute Repo.reload(user).is_active + refute Repo.reload(post) + end +end diff --git a/test/pleroma/web/admin_api/controllers/media_proxy_cache_controller_test.exs b/test/pleroma/web/admin_api/controllers/media_proxy_cache_controller_test.exs index 5d872901e..1818c8a8e 100644 --- a/test/pleroma/web/admin_api/controllers/media_proxy_cache_controller_test.exs +++ b/test/pleroma/web/admin_api/controllers/media_proxy_cache_controller_test.exs @@ -47,30 +47,34 @@ defmodule Pleroma.Web.AdminAPI.MediaProxyCacheControllerTest do assert response["page_size"] == 2 assert response["count"] == 5 - assert response["urls"] == [ - "http://localhost:4001/media/fb1f4d.jpg", - "http://localhost:4001/media/a688346.jpg" - ] + results = response["urls"] response = conn |> get("/api/pleroma/admin/media_proxy_caches?page_size=2&page=2") |> json_response_and_validate_schema(200) - assert response["urls"] == [ - "http://localhost:4001/media/gb1f44.jpg", - "http://localhost:4001/media/tb13f47.jpg" - ] - assert response["page_size"] == 2 assert response["count"] == 5 + results = results ++ response["urls"] + response = conn |> get("/api/pleroma/admin/media_proxy_caches?page_size=2&page=3") |> json_response_and_validate_schema(200) - assert response["urls"] == ["http://localhost:4001/media/wb1f46.jpg"] + results = results ++ response["urls"] + + assert results |> Enum.sort() == + [ + "http://localhost:4001/media/wb1f46.jpg", + "http://localhost:4001/media/gb1f44.jpg", + "http://localhost:4001/media/tb13f47.jpg", + "http://localhost:4001/media/fb1f4d.jpg", + "http://localhost:4001/media/a688346.jpg" + ] + |> Enum.sort() end test "search banned MediaProxy URLs", %{conn: conn} do @@ -88,9 +92,9 @@ defmodule Pleroma.Web.AdminAPI.MediaProxyCacheControllerTest do |> get("/api/pleroma/admin/media_proxy_caches?page_size=2&query=F44") |> json_response_and_validate_schema(200) - assert response["urls"] == [ - "http://localhost:4001/media/gb1f44.jpg", - "http://localhost:4001/media/ff44b1f4d.jpg" + assert response["urls"] |> Enum.sort() == [ + "http://localhost:4001/media/ff44b1f4d.jpg", + "http://localhost:4001/media/gb1f44.jpg" ] assert response["page_size"] == 2 diff --git a/test/pleroma/web/admin_api/controllers/report_controller_test.exs b/test/pleroma/web/admin_api/controllers/report_controller_test.exs index 8102845d5..99cc7bbd0 100644 --- a/test/pleroma/web/admin_api/controllers/report_controller_test.exs +++ b/test/pleroma/web/admin_api/controllers/report_controller_test.exs @@ -204,9 +204,7 @@ defmodule Pleroma.Web.AdminAPI.ReportControllerTest do "@#{admin.nickname} updated report ##{id} (on user @#{activity.user_actor.nickname}) with 'resolved' state" assert ModerationLog.get_log_entry_message(second_log_entry) == - "@#{admin.nickname} updated report ##{second_report_id} (on user @#{ - second_activity.user_actor.nickname - }) with 'closed' state" + "@#{admin.nickname} updated report ##{second_report_id} (on user @#{second_activity.user_actor.nickname}) with 'closed' state" end end diff --git a/test/pleroma/web/admin_api/controllers/user_controller_test.exs b/test/pleroma/web/admin_api/controllers/user_controller_test.exs index d9da34f6e..b199fa704 100644 --- a/test/pleroma/web/admin_api/controllers/user_controller_test.exs +++ b/test/pleroma/web/admin_api/controllers/user_controller_test.exs @@ -873,6 +873,56 @@ defmodule Pleroma.Web.AdminAPI.UserControllerTest do "@#{admin.nickname} approved users: @#{user_one.nickname}, @#{user_two.nickname}" end + test "PATCH /api/pleroma/admin/users/suggest", %{admin: admin, conn: conn} do + user1 = insert(:user, is_suggested: false) + user2 = insert(:user, is_suggested: false) + + response = + conn + |> put_req_header("content-type", "application/json") + |> patch( + "/api/pleroma/admin/users/suggest", + %{nicknames: [user1.nickname, user2.nickname]} + ) + |> json_response_and_validate_schema(200) + + assert Enum.map(response["users"], & &1["is_suggested"]) == [true, true] + [user1, user2] = Repo.reload!([user1, user2]) + + assert user1.is_suggested + assert user2.is_suggested + + log_entry = Repo.one(ModerationLog) + + assert ModerationLog.get_log_entry_message(log_entry) == + "@#{admin.nickname} added suggested users: @#{user1.nickname}, @#{user2.nickname}" + end + + test "PATCH /api/pleroma/admin/users/unsuggest", %{admin: admin, conn: conn} do + user1 = insert(:user, is_suggested: true) + user2 = insert(:user, is_suggested: true) + + response = + conn + |> put_req_header("content-type", "application/json") + |> patch( + "/api/pleroma/admin/users/unsuggest", + %{nicknames: [user1.nickname, user2.nickname]} + ) + |> json_response_and_validate_schema(200) + + assert Enum.map(response["users"], & &1["is_suggested"]) == [false, false] + [user1, user2] = Repo.reload!([user1, user2]) + + refute user1.is_suggested + refute user2.is_suggested + + log_entry = Repo.one(ModerationLog) + + assert ModerationLog.get_log_entry_message(log_entry) == + "@#{admin.nickname} removed suggested users: @#{user1.nickname}, @#{user2.nickname}" + end + test "PATCH /api/pleroma/admin/users/:nickname/toggle_activation", %{admin: admin, conn: conn} do user = insert(:user) @@ -906,6 +956,7 @@ defmodule Pleroma.Web.AdminAPI.UserControllerTest do "display_name" => HTML.strip_tags(user.name || user.nickname), "is_confirmed" => true, "is_approved" => true, + "is_suggested" => false, "url" => user.ap_id, "registration_reason" => nil, "actor_type" => "Person", diff --git a/test/pleroma/web/common_api/utils_test.exs b/test/pleroma/web/common_api/utils_test.exs index d8fec3520..fc01f820a 100644 --- a/test/pleroma/web/common_api/utils_test.exs +++ b/test/pleroma/web/common_api/utils_test.exs @@ -160,11 +160,7 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do {output, _, _} = Utils.format_input(text, "text/markdown") assert output == - ~s(<p><strong>hello world</strong></p><p><em>another <span class="h-card"><a class="u-url mention" data-user="#{ - user.id - }" href="http://foo.com/user__test" rel="ugc">@<span>user__test</span></a></span> and <span class="h-card"><a class="u-url mention" data-user="#{ - user.id - }" href="http://foo.com/user__test" rel="ugc">@<span>user__test</span></a></span> <a href="http://google.com" rel="ugc">google.com</a> paragraph</em></p>) + ~s(<p><strong>hello world</strong></p><p><em>another <span class="h-card"><a class="u-url mention" data-user="#{user.id}" href="http://foo.com/user__test" rel="ugc">@<span>user__test</span></a></span> and <span class="h-card"><a class="u-url mention" data-user="#{user.id}" href="http://foo.com/user__test" rel="ugc">@<span>user__test</span></a></span> <a href="http://google.com" rel="ugc">google.com</a> paragraph</em></p>) end end @@ -201,11 +197,7 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do {result, _, []} = Utils.format_input(code, "text/markdown") assert result == - ~s[<p><span class="h-card"><a class="u-url mention" data-user="#{mario.id}" href="#{ - mario.ap_id - }" rel="ugc">@<span>mario</span></a></span> <span class="h-card"><a class="u-url mention" data-user="#{ - luigi.id - }" href="#{luigi.ap_id}" rel="ugc">@<span>luigi</span></a></span> yo what’s up?</p>] + ~s[<p><span class="h-card"><a class="u-url mention" data-user="#{mario.id}" href="#{mario.ap_id}" rel="ugc">@<span>mario</span></a></span> <span class="h-card"><a class="u-url mention" data-user="#{luigi.id}" href="#{luigi.ap_id}" rel="ugc">@<span>luigi</span></a></span> yo what’s up?</p>] end test "remote mentions" do @@ -216,11 +208,7 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do {result, _, []} = Utils.format_input(code, "text/markdown") assert result == - ~s[<p><span class="h-card"><a class="u-url mention" data-user="#{mario.id}" href="#{ - mario.ap_id - }" rel="ugc">@<span>mario</span></a></span> <span class="h-card"><a class="u-url mention" data-user="#{ - luigi.id - }" href="#{luigi.ap_id}" rel="ugc">@<span>luigi</span></a></span> yo what’s up?</p>] + ~s[<p><span class="h-card"><a class="u-url mention" data-user="#{mario.id}" href="#{mario.ap_id}" rel="ugc">@<span>mario</span></a></span> <span class="h-card"><a class="u-url mention" data-user="#{luigi.id}" href="#{luigi.ap_id}" rel="ugc">@<span>luigi</span></a></span> yo what’s up?</p>] end test "raw HTML" do diff --git a/test/pleroma/web/common_api_test.exs b/test/pleroma/web/common_api_test.exs index 4a10a5bc4..ad0b87543 100644 --- a/test/pleroma/web/common_api_test.exs +++ b/test/pleroma/web/common_api_test.exs @@ -209,9 +209,7 @@ defmodule Pleroma.Web.CommonAPITest do object = Object.normalize(activity, fetch: false) assert object.data["content"] == - "<a href=\"https://example.org\" rel=\"ugc\">https://example.org</a> is the site of <span class=\"h-card\"><a class=\"u-url mention\" data-user=\"#{ - other_user.id - }\" href=\"#{other_user.ap_id}\" rel=\"ugc\">@<span>#{other_user.nickname}</span></a></span> <a class=\"hashtag\" data-tag=\"2hu\" href=\"http://localhost:4001/tag/2hu\">#2hu</a>" + "<a href=\"https://example.org\" rel=\"ugc\">https://example.org</a> is the site of <span class=\"h-card\"><a class=\"u-url mention\" data-user=\"#{other_user.id}\" href=\"#{other_user.ap_id}\" rel=\"ugc\">@<span>#{other_user.nickname}</span></a></span> <a class=\"hashtag\" data-tag=\"2hu\" href=\"http://localhost:4001/tag/2hu\">#2hu</a>" end test "it posts a chat message" do diff --git a/test/pleroma/web/feed/user_controller_test.exs b/test/pleroma/web/feed/user_controller_test.exs index 6f6ff433f..6e3f790b2 100644 --- a/test/pleroma/web/feed/user_controller_test.exs +++ b/test/pleroma/web/feed/user_controller_test.exs @@ -196,13 +196,26 @@ defmodule Pleroma.Web.Feed.UserControllerTest do ).resp_body end - test "with html format, it returns error when user is not found", %{conn: conn} do + test "with html format, it falls back to frontend when user is remote", %{conn: conn} do + user = insert(:user, local: false) + + {:ok, _} = CommonAPI.post(user, %{status: "test"}) + + response = + conn + |> get("/users/#{user.nickname}") + |> response(200) + + assert response =~ "</html>" + end + + test "with html format, it falls back to frontend when user is not found", %{conn: conn} do response = conn |> get("/users/jimm") - |> json_response(404) + |> response(200) - assert response == %{"error" => "Not found"} + assert response =~ "</html>" end test "with non-html / non-json format, it redirects to user feed in atom format", %{ diff --git a/test/pleroma/web/manifest_controller_test.exs b/test/pleroma/web/manifest_controller_test.exs new file mode 100644 index 000000000..b7a4940db --- /dev/null +++ b/test/pleroma/web/manifest_controller_test.exs @@ -0,0 +1,17 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ManifestControllerTest do + use Pleroma.Web.ConnCase + + setup do + clear_config([:instance, :name], "Manifest Test") + clear_config([:manifest, :theme_color], "#ff0000") + end + + test "manifest.json", %{conn: conn} do + conn = get(conn, "/manifest.json") + assert %{"name" => "Manifest Test", "theme_color" => "#ff0000"} = json_response(conn, 200) + end +end diff --git a/test/pleroma/web/mastodon_api/controllers/account_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/account_controller_test.exs index 3036e25b3..a92a58224 100644 --- a/test/pleroma/web/mastodon_api/controllers/account_controller_test.exs +++ b/test/pleroma/web/mastodon_api/controllers/account_controller_test.exs @@ -709,9 +709,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do assert [%{"id" => ^follower2_id}, %{"id" => ^follower1_id}] = conn |> get( - "/api/v1/accounts/#{user.id}/followers?id=#{user.id}&limit=20&max_id=#{ - follower3_id - }" + "/api/v1/accounts/#{user.id}/followers?id=#{user.id}&limit=20&max_id=#{follower3_id}" ) |> json_response_and_validate_schema(200) diff --git a/test/pleroma/web/mastodon_api/controllers/notification_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/notification_controller_test.exs index 2615912a8..d991f284f 100644 --- a/test/pleroma/web/mastodon_api/controllers/notification_controller_test.exs +++ b/test/pleroma/web/mastodon_api/controllers/notification_controller_test.exs @@ -44,9 +44,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do |> get("/api/v1/notifications") expected_response = - "hi <span class=\"h-card\"><a class=\"u-url mention\" data-user=\"#{user.id}\" href=\"#{ - user.ap_id - }\" rel=\"ugc\">@<span>#{user.nickname}</span></a></span>" + "hi <span class=\"h-card\"><a class=\"u-url mention\" data-user=\"#{user.id}\" href=\"#{user.ap_id}\" rel=\"ugc\">@<span>#{user.nickname}</span></a></span>" assert [%{"status" => %{"content" => response}} | _rest] = json_response_and_validate_schema(conn, 200) @@ -103,6 +101,25 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do assert [_] = result end + test "excludes mentions from blockers when blockers_visible is false" do + clear_config([:activitypub, :blockers_visible], false) + + %{user: user, conn: conn} = oauth_access(["read:notifications"]) + blocker = insert(:user) + + {:ok, _} = CommonAPI.block(blocker, user) + {:ok, activity} = CommonAPI.post(blocker, %{status: "hi @#{user.nickname}"}) + + {:ok, [_notification]} = Notification.create_notifications(activity) + + conn = + conn + |> assign(:user, user) + |> get("/api/v1/notifications") + + assert [] == json_response_and_validate_schema(conn, 200) + end + test "getting a single notification" do %{user: user, conn: conn} = oauth_access(["read:notifications"]) other_user = insert(:user) @@ -114,9 +131,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do conn = get(conn, "/api/v1/notifications/#{notification.id}") expected_response = - "hi <span class=\"h-card\"><a class=\"u-url mention\" data-user=\"#{user.id}\" href=\"#{ - user.ap_id - }\" rel=\"ugc\">@<span>#{user.nickname}</span></a></span>" + "hi <span class=\"h-card\"><a class=\"u-url mention\" data-user=\"#{user.id}\" href=\"#{user.ap_id}\" rel=\"ugc\">@<span>#{user.nickname}</span></a></span>" assert %{"status" => %{"content" => response}} = json_response_and_validate_schema(conn, 200) assert response == expected_response diff --git a/test/pleroma/web/mastodon_api/controllers/search_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/search_controller_test.exs index 7b0bbd8bd..e31cd0291 100644 --- a/test/pleroma/web/mastodon_api/controllers/search_controller_test.exs +++ b/test/pleroma/web/mastodon_api/controllers/search_controller_test.exs @@ -125,13 +125,7 @@ defmodule Pleroma.Web.MastodonAPI.SearchControllerTest do results = conn |> get( - "/api/v2/search?#{ - URI.encode_query(%{ - q: - "https://www.washingtonpost.com/sports/2020/06/10/" <> - "nascar-ban-display-confederate-flag-all-events-properties/" - }) - }" + "/api/v2/search?#{URI.encode_query(%{q: "https://www.washingtonpost.com/sports/2020/06/10/" <> "nascar-ban-display-confederate-flag-all-events-properties/"})}" ) |> json_response_and_validate_schema(200) @@ -156,9 +150,7 @@ defmodule Pleroma.Web.MastodonAPI.SearchControllerTest do results = conn |> get( - "/api/v2/search?#{ - URI.encode_query(%{q: "#some #text #with #hashtags", limit: 2, offset: 1}) - }" + "/api/v2/search?#{URI.encode_query(%{q: "#some #text #with #hashtags", limit: 2, offset: 1})}" ) |> json_response_and_validate_schema(200) diff --git a/test/pleroma/web/mastodon_api/controllers/suggestion_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/suggestion_controller_test.exs index 168966fc9..89273e67b 100644 --- a/test/pleroma/web/mastodon_api/controllers/suggestion_controller_test.exs +++ b/test/pleroma/web/mastodon_api/controllers/suggestion_controller_test.exs @@ -4,8 +4,11 @@ defmodule Pleroma.Web.MastodonAPI.SuggestionControllerTest do use Pleroma.Web.ConnCase, async: true + alias Pleroma.UserRelationship + alias Pleroma.Web.CommonAPI + import Pleroma.Factory - setup do: oauth_access(["read"]) + setup do: oauth_access(["read", "write"]) test "returns empty result", %{conn: conn} do res = @@ -15,4 +18,66 @@ defmodule Pleroma.Web.MastodonAPI.SuggestionControllerTest do assert res == [] end + + test "returns v2 suggestions", %{conn: conn} do + %{id: user_id} = insert(:user, is_suggested: true) + + res = + conn + |> get("/api/v2/suggestions") + |> json_response_and_validate_schema(200) + + assert [%{"source" => "staff", "account" => %{"id" => ^user_id}}] = res + end + + test "returns v2 suggestions excluding dismissed accounts", %{conn: conn} do + %{id: user_id} = insert(:user, is_suggested: true) + + conn + |> delete("/api/v1/suggestions/#{user_id}") + |> json_response_and_validate_schema(200) + + res = + conn + |> get("/api/v2/suggestions") + |> json_response_and_validate_schema(200) + + assert [] = res + end + + test "returns v2 suggestions excluding blocked accounts", %{conn: conn, user: blocker} do + blocked = insert(:user, is_suggested: true) + {:ok, _} = CommonAPI.block(blocker, blocked) + + res = + conn + |> get("/api/v2/suggestions") + |> json_response_and_validate_schema(200) + + assert [] = res + end + + test "returns v2 suggestions excluding followed accounts", %{conn: conn, user: follower} do + followed = insert(:user, is_suggested: true) + {:ok, _, _, _} = CommonAPI.follow(follower, followed) + + res = + conn + |> get("/api/v2/suggestions") + |> json_response_and_validate_schema(200) + + assert [] = res + end + + test "dismiss suggestion", %{conn: conn, user: source} do + target = insert(:user, is_suggested: true) + + res = + conn + |> delete("/api/v1/suggestions/#{target.id}") + |> json_response_and_validate_schema(200) + + assert res == %{} + assert UserRelationship.exists?(:suggestion_dismiss, source, target) + end end diff --git a/test/pleroma/web/mastodon_api/controllers/timeline_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/timeline_controller_test.exs index ed1286675..187982d92 100644 --- a/test/pleroma/web/mastodon_api/controllers/timeline_controller_test.exs +++ b/test/pleroma/web/mastodon_api/controllers/timeline_controller_test.exs @@ -273,6 +273,24 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do [%{"id" => ^reply_from_me}, %{"id" => ^activity_id}] = response end + test "doesn't return posts from users who blocked you when :blockers_visible is disabled" do + clear_config([:activitypub, :blockers_visible], false) + + %{conn: conn, user: blockee} = oauth_access(["read:statuses"]) + blocker = insert(:user) + {:ok, _} = User.block(blocker, blockee) + + conn = assign(conn, :user, blockee) + + {:ok, _} = CommonAPI.post(blocker, %{status: "hey!"}) + + response = + get(conn, "/api/v1/timelines/public") + |> json_response_and_validate_schema(200) + + assert length(response) == 0 + end + test "doesn't return replies if follow is posting with users from blocked domain" do %{conn: conn, user: blocker} = oauth_access(["read:statuses"]) friend = insert(:user) diff --git a/test/pleroma/web/mastodon_api/update_credentials_test.exs b/test/pleroma/web/mastodon_api/update_credentials_test.exs index cf8ccf187..1d2027899 100644 --- a/test/pleroma/web/mastodon_api/update_credentials_test.exs +++ b/test/pleroma/web/mastodon_api/update_credentials_test.exs @@ -88,9 +88,7 @@ defmodule Pleroma.Web.MastodonAPI.UpdateCredentialsTest do assert user_data = json_response_and_validate_schema(conn, 200) assert user_data["note"] == - ~s(I drink <a class="hashtag" data-tag="cofe" href="http://localhost:4001/tag/cofe">#cofe</a> with <span class="h-card"><a class="u-url mention" data-user="#{ - user2.id - }" href="#{user2.ap_id}" rel="ugc">@<span>#{user2.nickname}</span></a></span><br/><br/>suya..) + ~s(I drink <a class="hashtag" data-tag="cofe" href="http://localhost:4001/tag/cofe">#cofe</a> with <span class="h-card"><a class="u-url mention" data-user="#{user2.id}" href="#{user2.ap_id}" rel="ugc">@<span>#{user2.nickname}</span></a></span><br/><br/>suya..) assert user_data["source"]["note"] == raw_bio diff --git a/test/pleroma/web/mastodon_api/views/account_view_test.exs b/test/pleroma/web/mastodon_api/views/account_view_test.exs index 60881756d..9af588778 100644 --- a/test/pleroma/web/mastodon_api/views/account_view_test.exs +++ b/test/pleroma/web/mastodon_api/views/account_view_test.exs @@ -83,6 +83,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do tags: [], is_admin: false, is_moderator: false, + is_suggested: false, hide_favorites: true, hide_followers: false, hide_follows: false, @@ -183,6 +184,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do tags: [], is_admin: false, is_moderator: false, + is_suggested: false, hide_favorites: true, hide_followers: false, hide_follows: false, diff --git a/test/pleroma/web/mastodon_api/views/suggestion_view_test.exs b/test/pleroma/web/mastodon_api/views/suggestion_view_test.exs new file mode 100644 index 000000000..5aae36ce9 --- /dev/null +++ b/test/pleroma/web/mastodon_api/views/suggestion_view_test.exs @@ -0,0 +1,34 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.MastodonAPI.SuggestionViewTest do + use Pleroma.DataCase, async: true + import Pleroma.Factory + alias Pleroma.Web.MastodonAPI.SuggestionView, as: View + + test "show.json" do + user = insert(:user, is_suggested: true) + json = View.render("show.json", %{user: user, source: :staff, skip_visibility_check: true}) + + assert json.source == :staff + assert json.account.id == user.id + end + + test "index.json" do + user1 = insert(:user, is_suggested: true) + user2 = insert(:user, is_suggested: true) + user3 = insert(:user, is_suggested: true) + + [suggestion1, suggestion2, suggestion3] = + View.render("index.json", %{ + users: [user1, user2, user3], + source: :staff, + skip_visibility_check: true + }) + + assert suggestion1.source == :staff + assert suggestion2.account.id == user2.id + assert suggestion3.account.url == user3.ap_id + end +end diff --git a/test/pleroma/web/media_proxy/media_proxy_controller_test.exs b/test/pleroma/web/media_proxy/media_proxy_controller_test.exs index 2a449e56d..1f2e54194 100644 --- a/test/pleroma/web/media_proxy/media_proxy_controller_test.exs +++ b/test/pleroma/web/media_proxy/media_proxy_controller_test.exs @@ -81,9 +81,7 @@ defmodule Pleroma.Web.MediaProxy.MediaProxyControllerTest do missing_dependencies = Pleroma.Helpers.MediaHelper.missing_dependencies() assert missing_dependencies == [], - "Error: missing dependencies (please refer to `docs/installation`): #{ - inspect(missing_dependencies) - }" + "Error: missing dependencies (please refer to `docs/installation`): #{inspect(missing_dependencies)}" end setup do diff --git a/test/pleroma/web/pleroma_api/controllers/account_controller_test.exs b/test/pleroma/web/pleroma_api/controllers/account_controller_test.exs index 9f14c5577..ad271c31b 100644 --- a/test/pleroma/web/pleroma_api/controllers/account_controller_test.exs +++ b/test/pleroma/web/pleroma_api/controllers/account_controller_test.exs @@ -174,9 +174,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do response = conn |> get( - "/api/v1/pleroma/accounts/#{user.id}/favourites?since_id=#{third_activity.id}&max_id=#{ - seventh_activity.id - }" + "/api/v1/pleroma/accounts/#{user.id}/favourites?since_id=#{third_activity.id}&max_id=#{seventh_activity.id}" ) |> json_response_and_validate_schema(:ok) diff --git a/test/pleroma/web/plugs/frontend_static_plug_test.exs b/test/pleroma/web/plugs/frontend_static_plug_test.exs index a9342e6f0..52379b86a 100644 --- a/test/pleroma/web/plugs/frontend_static_plug_test.exs +++ b/test/pleroma/web/plugs/frontend_static_plug_test.exs @@ -94,7 +94,10 @@ defmodule Pleroma.Web.Plugs.FrontendStaticPlugTest do "internal", ".well-known", "nodeinfo", + "manifest.json", + "auth", "proxy", + "phoenix", "test", "user_exists", "check_password" diff --git a/test/pleroma/web/rich_media/parser/ttl/aws_signed_url_test.exs b/test/pleroma/web/rich_media/parser/ttl/aws_signed_url_test.exs index df3ea3e99..0c8203417 100644 --- a/test/pleroma/web/rich_media/parser/ttl/aws_signed_url_test.exs +++ b/test/pleroma/web/rich_media/parser/ttl/aws_signed_url_test.exs @@ -66,9 +66,7 @@ defmodule Pleroma.Web.RichMedia.Parser.TTL.AwsSignedUrlTest do end defp construct_s3_url(timestamp, valid_till) do - "https://pleroma.s3.ap-southeast-1.amazonaws.com/sachin%20%281%29%20_a%20-%25%2Aasdasd%20BNN%20bnnn%20.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIBLWWK6RGDQXDLJQ%2F20190716%2Fap-southeast-1%2Fs3%2Faws4_request&X-Amz-Date=#{ - timestamp - }&X-Amz-Expires=#{valid_till}&X-Amz-Signature=04ffd6b98634f4b1bbabc62e0fac4879093cd54a6eed24fe8eb38e8369526bbf&X-Amz-SignedHeaders=host" + "https://pleroma.s3.ap-southeast-1.amazonaws.com/sachin%20%281%29%20_a%20-%25%2Aasdasd%20BNN%20bnnn%20.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIBLWWK6RGDQXDLJQ%2F20190716%2Fap-southeast-1%2Fs3%2Faws4_request&X-Amz-Date=#{timestamp}&X-Amz-Expires=#{valid_till}&X-Amz-Signature=04ffd6b98634f4b1bbabc62e0fac4879093cd54a6eed24fe8eb38e8369526bbf&X-Amz-SignedHeaders=host" end defp construct_metadata(timestamp, valid_till, url) do diff --git a/test/pleroma/web/twitter_api/password_controller_test.exs b/test/pleroma/web/twitter_api/password_controller_test.exs index cf99e2434..45ab10a8a 100644 --- a/test/pleroma/web/twitter_api/password_controller_test.exs +++ b/test/pleroma/web/twitter_api/password_controller_test.exs @@ -5,10 +5,14 @@ defmodule Pleroma.Web.TwitterAPI.PasswordControllerTest do use Pleroma.Web.ConnCase + alias Pleroma.Config alias Pleroma.PasswordResetToken + alias Pleroma.Repo + alias Pleroma.Tests.ObanHelpers alias Pleroma.User alias Pleroma.Web.OAuth.Token import Pleroma.Factory + import Swoosh.TestAssertions describe "GET /api/pleroma/password_reset/token" do test "it returns error when token invalid", %{conn: conn} do @@ -116,4 +120,94 @@ defmodule Pleroma.Web.TwitterAPI.PasswordControllerTest do assert User.get_by_id(user.id).password_reset_pending == false end end + + describe "POST /auth/password, with valid parameters" do + setup %{conn: conn} do + user = insert(:user) + conn = post(conn, "/auth/password?email=#{user.email}") + %{conn: conn, user: user} + end + + test "it returns 204", %{conn: conn} do + assert empty_json_response(conn) + end + + test "it creates a PasswordResetToken record for user", %{user: user} do + token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id) + assert token_record + end + + test "it sends an email to user", %{user: user} do + ObanHelpers.perform_all() + token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id) + + email = Pleroma.Emails.UserEmail.password_reset_email(user, token_record.token) + notify_email = Config.get([:instance, :notify_email]) + instance_name = Config.get([:instance, :name]) + + assert_email_sent( + from: {instance_name, notify_email}, + to: {user.name, user.email}, + html_body: email.html_body + ) + end + end + + describe "POST /auth/password, with nickname" do + test "it returns 204", %{conn: conn} do + user = insert(:user) + + assert conn + |> post("/auth/password?nickname=#{user.nickname}") + |> empty_json_response() + + ObanHelpers.perform_all() + token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id) + + email = Pleroma.Emails.UserEmail.password_reset_email(user, token_record.token) + notify_email = Config.get([:instance, :notify_email]) + instance_name = Config.get([:instance, :name]) + + assert_email_sent( + from: {instance_name, notify_email}, + to: {user.name, user.email}, + html_body: email.html_body + ) + end + + test "it doesn't fail when a user has no email", %{conn: conn} do + user = insert(:user, %{email: nil}) + + assert conn + |> post("/auth/password?nickname=#{user.nickname}") + |> empty_json_response() + end + end + + describe "POST /auth/password, with invalid parameters" do + setup do + user = insert(:user) + {:ok, user: user} + end + + test "it returns 204 when user is not found", %{conn: conn, user: user} do + conn = post(conn, "/auth/password?email=nonexisting_#{user.email}") + + assert empty_json_response(conn) + end + + test "it returns 204 when user is not local", %{conn: conn, user: user} do + {:ok, user} = Repo.update(Ecto.Changeset.change(user, local: false)) + conn = post(conn, "/auth/password?email=#{user.email}") + + assert empty_json_response(conn) + end + + test "it returns 204 when user is deactivated", %{conn: conn, user: user} do + {:ok, user} = Repo.update(Ecto.Changeset.change(user, is_active: false, local: true)) + conn = post(conn, "/auth/password?email=#{user.email}") + + assert empty_json_response(conn) + end + end end diff --git a/test/pleroma/web/twitter_api/twitter_api_test.exs b/test/pleroma/web/twitter_api/twitter_api_test.exs index 85629be04..2b8a4c3f5 100644 --- a/test/pleroma/web/twitter_api/twitter_api_test.exs +++ b/test/pleroma/web/twitter_api/twitter_api_test.exs @@ -139,9 +139,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do {:ok, user2} = TwitterAPI.register_user(data2) expected_text = - ~s(<span class="h-card"><a class="u-url mention" data-user="#{user1.id}" href="#{ - user1.ap_id - }" rel="ugc">@<span>john</span></a></span> test) + ~s(<span class="h-card"><a class="u-url mention" data-user="#{user1.id}" href="#{user1.ap_id}" rel="ugc">@<span>john</span></a></span> test) assert user2.bio == expected_text end diff --git a/test/pleroma/web/twitter_api/util_controller_test.exs b/test/pleroma/web/twitter_api/util_controller_test.exs index f030483d8..ee658ddf6 100644 --- a/test/pleroma/web/twitter_api/util_controller_test.exs +++ b/test/pleroma/web/twitter_api/util_controller_test.exs @@ -26,11 +26,7 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do test "it updates notification settings", %{user: user, conn: conn} do conn |> put( - "/api/pleroma/notification_settings?#{ - URI.encode_query(%{ - block_from_strangers: true - }) - }" + "/api/pleroma/notification_settings?#{URI.encode_query(%{block_from_strangers: true})}" ) |> json_response_and_validate_schema(:ok) @@ -45,11 +41,7 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do test "it updates notification settings to enable hiding contents", %{user: user, conn: conn} do conn |> put( - "/api/pleroma/notification_settings?#{ - URI.encode_query(%{ - hide_notification_contents: 1 - }) - }" + "/api/pleroma/notification_settings?#{URI.encode_query(%{hide_notification_contents: 1})}" ) |> json_response_and_validate_schema(:ok) @@ -302,9 +294,22 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do assert %{"error" => "Missing field: email."} = json_response_and_validate_schema(conn, 400) end - test "with proper permissions, valid password and blank email", %{ - conn: conn - } do + test "with proper permissions, valid password and blank email, when instance requires user email", + %{ + conn: conn + } do + orig_account_activation_required = + Pleroma.Config.get([:instance, :account_activation_required]) + + Pleroma.Config.put([:instance, :account_activation_required], true) + + on_exit(fn -> + Pleroma.Config.put( + [:instance, :account_activation_required], + orig_account_activation_required + ) + end) + conn = conn |> put_req_header("content-type", "multipart/form-data") @@ -313,6 +318,30 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do assert json_response_and_validate_schema(conn, 200) == %{"error" => "Email can't be blank."} end + test "with proper permissions, valid password and blank email, when instance does not require user email", + %{ + conn: conn + } do + orig_account_activation_required = + Pleroma.Config.get([:instance, :account_activation_required]) + + Pleroma.Config.put([:instance, :account_activation_required], false) + + on_exit(fn -> + Pleroma.Config.put( + [:instance, :account_activation_required], + orig_account_activation_required + ) + end) + + conn = + conn + |> put_req_header("content-type", "multipart/form-data") + |> post("/api/pleroma/change_email", %{password: "test", email: ""}) + + assert json_response_and_validate_schema(conn, 200) == %{"status" => "success"} + end + test "with proper permissions, valid password and non unique email", %{ conn: conn } do @@ -444,7 +473,10 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do test "with proper permissions and wrong or missing password", %{conn: conn} do for params <- [%{"password" => "hi"}, %{}] do - ret_conn = post(conn, "/api/pleroma/delete_account", params) + ret_conn = + conn + |> put_req_header("content-type", "application/json") + |> post("/api/pleroma/delete_account", params) assert json_response_and_validate_schema(ret_conn, 200) == %{ "error" => "Invalid password." @@ -452,8 +484,28 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do end end - test "with proper permissions and valid password", %{conn: conn, user: user} do - conn = post(conn, "/api/pleroma/delete_account?password=test") + test "with proper permissions and valid password (URL query)", %{conn: conn, user: user} do + conn = + conn + |> put_req_header("content-type", "application/json") + |> post("/api/pleroma/delete_account?password=test") + + ObanHelpers.perform_all() + assert json_response_and_validate_schema(conn, 200) == %{"status" => "success"} + + user = User.get_by_id(user.id) + refute user.is_active + assert user.name == nil + assert user.bio == "" + assert user.password_hash == nil + end + + test "with proper permissions and valid password (JSON body)", %{conn: conn, user: user} do + conn = + conn + |> put_req_header("content-type", "application/json") + |> post("/api/pleroma/delete_account", %{password: "test"}) + ObanHelpers.perform_all() assert json_response_and_validate_schema(conn, 200) == %{"status" => "success"} diff --git a/test/pleroma/web/web_finger/web_finger_controller_test.exs b/test/pleroma/web/web_finger/web_finger_controller_test.exs index 2421c5800..66d79320f 100644 --- a/test/pleroma/web/web_finger/web_finger_controller_test.exs +++ b/test/pleroma/web/web_finger/web_finger_controller_test.exs @@ -24,9 +24,7 @@ defmodule Pleroma.Web.WebFinger.WebFingerControllerTest do assert response.status == 200 assert response.resp_body == - ~s(<?xml version="1.0" encoding="UTF-8"?><XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0"><Link rel="lrdd" template="#{ - Pleroma.Web.Endpoint.url() - }/.well-known/webfinger?resource={uri}" type="application/xrd+xml" /></XRD>) + ~s(<?xml version="1.0" encoding="UTF-8"?><XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0"><Link rel="lrdd" template="#{Pleroma.Web.Endpoint.url()}/.well-known/webfinger?resource={uri}" type="application/xrd+xml" /></XRD>) end test "Webfinger JRD" do diff --git a/test/support/api_spec_helpers.ex b/test/support/api_spec_helpers.ex index 36d6a8b81..886e72d73 100644 --- a/test/support/api_spec_helpers.ex +++ b/test/support/api_spec_helpers.ex @@ -29,9 +29,7 @@ defmodule Pleroma.Tests.ApiSpecHelpers do end) flunk( - "Value does not conform to schema #{schema.title}: #{Enum.join(errors, "\n")}\n#{ - inspect(value) - }" + "Value does not conform to schema #{schema.title}: #{Enum.join(errors, "\n")}\n#{inspect(value)}" ) end end diff --git a/test/support/conn_case.ex b/test/support/conn_case.ex index deee98599..eab469833 100644 --- a/test/support/conn_case.ex +++ b/test/support/conn_case.ex @@ -102,9 +102,7 @@ defmodule Pleroma.Web.ConnCase do end) flunk( - "Response does not conform to schema of #{op_id} operation: #{ - Enum.join(errors, "\n") - }\n#{inspect(json)}" + "Response does not conform to schema of #{op_id} operation: #{Enum.join(errors, "\n")}\n#{inspect(json)}" ) end end diff --git a/test/support/http_request_mock.ex b/test/support/http_request_mock.ex index 8807c2d14..94900dc14 100644 --- a/test/support/http_request_mock.ex +++ b/test/support/http_request_mock.ex @@ -1313,9 +1313,7 @@ defmodule HttpRequestMock do def get(url, query, body, headers) do {:error, - "Mock response not implemented for GET #{inspect(url)}, #{query}, #{inspect(body)}, #{ - inspect(headers) - }"} + "Mock response not implemented for GET #{inspect(url)}, #{query}, #{inspect(body)}, #{inspect(headers)}"} end # POST Requests @@ -1381,9 +1379,7 @@ defmodule HttpRequestMock do def post(url, query, body, headers) do {:error, - "Mock response not implemented for POST #{inspect(url)}, #{query}, #{inspect(body)}, #{ - inspect(headers) - }"} + "Mock response not implemented for POST #{inspect(url)}, #{query}, #{inspect(body)}, #{inspect(headers)}"} end # Most of the rich media mocks are missing HEAD requests, so we just return 404. @@ -1398,8 +1394,6 @@ defmodule HttpRequestMock do def head(url, query, body, headers) do {:error, - "Mock response not implemented for HEAD #{inspect(url)}, #{query}, #{inspect(body)}, #{ - inspect(headers) - }"} + "Mock response not implemented for HEAD #{inspect(url)}, #{query}, #{inspect(body)}, #{inspect(headers)}"} end end |