From ec1452fd1cdb9cb1db9b8bad872916d3213489e2 Mon Sep 17 00:00:00 2001 From: href Date: Thu, 14 May 2020 21:36:31 +0200 Subject: Pleroma.MIME: use gen_magic --- lib/pleroma/application.ex | 1 + lib/pleroma/mime.ex | 84 ++++++++++++---------------------------------- 2 files changed, 23 insertions(+), 62 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/application.ex b/lib/pleroma/application.ex index 9d3d92b38..c74255629 100644 --- a/lib/pleroma/application.ex +++ b/lib/pleroma/application.ex @@ -80,6 +80,7 @@ defmodule Pleroma.Application do [ Pleroma.Stats, Pleroma.JobQueueMonitor, + Pleroma.MIME, {Oban, Config.get(Oban)} ] ++ task_children(@env) ++ diff --git a/lib/pleroma/mime.ex b/lib/pleroma/mime.ex index 6ee055f50..3b406630e 100644 --- a/lib/pleroma/mime.ex +++ b/lib/pleroma/mime.ex @@ -6,8 +6,21 @@ defmodule Pleroma.MIME do @moduledoc """ Returns the mime-type of a binary and optionally a normalized file-name. """ - @default "application/octet-stream" @read_bytes 35 + @pool __MODULE__.GenMagicPool + + def child_spec(_) do + pool_size = Pleroma.Config.get!([:gen_magic_pool, :size]) + name = @pool + + %{ + id: __MODULE__, + start: {GenMagic.Pool, :start_link, [[name: name, pool_size: pool_size]]}, + type: :worker, + restart: :permanent, + shutdown: 500 + } + end @spec file_mime_type(String.t(), String.t()) :: {:ok, content_type :: String.t(), filename :: String.t()} | {:error, any()} | :error @@ -20,9 +33,10 @@ defmodule Pleroma.MIME do @spec file_mime_type(String.t()) :: {:ok, String.t()} | {:error, any()} | :error def file_mime_type(filename) do - File.open(filename, [:read], fn f -> - check_mime_type(IO.binread(f, @read_bytes)) - end) + case GenMagic.Pool.perform(@pool, filename) do + {:ok, %GenMagic.Result{mime_type: content_type}} -> {:ok, content_type} + error -> error + end end def bin_mime_type(binary, filename) do @@ -34,13 +48,14 @@ defmodule Pleroma.MIME do @spec bin_mime_type(binary()) :: {:ok, String.t()} | :error def bin_mime_type(<>) do - {:ok, check_mime_type(head)} + case GenMagic.Pool.perform(@pool, {:bytes, head}) do + {:ok, %GenMagic.Result{mime_type: content_type}} -> {:ok, content_type} + error -> error + end end def bin_mime_type(_), do: :error - def mime_type(<<_::binary>>), do: {:ok, @default} - defp fix_extension(filename, content_type) do parts = String.split(filename, ".") @@ -62,59 +77,4 @@ defmodule Pleroma.MIME do Enum.join([new_filename, String.split(content_type, "/") |> List.last()], ".") end end - - defp check_mime_type(<<0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, _::binary>>) do - "image/png" - end - - defp check_mime_type(<<0x47, 0x49, 0x46, 0x38, _, 0x61, _::binary>>) do - "image/gif" - end - - defp check_mime_type(<<0xFF, 0xD8, 0xFF, _::binary>>) do - "image/jpeg" - end - - defp check_mime_type(<<0x1A, 0x45, 0xDF, 0xA3, _::binary>>) do - "video/webm" - end - - defp check_mime_type(<<0x00, 0x00, 0x00, _, 0x66, 0x74, 0x79, 0x70, _::binary>>) do - "video/mp4" - end - - defp check_mime_type(<<0x49, 0x44, 0x33, _::binary>>) do - "audio/mpeg" - end - - defp check_mime_type(<<255, 251, _, 68, 0, 0, 0, 0, _::binary>>) do - "audio/mpeg" - end - - defp check_mime_type( - <<0x4F, 0x67, 0x67, 0x53, 0x00, 0x02, 0x00, 0x00, _::size(160), 0x80, 0x74, 0x68, 0x65, - 0x6F, 0x72, 0x61, _::binary>> - ) do - "video/ogg" - end - - defp check_mime_type(<<0x4F, 0x67, 0x67, 0x53, 0x00, 0x02, 0x00, 0x00, _::binary>>) do - "audio/ogg" - end - - defp check_mime_type(<<"RIFF", _::binary-size(4), "WAVE", _::binary>>) do - "audio/wav" - end - - defp check_mime_type(<<"RIFF", _::binary-size(4), "WEBP", _::binary>>) do - "image/webp" - end - - defp check_mime_type(<<"RIFF", _::binary-size(4), "AVI.", _::binary>>) do - "video/avi" - end - - defp check_mime_type(_) do - @default - end end -- cgit v1.2.3 From f124f6820582d50be83ba7a1709b14ce8ee1abcc Mon Sep 17 00:00:00 2001 From: href Date: Tue, 16 Jun 2020 15:11:45 +0200 Subject: Switch from gen_magic to majic, use Majic.Plug, remove Pleroma.MIME --- lib/pleroma/application.ex | 2 +- lib/pleroma/mime.ex | 80 ---------------------- lib/pleroma/upload.ex | 19 ++--- .../web/activity_pub/activity_pub_controller.ex | 2 + .../mastodon_api/controllers/media_controller.ex | 1 + .../pleroma_api/controllers/account_controller.ex | 5 ++ .../pleroma_api/controllers/mascot_controller.ex | 10 +-- 7 files changed, 25 insertions(+), 94 deletions(-) delete mode 100644 lib/pleroma/mime.ex (limited to 'lib') diff --git a/lib/pleroma/application.ex b/lib/pleroma/application.ex index c74255629..9c74fa00e 100644 --- a/lib/pleroma/application.ex +++ b/lib/pleroma/application.ex @@ -80,7 +80,7 @@ defmodule Pleroma.Application do [ Pleroma.Stats, Pleroma.JobQueueMonitor, - Pleroma.MIME, + {Majic.Pool, [name: Pleroma.MajicPool, pool_size: Config.get([:majic_pool, :size], 2)]}, {Oban, Config.get(Oban)} ] ++ task_children(@env) ++ diff --git a/lib/pleroma/mime.ex b/lib/pleroma/mime.ex deleted file mode 100644 index 3b406630e..000000000 --- a/lib/pleroma/mime.ex +++ /dev/null @@ -1,80 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2020 Pleroma Authors -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.MIME do - @moduledoc """ - Returns the mime-type of a binary and optionally a normalized file-name. - """ - @read_bytes 35 - @pool __MODULE__.GenMagicPool - - def child_spec(_) do - pool_size = Pleroma.Config.get!([:gen_magic_pool, :size]) - name = @pool - - %{ - id: __MODULE__, - start: {GenMagic.Pool, :start_link, [[name: name, pool_size: pool_size]]}, - type: :worker, - restart: :permanent, - shutdown: 500 - } - end - - @spec file_mime_type(String.t(), String.t()) :: - {:ok, content_type :: String.t(), filename :: String.t()} | {:error, any()} | :error - def file_mime_type(path, filename) do - with {:ok, content_type} <- file_mime_type(path), - filename <- fix_extension(filename, content_type) do - {:ok, content_type, filename} - end - end - - @spec file_mime_type(String.t()) :: {:ok, String.t()} | {:error, any()} | :error - def file_mime_type(filename) do - case GenMagic.Pool.perform(@pool, filename) do - {:ok, %GenMagic.Result{mime_type: content_type}} -> {:ok, content_type} - error -> error - end - end - - def bin_mime_type(binary, filename) do - with {:ok, content_type} <- bin_mime_type(binary), - filename <- fix_extension(filename, content_type) do - {:ok, content_type, filename} - end - end - - @spec bin_mime_type(binary()) :: {:ok, String.t()} | :error - def bin_mime_type(<>) do - case GenMagic.Pool.perform(@pool, {:bytes, head}) do - {:ok, %GenMagic.Result{mime_type: content_type}} -> {:ok, content_type} - error -> error - end - end - - def bin_mime_type(_), do: :error - - defp fix_extension(filename, content_type) do - parts = String.split(filename, ".") - - new_filename = - if length(parts) > 1 do - Enum.drop(parts, -1) |> Enum.join(".") - else - Enum.join(parts) - end - - cond do - content_type == "application/octet-stream" -> - filename - - ext = List.first(MIME.extensions(content_type)) -> - new_filename <> "." <> ext - - true -> - Enum.join([new_filename, String.split(content_type, "/") |> List.last()], ".") - end - end -end diff --git a/lib/pleroma/upload.ex b/lib/pleroma/upload.ex index 797555bff..a0ba2f4c0 100644 --- a/lib/pleroma/upload.ex +++ b/lib/pleroma/upload.ex @@ -57,6 +57,7 @@ defmodule Pleroma.Upload do defstruct [:id, :name, :tempfile, :content_type, :path] @spec store(source, options :: [option()]) :: {:ok, Map.t()} | {:error, any()} + @doc "Store a file. If using a `Plug.Upload{}` as the source, be sure to use `Majic.Plug` to ensure its content_type and filename is correct." def store(upload, opts \\ []) do opts = get_opts(opts) @@ -123,14 +124,13 @@ defmodule Pleroma.Upload do end defp prepare_upload(%Plug.Upload{} = file, opts) do - with :ok <- check_file_size(file.path, opts.size_limit), - {:ok, content_type, name} <- Pleroma.MIME.file_mime_type(file.path, file.filename) do + with :ok <- check_file_size(file.path, opts.size_limit) do {:ok, %__MODULE__{ id: UUID.generate(), - name: name, + name: file.filename, tempfile: file.path, - content_type: content_type + content_type: file.content_type }} end end @@ -138,16 +138,17 @@ defmodule Pleroma.Upload do defp prepare_upload(%{img: "data:image/" <> image_data}, opts) do parsed = Regex.named_captures(~r/(?jpeg|png|gif);base64,(?.*)/, image_data) data = Base.decode64!(parsed["data"], ignore: :whitespace) - hash = String.downcase(Base.encode16(:crypto.hash(:sha256, data))) + hash = Base.encode16(:crypto.hash(:sha256, data), lower: true) with :ok <- check_binary_size(data, opts.size_limit), tmp_path <- tempfile_for_image(data), - {:ok, content_type, name} <- - Pleroma.MIME.bin_mime_type(data, hash <> "." <> parsed["filetype"]) do + {:ok, %{mime_type: content_type}} <- + Majic.perform({:bytes, data}, pool: Pleroma.MajicPool), + [ext | _] <- MIME.extensions(content_type) do {:ok, %__MODULE__{ id: UUID.generate(), - name: name, + name: hash <> "." <> ext, tempfile: tmp_path, content_type: content_type }} @@ -156,7 +157,7 @@ defmodule Pleroma.Upload do # For Mix.Tasks.MigrateLocalUploads defp prepare_upload(%__MODULE__{tempfile: path} = upload, _opts) do - with {:ok, content_type} <- Pleroma.MIME.file_mime_type(path) do + with {:ok, %{mime_type: content_type}} <- Majic.perform(path, pool: Pleroma.MajicPool) do {:ok, %__MODULE__{upload | content_type: content_type}} end end diff --git a/lib/pleroma/web/activity_pub/activity_pub_controller.ex b/lib/pleroma/web/activity_pub/activity_pub_controller.ex index f0b5c6e93..e2a5fb9e9 100644 --- a/lib/pleroma/web/activity_pub/activity_pub_controller.ex +++ b/lib/pleroma/web/activity_pub/activity_pub_controller.ex @@ -45,6 +45,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do when action in [:read_inbox, :update_outbox, :whoami, :upload_media] ) + plug(Majic.Plug, [pool: Pleroma.MajicPool] when action in [:upload_media]) + plug( Pleroma.Plugs.Cache, [query_params: false, tracking_fun: &__MODULE__.track_object_fetch/2] diff --git a/lib/pleroma/web/mastodon_api/controllers/media_controller.ex b/lib/pleroma/web/mastodon_api/controllers/media_controller.ex index 513de279f..06bb718ef 100644 --- a/lib/pleroma/web/mastodon_api/controllers/media_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/media_controller.ex @@ -16,6 +16,7 @@ defmodule Pleroma.Web.MastodonAPI.MediaController do plug(OAuthScopesPlug, %{scopes: ["read:media"]} when action == :show) plug(OAuthScopesPlug, %{scopes: ["write:media"]} when action != :show) + plug(Majic.Plug, [pool: Pleroma.MajicPool] when action in [:create, :create2]) defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.MediaOperation diff --git a/lib/pleroma/web/pleroma_api/controllers/account_controller.ex b/lib/pleroma/web/pleroma_api/controllers/account_controller.ex index f3554d919..97a6ae60d 100644 --- a/lib/pleroma/web/pleroma_api/controllers/account_controller.ex +++ b/lib/pleroma/web/pleroma_api/controllers/account_controller.ex @@ -56,6 +56,11 @@ defmodule Pleroma.Web.PleromaAPI.AccountController do plug(:assign_account_by_id when action in [:favourites, :subscribe, :unsubscribe]) plug(:put_view, Pleroma.Web.MastodonAPI.AccountView) + plug( + Majic.Plug, + [pool: Pleroma.MajicPool] when action in [:update_avatar, :update_background, :update_banner] + ) + defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.PleromaAccountOperation @doc "POST /api/v1/pleroma/accounts/confirmation_resend" diff --git a/lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex b/lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex index df6c50ca5..4ba4154dd 100644 --- a/lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex +++ b/lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex @@ -12,6 +12,7 @@ defmodule Pleroma.Web.PleromaAPI.MascotController do plug(Pleroma.Web.ApiSpec.CastAndValidate) plug(OAuthScopesPlug, %{scopes: ["read:accounts"]} when action == :show) plug(OAuthScopesPlug, %{scopes: ["write:accounts"]} when action != :show) + plug(Majic.Plug, [pool: Pleroma.MajicPool] when action in [:update]) defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.PleromaMascotOperation @@ -22,14 +23,15 @@ defmodule Pleroma.Web.PleromaAPI.MascotController do @doc "PUT /api/v1/pleroma/mascot" def update(%{assigns: %{user: user}, body_params: %{file: file}} = conn, _) do - with {:ok, object} <- ActivityPub.upload(file, actor: User.ap_id(user)), - # Reject if not an image - %{type: "image"} = attachment <- render_attachment(object) do + with {:content_type, "image" <> _} <- {:content_type, file.content_type}, + {:ok, object} <- ActivityPub.upload(file, actor: User.ap_id(user)) do + attachment = render_attachment(object) {:ok, _user} = User.mascot_update(user, attachment) json(conn, attachment) else - %{type: _} -> render_error(conn, :unsupported_media_type, "mascots can only be images") + {:content_type, _} -> + render_error(conn, :unsupported_media_type, "mascots can only be images") end end -- cgit v1.2.3 From 39f7fc5b8ef781c98136d1f9be50a14bff394233 Mon Sep 17 00:00:00 2001 From: href Date: Tue, 16 Jun 2020 19:00:54 +0200 Subject: Update majic & call plug before OpenApiSpex --- lib/pleroma/web/mastodon_api/controllers/media_controller.ex | 2 +- lib/pleroma/web/pleroma_api/controllers/account_controller.ex | 10 +++++----- lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/mastodon_api/controllers/media_controller.ex b/lib/pleroma/web/mastodon_api/controllers/media_controller.ex index 06bb718ef..09acea7f4 100644 --- a/lib/pleroma/web/mastodon_api/controllers/media_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/media_controller.ex @@ -11,12 +11,12 @@ defmodule Pleroma.Web.MastodonAPI.MediaController do alias Pleroma.Web.ActivityPub.ActivityPub action_fallback(Pleroma.Web.MastodonAPI.FallbackController) + plug(Majic.Plug, [pool: Pleroma.MajicPool] when action in [:create, :create2]) plug(Pleroma.Web.ApiSpec.CastAndValidate) plug(:put_view, Pleroma.Web.MastodonAPI.StatusView) plug(OAuthScopesPlug, %{scopes: ["read:media"]} when action == :show) plug(OAuthScopesPlug, %{scopes: ["write:media"]} when action != :show) - plug(Majic.Plug, [pool: Pleroma.MajicPool] when action in [:create, :create2]) defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.MediaOperation diff --git a/lib/pleroma/web/pleroma_api/controllers/account_controller.ex b/lib/pleroma/web/pleroma_api/controllers/account_controller.ex index 97a6ae60d..c76cbfc48 100644 --- a/lib/pleroma/web/pleroma_api/controllers/account_controller.ex +++ b/lib/pleroma/web/pleroma_api/controllers/account_controller.ex @@ -18,6 +18,11 @@ defmodule Pleroma.Web.PleromaAPI.AccountController do require Pleroma.Constants + plug( + Majic.Plug, + [pool: Pleroma.MajicPool] when action in [:update_avatar, :update_background, :update_banner] + ) + plug( OpenApiSpex.Plug.PutApiSpec, [module: Pleroma.Web.ApiSpec] when action == :confirmation_resend @@ -56,11 +61,6 @@ defmodule Pleroma.Web.PleromaAPI.AccountController do plug(:assign_account_by_id when action in [:favourites, :subscribe, :unsubscribe]) plug(:put_view, Pleroma.Web.MastodonAPI.AccountView) - plug( - Majic.Plug, - [pool: Pleroma.MajicPool] when action in [:update_avatar, :update_background, :update_banner] - ) - defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.PleromaAccountOperation @doc "POST /api/v1/pleroma/accounts/confirmation_resend" diff --git a/lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex b/lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex index 4ba4154dd..7e2f6c328 100644 --- a/lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex +++ b/lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex @@ -9,10 +9,10 @@ defmodule Pleroma.Web.PleromaAPI.MascotController do alias Pleroma.User alias Pleroma.Web.ActivityPub.ActivityPub + plug(Majic.Plug, [pool: Pleroma.MajicPool] when action in [:update]) plug(Pleroma.Web.ApiSpec.CastAndValidate) plug(OAuthScopesPlug, %{scopes: ["read:accounts"]} when action == :show) plug(OAuthScopesPlug, %{scopes: ["write:accounts"]} when action != :show) - plug(Majic.Plug, [pool: Pleroma.MajicPool] when action in [:update]) defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.PleromaMascotOperation -- cgit v1.2.3 From 0d5088c2b83fafd9d8da1f1b04936f831ac5ee87 Mon Sep 17 00:00:00 2001 From: Maksim Pechnikov Date: Tue, 1 Sep 2020 09:37:08 +0300 Subject: remove `unread_conversation_count` from User --- lib/pleroma/conversation.ex | 6 +--- lib/pleroma/conversation/participation.ex | 27 ++++++-------- lib/pleroma/user.ex | 42 ---------------------- lib/pleroma/web/mastodon_api/views/account_view.ex | 2 +- 4 files changed, 12 insertions(+), 65 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/conversation.ex b/lib/pleroma/conversation.ex index e76eb0087..77933f0be 100644 --- a/lib/pleroma/conversation.ex +++ b/lib/pleroma/conversation.ex @@ -43,7 +43,7 @@ defmodule Pleroma.Conversation do def maybe_create_recipientships(participation, activity) do participation = Repo.preload(participation, :recipients) - if participation.recipients |> Enum.empty?() do + if Enum.empty?(participation.recipients) do recipients = User.get_all_by_ap_id(activity.recipients) RecipientShip.create(recipients, participation) end @@ -69,10 +69,6 @@ defmodule Pleroma.Conversation do Enum.map(users, fn user -> invisible_conversation = Enum.any?(users, &User.blocks?(user, &1)) - unless invisible_conversation do - User.increment_unread_conversation_count(conversation, user) - end - opts = Keyword.put(opts, :invisible_conversation, invisible_conversation) {:ok, participation} = diff --git a/lib/pleroma/conversation/participation.ex b/lib/pleroma/conversation/participation.ex index 8bc3e85d6..4c32b273a 100644 --- a/lib/pleroma/conversation/participation.ex +++ b/lib/pleroma/conversation/participation.ex @@ -63,21 +63,10 @@ defmodule Pleroma.Conversation.Participation do end end - def mark_as_read(participation) do - __MODULE__ - |> where(id: ^participation.id) - |> update(set: [read: true]) - |> select([p], p) - |> Repo.update_all([]) - |> case do - {1, [participation]} -> - participation = Repo.preload(participation, :user) - User.set_unread_conversation_count(participation.user) - {:ok, participation} - - error -> - error - end + def mark_as_read(%__MODULE__{} = participation) do + participation + |> change(read: true) + |> Repo.update() end def mark_all_as_read(%User{local: true} = user, %User{} = target_user) do @@ -93,7 +82,6 @@ defmodule Pleroma.Conversation.Participation do |> update([p], set: [read: true]) |> Repo.update_all([]) - {:ok, user} = User.set_unread_conversation_count(user) {:ok, user, []} end @@ -108,7 +96,6 @@ defmodule Pleroma.Conversation.Participation do |> select([p], p) |> Repo.update_all([]) - {:ok, user} = User.set_unread_conversation_count(user) {:ok, user, participations} end @@ -220,6 +207,12 @@ defmodule Pleroma.Conversation.Participation do {:ok, Repo.preload(participation, :recipients, force: true)} end + @spec unread_count(User.t()) :: integer() + def unread_count(%User{id: user_id}) do + from(q in __MODULE__, where: q.user_id == ^user_id and q.read == false) + |> Repo.aggregate(:count, :id) + end + def unread_conversation_count_for_user(user) do from(p in __MODULE__, where: p.user_id == ^user.id, diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index d2ad9516f..7fc7a533e 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -129,7 +129,6 @@ defmodule Pleroma.User do field(:hide_followers, :boolean, default: false) field(:hide_follows, :boolean, default: false) field(:hide_favorites, :boolean, default: true) - field(:unread_conversation_count, :integer, default: 0) field(:pinned_activities, {:array, :string}, default: []) field(:email_notifications, :map, default: %{"digest" => false}) field(:mascot, :map, default: nil) @@ -1295,47 +1294,6 @@ defmodule Pleroma.User do |> update_and_set_cache() end - def set_unread_conversation_count(%User{local: true} = user) do - unread_query = Participation.unread_conversation_count_for_user(user) - - User - |> join(:inner, [u], p in subquery(unread_query)) - |> update([u, p], - set: [unread_conversation_count: p.count] - ) - |> where([u], u.id == ^user.id) - |> select([u], u) - |> Repo.update_all([]) - |> case do - {1, [user]} -> set_cache(user) - _ -> {:error, user} - end - end - - def set_unread_conversation_count(user), do: {:ok, user} - - def increment_unread_conversation_count(conversation, %User{local: true} = user) do - unread_query = - Participation.unread_conversation_count_for_user(user) - |> where([p], p.conversation_id == ^conversation.id) - - User - |> join(:inner, [u], p in subquery(unread_query)) - |> update([u, p], - inc: [unread_conversation_count: 1] - ) - |> where([u], u.id == ^user.id) - |> where([u, p], p.count == 0) - |> select([u], u) - |> Repo.update_all([]) - |> case do - {1, [user]} -> set_cache(user) - _ -> {:error, user} - end - end - - def increment_unread_conversation_count(_, user), do: {:ok, user} - @spec get_users_from_set([String.t()], keyword()) :: [User.t()] def get_users_from_set(ap_ids, opts \\ []) do local_only = Keyword.get(opts, :local_only, true) diff --git a/lib/pleroma/web/mastodon_api/views/account_view.ex b/lib/pleroma/web/mastodon_api/views/account_view.ex index 864c0417f..1bf53600c 100644 --- a/lib/pleroma/web/mastodon_api/views/account_view.ex +++ b/lib/pleroma/web/mastodon_api/views/account_view.ex @@ -386,7 +386,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do data |> Kernel.put_in( [:pleroma, :unread_conversation_count], - user.unread_conversation_count + Pleroma.Conversation.Participation.unread_count(user) ) end -- cgit v1.2.3 From 7efadc3cbd46369e960f31c33a2c555f718ca8c5 Mon Sep 17 00:00:00 2001 From: Ivan Tashkinov Date: Thu, 1 Oct 2020 21:34:45 +0300 Subject: No auth check in OStatusController, even on non-federating instances. --- lib/pleroma/web/ostatus/ostatus_controller.ex | 4 ---- 1 file changed, 4 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/ostatus/ostatus_controller.ex b/lib/pleroma/web/ostatus/ostatus_controller.ex index de1b0b3f0..8646d2c1c 100644 --- a/lib/pleroma/web/ostatus/ostatus_controller.ex +++ b/lib/pleroma/web/ostatus/ostatus_controller.ex @@ -16,10 +16,6 @@ defmodule Pleroma.Web.OStatus.OStatusController do alias Pleroma.Web.Metadata.PlayerView alias Pleroma.Web.Router - plug(Pleroma.Plugs.EnsureAuthenticatedPlug, - unless_func: &Pleroma.Web.FederatingPlug.federating?/1 - ) - plug( RateLimiter, [name: :ap_routes, params: ["uuid"]] when action in [:object, :activity] -- cgit v1.2.3 From 0d575735bfd280b878bdecc6d018d8cca23ad09f Mon Sep 17 00:00:00 2001 From: Ivan Tashkinov Date: Thu, 1 Oct 2020 21:41:22 +0300 Subject: No auth check in UserController.feed_redirect/2, even on non-federating instances. --- lib/pleroma/web/feed/user_controller.ex | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/feed/user_controller.ex b/lib/pleroma/web/feed/user_controller.ex index 71eb1ea7e..09ecdedb4 100644 --- a/lib/pleroma/web/feed/user_controller.ex +++ b/lib/pleroma/web/feed/user_controller.ex @@ -23,12 +23,7 @@ defmodule Pleroma.Web.Feed.UserController do def feed_redirect(%{assigns: %{format: format}} = conn, _params) when format in ["json", "activity+json"] do - with %{halted: false} = conn <- - Pleroma.Plugs.EnsureAuthenticatedPlug.call(conn, - unless_func: &Pleroma.Web.FederatingPlug.federating?/1 - ) do - ActivityPubController.call(conn, :user) - end + ActivityPubController.call(conn, :user) end def feed_redirect(conn, %{"nickname" => nickname}) do -- cgit v1.2.3 From f6024252ae8601d41bea943bb3cae5c656416eb9 Mon Sep 17 00:00:00 2001 From: Ivan Tashkinov Date: Fri, 2 Oct 2020 22:18:02 +0300 Subject: [#3053] No auth check in StaticFEController, even on non-federating instances. Adjusted tests. --- lib/pleroma/web/feed/tag_controller.ex | 4 +- lib/pleroma/web/feed/user_controller.ex | 4 +- lib/pleroma/web/router.ex | 11 +- lib/pleroma/web/static_fe/static_fe_controller.ex | 124 +++++++++++----------- 4 files changed, 75 insertions(+), 68 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/feed/tag_controller.ex b/lib/pleroma/web/feed/tag_controller.ex index 93a8294b7..c348b32c2 100644 --- a/lib/pleroma/web/feed/tag_controller.ex +++ b/lib/pleroma/web/feed/tag_controller.ex @@ -10,14 +10,14 @@ defmodule Pleroma.Web.Feed.TagController do alias Pleroma.Web.Feed.FeedView def feed(conn, params) do - unless Pleroma.Config.restrict_unauthenticated_access?(:activities, :local) do + unless Config.restrict_unauthenticated_access?(:activities, :local) do render_feed(conn, params) else render_error(conn, :not_found, "Not found") end end - def render_feed(conn, %{"tag" => raw_tag} = params) do + defp render_feed(conn, %{"tag" => raw_tag} = params) do {format, tag} = parse_tag(raw_tag) activities = diff --git a/lib/pleroma/web/feed/user_controller.ex b/lib/pleroma/web/feed/user_controller.ex index 09ecdedb4..5fbcd82d7 100644 --- a/lib/pleroma/web/feed/user_controller.ex +++ b/lib/pleroma/web/feed/user_controller.ex @@ -40,11 +40,11 @@ defmodule Pleroma.Web.Feed.UserController do end end - def render_feed(conn, %{"nickname" => nickname} = params) do + defp render_feed(conn, %{"nickname" => nickname} = params) do format = get_format(conn) format = - if format in ["rss", "atom"] do + if format in ["atom", "rss"] do format else "atom" diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index 42a9db21d..e0e92549f 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -561,12 +561,17 @@ defmodule Pleroma.Web.Router do plug(Pleroma.Plugs.StaticFEPlug) end + pipeline :ostatus_no_html do + plug(:accepts, ["xml", "rss", "atom", "activity+json", "json"]) + end + pipeline :oembed do plug(:accepts, ["json", "xml"]) end scope "/", Pleroma.Web do - pipe_through([:ostatus, :http_signature]) + # Note: no authentication plugs, all endpoints below should only yield public objects + pipe_through(:ostatus) get("/objects/:uuid", OStatus.OStatusController, :object) get("/activities/:uuid", OStatus.OStatusController, :activity) @@ -579,6 +584,10 @@ defmodule Pleroma.Web.Router do get("/users/:nickname/feed", Feed.UserController, :feed, as: :user_feed) get("/users/:nickname", Feed.UserController, :feed_redirect, as: :user_feed) + end + + scope "/", Pleroma.Web do + pipe_through(:ostatus_no_html) get("/tags/:tag", Feed.TagController, :feed, as: :tag_feed) end diff --git a/lib/pleroma/web/static_fe/static_fe_controller.ex b/lib/pleroma/web/static_fe/static_fe_controller.ex index a7a891b13..b1c62f5b0 100644 --- a/lib/pleroma/web/static_fe/static_fe_controller.ex +++ b/lib/pleroma/web/static_fe/static_fe_controller.ex @@ -17,70 +17,9 @@ defmodule Pleroma.Web.StaticFE.StaticFEController do plug(:put_view, Pleroma.Web.StaticFE.StaticFEView) plug(:assign_id) - plug(Pleroma.Plugs.EnsureAuthenticatedPlug, - unless_func: &Pleroma.Web.FederatingPlug.federating?/1 - ) - @page_keys ["max_id", "min_id", "limit", "since_id", "order"] - defp get_title(%Object{data: %{"name" => name}}) when is_binary(name), - do: name - - defp get_title(%Object{data: %{"summary" => summary}}) when is_binary(summary), - do: summary - - defp get_title(_), do: nil - - defp not_found(conn, message) do - conn - |> put_status(404) - |> render("error.html", %{message: message, meta: ""}) - end - - defp get_counts(%Activity{} = activity) do - %Object{data: data} = Object.normalize(activity) - - %{ - likes: data["like_count"] || 0, - replies: data["repliesCount"] || 0, - announces: data["announcement_count"] || 0 - } - end - - defp represent(%Activity{} = activity), do: represent(activity, false) - - defp represent(%Activity{object: %Object{data: data}} = activity, selected) do - {:ok, user} = User.get_or_fetch(activity.object.data["actor"]) - - link = - case user.local do - true -> Helpers.o_status_url(Pleroma.Web.Endpoint, :notice, activity) - _ -> data["url"] || data["external_url"] || data["id"] - end - - content = - if data["content"] do - data["content"] - |> Pleroma.HTML.filter_tags() - |> Pleroma.Emoji.Formatter.emojify(Map.get(data, "emoji", %{})) - else - nil - end - - %{ - user: User.sanitize_html(user), - title: get_title(activity.object), - content: content, - attachment: data["attachment"], - link: link, - published: data["published"], - sensitive: data["sensitive"], - selected: selected, - counts: get_counts(activity), - id: activity.id - } - end - + @doc "Renders requested local public activity" def show(%{assigns: %{notice_id: notice_id}} = conn, _params) do with %Activity{local: true} = activity <- Activity.get_by_id_with_object(notice_id), @@ -106,6 +45,7 @@ defmodule Pleroma.Web.StaticFE.StaticFEController do end end + @doc "Renders public activities of requested user" def show(%{assigns: %{username_or_id: username_or_id}} = conn, params) do case User.get_cached_by_nickname_or_id(username_or_id) do %User{} = user -> @@ -118,7 +58,7 @@ defmodule Pleroma.Web.StaticFE.StaticFEController do timeline = user - |> ActivityPub.fetch_user_activities(nil, params) + |> ActivityPub.fetch_user_activities(_reading_user = nil, params) |> Enum.map(&represent/1) prev_page_id = @@ -166,6 +106,64 @@ defmodule Pleroma.Web.StaticFE.StaticFEController do end end + defp get_title(%Object{data: %{"name" => name}}) when is_binary(name), + do: name + + defp get_title(%Object{data: %{"summary" => summary}}) when is_binary(summary), + do: summary + + defp get_title(_), do: nil + + defp not_found(conn, message) do + conn + |> put_status(404) + |> render("error.html", %{message: message, meta: ""}) + end + + defp get_counts(%Activity{} = activity) do + %Object{data: data} = Object.normalize(activity) + + %{ + likes: data["like_count"] || 0, + replies: data["repliesCount"] || 0, + announces: data["announcement_count"] || 0 + } + end + + defp represent(%Activity{} = activity), do: represent(activity, false) + + defp represent(%Activity{object: %Object{data: data}} = activity, selected) do + {:ok, user} = User.get_or_fetch(activity.object.data["actor"]) + + link = + case user.local do + true -> Helpers.o_status_url(Pleroma.Web.Endpoint, :notice, activity) + _ -> data["url"] || data["external_url"] || data["id"] + end + + content = + if data["content"] do + data["content"] + |> Pleroma.HTML.filter_tags() + |> Pleroma.Emoji.Formatter.emojify(Map.get(data, "emoji", %{})) + else + nil + end + + %{ + user: User.sanitize_html(user), + title: get_title(activity.object), + content: content, + attachment: data["attachment"], + link: link, + published: data["published"], + sensitive: data["sensitive"], + selected: selected, + counts: get_counts(activity), + id: activity.id + } + end + defp assign_id(%{path_info: ["notice", notice_id]} = conn, _opts), do: assign(conn, :notice_id, notice_id) -- cgit v1.2.3 From f497eb034df6647fef9086a6e2ef03e61e2efc47 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Mon, 5 Oct 2020 21:11:00 +0200 Subject: activity_pub_controller.ex: Remove unused @doc block [ci skip] --- lib/pleroma/web/activity_pub/activity_pub_controller.ex | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/activity_pub/activity_pub_controller.ex b/lib/pleroma/web/activity_pub/activity_pub_controller.ex index 732c44271..832155643 100644 --- a/lib/pleroma/web/activity_pub/activity_pub_controller.ex +++ b/lib/pleroma/web/activity_pub/activity_pub_controller.ex @@ -523,19 +523,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do {new_user, for_user} end - @doc """ - Endpoint based on - - Parameters: - - (required) `file`: data of the media - - (optionnal) `description`: description of the media, intended for accessibility - - Response: - - HTTP Code: 201 Created - - HTTP Body: ActivityPub object to be inserted into another's `attachment` field - - Note: Will not point to a URL with a `Location` header because no standalone Activity has been created. - """ def upload_media(%{assigns: %{user: %User{} = user}} = conn, %{"file" => file} = data) do with {:ok, object} <- ActivityPub.upload( -- cgit v1.2.3 From 094edde7c4ddf65f46e5d692a5ef5b859587d1e1 Mon Sep 17 00:00:00 2001 From: Ivan Tashkinov Date: Mon, 5 Oct 2020 23:48:00 +0300 Subject: [#3053] Unauthenticated access control for OStatus-related controllers and ActivityPubController (base actions: :user, :object, :activity). Tests adjustments. --- .../web/activity_pub/activity_pub_controller.ex | 56 ++++++++++++---------- lib/pleroma/web/activity_pub/visibility.ex | 39 +++++++++++---- lib/pleroma/web/feed/tag_controller.ex | 15 +++--- lib/pleroma/web/feed/user_controller.ex | 19 ++++---- lib/pleroma/web/ostatus/ostatus_controller.ex | 26 +++++----- lib/pleroma/web/router.ex | 46 +++++++++++++----- lib/pleroma/web/static_fe/static_fe_controller.ex | 56 +++++++++++----------- 7 files changed, 154 insertions(+), 103 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/activity_pub/activity_pub_controller.ex b/lib/pleroma/web/activity_pub/activity_pub_controller.ex index 732c44271..c78edfb4c 100644 --- a/lib/pleroma/web/activity_pub/activity_pub_controller.ex +++ b/lib/pleroma/web/activity_pub/activity_pub_controller.ex @@ -32,17 +32,23 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do @federating_only_actions [:internal_fetch, :relay, :relay_following, :relay_followers] + # Note: :following and :followers must be served even without authentication (as via :api) + @auth_only_actions [:read_inbox, :update_outbox, :whoami, :upload_media] + + # Always accessible actions (must perform entity accessibility checks) + @no_auth_no_federation_actions [:user, :activity, :object] + + @authenticated_or_federating_actions @federating_only_actions ++ + @auth_only_actions ++ @no_auth_no_federation_actions + plug(FederatingPlug when action in @federating_only_actions) - plug( - EnsureAuthenticatedPlug, - [unless_func: &FederatingPlug.federating?/1] when action not in @federating_only_actions - ) + plug(EnsureAuthenticatedPlug when action in @auth_only_actions) - # Note: :following and :followers must be served even without authentication (as via :api) plug( - EnsureAuthenticatedPlug - when action in [:read_inbox, :update_outbox, :whoami, :upload_media] + EnsureAuthenticatedPlug, + [unless_func: &FederatingPlug.federating?/1] + when action not in @authenticated_or_federating_actions ) plug( @@ -66,21 +72,22 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do def user(conn, %{"nickname" => nickname}) do with %User{local: true} = user <- User.get_cached_by_nickname(nickname), + {_, :visible} <- {:visibility, User.visible_for(user, _reading_user = nil)}, {:ok, user} <- User.ensure_keys_present(user) do conn |> put_resp_content_type("application/activity+json") |> put_view(UserView) |> render("user.json", %{user: user}) else - nil -> {:error, :not_found} - %{local: false} -> {:error, :not_found} + _ -> {:error, :not_found} end end def object(conn, _) do with ap_id <- Endpoint.url() <> conn.request_path, %Object{} = object <- Object.get_cached_by_ap_id(ap_id), - {_, true} <- {:public?, Visibility.is_public?(object)} do + {_, true} <- {:public?, Visibility.is_public?(object)}, + {_, false} <- {:restricted?, Visibility.restrict_unauthenticated_access?(object)} do conn |> assign(:tracking_fun_data, object.id) |> set_cache_ttl_for(object) @@ -88,25 +95,15 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do |> put_view(ObjectView) |> render("object.json", object: object) else - {:public?, false} -> - {:error, :not_found} + _ -> {:error, :not_found} end end - def track_object_fetch(conn, nil), do: conn - - def track_object_fetch(conn, object_id) do - with %{assigns: %{user: %User{id: user_id}}} <- conn do - Delivery.create(object_id, user_id) - end - - conn - end - def activity(conn, _params) do with ap_id <- Endpoint.url() <> conn.request_path, %Activity{} = activity <- Activity.normalize(ap_id), - {_, true} <- {:public?, Visibility.is_public?(activity)} do + {_, true} <- {:public?, Visibility.is_public?(activity)}, + {_, true} <- {:visible?, Visibility.visible_for_user?(activity, _reading_user = nil)} do conn |> maybe_set_tracking_data(activity) |> set_cache_ttl_for(activity) @@ -114,8 +111,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do |> put_view(ObjectView) |> render("object.json", object: activity) else - {:public?, false} -> {:error, :not_found} - nil -> {:error, :not_found} + _ -> {:error, :not_found} end end @@ -550,4 +546,14 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do |> json(object.data) end end + + def track_object_fetch(conn, nil), do: conn + + def track_object_fetch(conn, object_id) do + with %{assigns: %{user: %User{id: user_id}}} <- conn do + Delivery.create(object_id, user_id) + end + + conn + end end diff --git a/lib/pleroma/web/activity_pub/visibility.ex b/lib/pleroma/web/activity_pub/visibility.ex index 5c349bb7a..76bd54a42 100644 --- a/lib/pleroma/web/activity_pub/visibility.ex +++ b/lib/pleroma/web/activity_pub/visibility.ex @@ -44,29 +44,30 @@ defmodule Pleroma.Web.ActivityPub.Visibility do def is_list?(%{data: %{"listMessage" => _}}), do: true def is_list?(_), do: false - @spec visible_for_user?(Activity.t(), User.t() | nil) :: boolean() - def visible_for_user?(%{actor: ap_id}, %User{ap_id: ap_id}), do: true + @spec visible_for_user?(Activity.t() | nil, User.t() | nil) :: boolean() + def visible_for_user?(%Activity{actor: ap_id}, %User{ap_id: ap_id}), do: true def visible_for_user?(nil, _), do: false - def visible_for_user?(%{data: %{"listMessage" => _}}, nil), do: false + def visible_for_user?(%Activity{data: %{"listMessage" => _}}, nil), do: false - def visible_for_user?(%{data: %{"listMessage" => list_ap_id}} = activity, %User{} = user) do + def visible_for_user?( + %Activity{data: %{"listMessage" => list_ap_id}} = activity, + %User{} = user + ) do user.ap_id in activity.data["to"] || list_ap_id |> Pleroma.List.get_by_ap_id() |> Pleroma.List.member?(user) end - def visible_for_user?(%{local: local} = activity, nil) do - cfg_key = if local, do: :local, else: :remote - - if Pleroma.Config.restrict_unauthenticated_access?(:activities, cfg_key), + def visible_for_user?(%Activity{} = activity, nil) do + if restrict_unauthenticated_access?(activity), do: false, else: is_public?(activity) end - def visible_for_user?(activity, user) do + def visible_for_user?(%Activity{} = activity, user) do x = [user.ap_id | User.following(user)] y = [activity.actor] ++ activity.data["to"] ++ (activity.data["cc"] || []) is_public?(activity) || Enum.any?(x, &(&1 in y)) @@ -82,6 +83,26 @@ defmodule Pleroma.Web.ActivityPub.Visibility do result end + def restrict_unauthenticated_access?(%Activity{local: local}) do + restrict_unauthenticated_access_to_activity?(local) + end + + def restrict_unauthenticated_access?(%Object{} = object) do + object + |> Object.local?() + |> restrict_unauthenticated_access_to_activity?() + end + + def restrict_unauthenticated_access?(%User{} = user) do + User.visible_for(user, _reading_user = nil) + end + + defp restrict_unauthenticated_access_to_activity?(local?) when is_boolean(local?) do + cfg_key = if local?, do: :local, else: :remote + + Pleroma.Config.restrict_unauthenticated_access?(:activities, cfg_key) + end + def get_visibility(object) do to = object.data["to"] || [] cc = object.data["cc"] || [] diff --git a/lib/pleroma/web/feed/tag_controller.ex b/lib/pleroma/web/feed/tag_controller.ex index c348b32c2..218cdbdf3 100644 --- a/lib/pleroma/web/feed/tag_controller.ex +++ b/lib/pleroma/web/feed/tag_controller.ex @@ -10,7 +10,7 @@ defmodule Pleroma.Web.Feed.TagController do alias Pleroma.Web.Feed.FeedView def feed(conn, params) do - unless Config.restrict_unauthenticated_access?(:activities, :local) do + if Config.get!([:instance, :public]) do render_feed(conn, params) else render_error(conn, :not_found, "Not found") @@ -36,12 +36,13 @@ defmodule Pleroma.Web.Feed.TagController do end @spec parse_tag(binary() | any()) :: {format :: String.t(), tag :: String.t()} - defp parse_tag(raw_tag) when is_binary(raw_tag) do - case Enum.reverse(String.split(raw_tag, ".")) do - [format | tag] when format in ["atom", "rss"] -> {format, Enum.join(tag, ".")} - _ -> {"rss", raw_tag} + defp parse_tag(raw_tag) do + case is_binary(raw_tag) && Enum.reverse(String.split(raw_tag, ".")) do + [format | tag] when format in ["rss", "atom"] -> + {format, Enum.join(tag, ".")} + + _ -> + {"atom", raw_tag} end end - - defp parse_tag(raw_tag), do: {"rss", raw_tag} end diff --git a/lib/pleroma/web/feed/user_controller.ex b/lib/pleroma/web/feed/user_controller.ex index 5fbcd82d7..f1d2bb7be 100644 --- a/lib/pleroma/web/feed/user_controller.ex +++ b/lib/pleroma/web/feed/user_controller.ex @@ -6,6 +6,8 @@ defmodule Pleroma.Web.Feed.UserController do use Pleroma.Web, :controller alias Fallback.RedirectController + + alias Pleroma.Config alias Pleroma.User alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.ActivityPubController @@ -32,15 +34,7 @@ defmodule Pleroma.Web.Feed.UserController do end end - def feed(conn, params) do - unless Pleroma.Config.restrict_unauthenticated_access?(:profiles, :local) do - render_feed(conn, params) - else - errors(conn, {:error, :not_found}) - end - end - - defp render_feed(conn, %{"nickname" => nickname} = params) do + def feed(conn, %{"nickname" => nickname} = params) do format = get_format(conn) format = @@ -50,7 +44,8 @@ defmodule Pleroma.Web.Feed.UserController do "atom" end - with {_, %User{local: true} = user} <- {:fetch_user, User.get_cached_by_nickname(nickname)} do + with {_, %User{local: true} = user} <- {:fetch_user, User.get_cached_by_nickname(nickname)}, + {_, :visible} <- {:visibility, User.visible_for(user, _reading_user = nil)} do activities = %{ type: ["Create"], @@ -65,7 +60,7 @@ defmodule Pleroma.Web.Feed.UserController do |> render("user.#{format}", user: user, activities: activities, - feed_config: Pleroma.Config.get([:feed]) + feed_config: Config.get([:feed]) ) end end @@ -77,6 +72,8 @@ defmodule Pleroma.Web.Feed.UserController do def errors(conn, {:fetch_user, %User{local: false}}), do: errors(conn, {:error, :not_found}) def errors(conn, {:fetch_user, nil}), do: errors(conn, {:error, :not_found}) + def errors(conn, {:visibility, _}), do: errors(conn, {:error, :not_found}) + def errors(conn, _) do render_error(conn, :internal_server_error, "Something went wrong") end diff --git a/lib/pleroma/web/ostatus/ostatus_controller.ex b/lib/pleroma/web/ostatus/ostatus_controller.ex index 8646d2c1c..b4dc2a87f 100644 --- a/lib/pleroma/web/ostatus/ostatus_controller.ex +++ b/lib/pleroma/web/ostatus/ostatus_controller.ex @@ -33,16 +33,15 @@ defmodule Pleroma.Web.OStatus.OStatusController do ActivityPubController.call(conn, :object) end - def object(%{assigns: %{format: format}} = conn, _params) do + def object(conn, _params) do with id <- Endpoint.url() <> conn.request_path, {_, %Activity{} = activity} <- {:activity, Activity.get_create_by_object_ap_id_with_object(id)}, - {_, true} <- {:public?, Visibility.is_public?(activity)} do - case format do - _ -> redirect(conn, to: "/notice/#{activity.id}") - end + {_, true} <- {:public?, Visibility.is_public?(activity)}, + {_, true} <- {:visible?, Visibility.visible_for_user?(activity, _reading_user = nil)} do + redirect(conn, to: "/notice/#{activity.id}") else - reason when reason in [{:public?, false}, {:activity, nil}] -> + reason when reason in [{:public?, false}, {:visible?, false}, {:activity, nil}] -> {:error, :not_found} e -> @@ -55,15 +54,14 @@ defmodule Pleroma.Web.OStatus.OStatusController do ActivityPubController.call(conn, :activity) end - def activity(%{assigns: %{format: format}} = conn, _params) do + def activity(conn, _params) do with id <- Endpoint.url() <> conn.request_path, {_, %Activity{} = activity} <- {:activity, Activity.normalize(id)}, - {_, true} <- {:public?, Visibility.is_public?(activity)} do - case format do - _ -> redirect(conn, to: "/notice/#{activity.id}") - end + {_, true} <- {:public?, Visibility.is_public?(activity)}, + {_, true} <- {:visible?, Visibility.visible_for_user?(activity, _reading_user = nil)} do + redirect(conn, to: "/notice/#{activity.id}") else - reason when reason in [{:public?, false}, {:activity, nil}] -> + reason when reason in [{:public?, false}, {:visible?, false}, {:activity, nil}] -> {:error, :not_found} e -> @@ -74,6 +72,7 @@ defmodule Pleroma.Web.OStatus.OStatusController do def notice(%{assigns: %{format: format}} = conn, %{"id" => id}) do with {_, %Activity{} = activity} <- {:activity, Activity.get_by_id_with_object(id)}, {_, true} <- {:public?, Visibility.is_public?(activity)}, + {_, true} <- {:visible?, Visibility.visible_for_user?(activity, _reading_user = nil)}, %User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]) do cond do format in ["json", "activity+json"] -> @@ -101,7 +100,7 @@ defmodule Pleroma.Web.OStatus.OStatusController do RedirectController.redirector(conn, nil) end else - reason when reason in [{:public?, false}, {:activity, nil}] -> + reason when reason in [{:public?, false}, {:visible?, false}, {:activity, nil}] -> conn |> put_status(404) |> RedirectController.redirector(nil, 404) @@ -115,6 +114,7 @@ defmodule Pleroma.Web.OStatus.OStatusController do def notice_player(conn, %{"id" => id}) do with %Activity{data: %{"type" => "Create"}} = activity <- Activity.get_by_id_with_object(id), true <- Visibility.is_public?(activity), + {_, true} <- {:visible?, Visibility.visible_for_user?(activity, _reading_user = nil)}, %Object{} = object <- Object.normalize(activity), %{data: %{"attachment" => [%{"url" => [url | _]} | _]}} <- object, true <- String.starts_with?(url["mediaType"], ["audio", "video"]) do diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index e0e92549f..6439a1c39 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -5,6 +5,14 @@ defmodule Pleroma.Web.Router do use Pleroma.Web, :router + pipeline :accepts_html do + plug(:accepts, ["html"]) + end + + pipeline :accepts_xml_rss_atom do + plug(:accepts, ["xml", "rss", "atom"]) + end + pipeline :browser do plug(:accepts, ["html"]) plug(:fetch_session) @@ -556,39 +564,55 @@ defmodule Pleroma.Web.Router do ) end - pipeline :ostatus do - plug(:accepts, ["html", "xml", "rss", "atom", "activity+json", "json"]) + pipeline :ostatus_html_json do + plug(:accepts, ["html", "activity+json", "json"]) plug(Pleroma.Plugs.StaticFEPlug) end - pipeline :ostatus_no_html do - plug(:accepts, ["xml", "rss", "atom", "activity+json", "json"]) + pipeline :ostatus_html_xml do + plug(:accepts, ["html", "xml", "rss", "atom"]) + plug(Pleroma.Plugs.StaticFEPlug) end - pipeline :oembed do - plug(:accepts, ["json", "xml"]) + pipeline :ostatus_html_xml_json do + plug(:accepts, ["html", "xml", "rss", "atom", "activity+json", "json"]) + plug(Pleroma.Plugs.StaticFEPlug) end scope "/", Pleroma.Web do - # Note: no authentication plugs, all endpoints below should only yield public objects - pipe_through(:ostatus) + # Note: html format is supported only if static FE is enabled + pipe_through(:ostatus_html_json) get("/objects/:uuid", OStatus.OStatusController, :object) get("/activities/:uuid", OStatus.OStatusController, :activity) get("/notice/:id", OStatus.OStatusController, :notice) - get("/notice/:id/embed_player", OStatus.OStatusController, :notice_player) # Mastodon compatibility routes get("/users/:nickname/statuses/:id", OStatus.OStatusController, :object) get("/users/:nickname/statuses/:id/activity", OStatus.OStatusController, :activity) + end - get("/users/:nickname/feed", Feed.UserController, :feed, as: :user_feed) + scope "/", Pleroma.Web do + # Note: html format is supported only if static FE is enabled + pipe_through(:ostatus_html_xml_json) + + # Note: for json format responds with user profile (not user feed) get("/users/:nickname", Feed.UserController, :feed_redirect, as: :user_feed) end scope "/", Pleroma.Web do - pipe_through(:ostatus_no_html) + # Note: html format is supported only if static FE is enabled + pipe_through(:ostatus_html_xml) + get("/users/:nickname/feed", Feed.UserController, :feed, as: :user_feed) + end + scope "/", Pleroma.Web do + pipe_through(:accepts_html) + get("/notice/:id/embed_player", OStatus.OStatusController, :notice_player) + end + + scope "/", Pleroma.Web do + pipe_through(:accepts_xml_rss_atom) get("/tags/:tag", Feed.TagController, :feed, as: :tag_feed) end diff --git a/lib/pleroma/web/static_fe/static_fe_controller.ex b/lib/pleroma/web/static_fe/static_fe_controller.ex index b1c62f5b0..76b82589f 100644 --- a/lib/pleroma/web/static_fe/static_fe_controller.ex +++ b/lib/pleroma/web/static_fe/static_fe_controller.ex @@ -24,6 +24,7 @@ defmodule Pleroma.Web.StaticFE.StaticFEController do with %Activity{local: true} = activity <- Activity.get_by_id_with_object(notice_id), true <- Visibility.is_public?(activity.object), + {_, true} <- {:visible?, Visibility.visible_for_user?(activity, _reading_user = nil)}, %User{} = user <- User.get_by_ap_id(activity.object.data["actor"]) do meta = Metadata.build_tags(%{activity_id: notice_id, object: activity.object, user: user}) @@ -47,34 +48,35 @@ defmodule Pleroma.Web.StaticFE.StaticFEController do @doc "Renders public activities of requested user" def show(%{assigns: %{username_or_id: username_or_id}} = conn, params) do - case User.get_cached_by_nickname_or_id(username_or_id) do - %User{} = user -> - meta = Metadata.build_tags(%{user: user}) - - params = - params - |> Map.take(@page_keys) - |> Map.new(fn {k, v} -> {String.to_existing_atom(k), v} end) - - timeline = - user - |> ActivityPub.fetch_user_activities(_reading_user = nil, params) - |> Enum.map(&represent/1) - - prev_page_id = - (params["min_id"] || params["max_id"]) && - List.first(timeline) && List.first(timeline).id - - next_page_id = List.last(timeline) && List.last(timeline).id - - render(conn, "profile.html", %{ - user: User.sanitize_html(user), - timeline: timeline, - prev_page_id: prev_page_id, - next_page_id: next_page_id, - meta: meta - }) + with {_, %User{local: true} = user} <- + {:fetch_user, User.get_cached_by_nickname_or_id(username_or_id)}, + {_, :visible} <- {:visibility, User.visible_for(user, _reading_user = nil)} do + meta = Metadata.build_tags(%{user: user}) + params = + params + |> Map.take(@page_keys) + |> Map.new(fn {k, v} -> {String.to_existing_atom(k), v} end) + + timeline = + user + |> ActivityPub.fetch_user_activities(_reading_user = nil, params) + |> Enum.map(&represent/1) + + prev_page_id = + (params["min_id"] || params["max_id"]) && + List.first(timeline) && List.first(timeline).id + + next_page_id = List.last(timeline) && List.last(timeline).id + + render(conn, "profile.html", %{ + user: User.sanitize_html(user), + timeline: timeline, + prev_page_id: prev_page_id, + next_page_id: next_page_id, + meta: meta + }) + else _ -> not_found(conn, "User not found.") end -- cgit v1.2.3 From 257e059e61b89752bcde9544cb5ae645b167c96b Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Wed, 19 Aug 2020 15:31:33 +0400 Subject: Add account export --- lib/pleroma/export.ex | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 lib/pleroma/export.ex (limited to 'lib') diff --git a/lib/pleroma/export.ex b/lib/pleroma/export.ex new file mode 100644 index 000000000..82a4b7ace --- /dev/null +++ b/lib/pleroma/export.ex @@ -0,0 +1,118 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Export do + alias Pleroma.Activity + alias Pleroma.Bookmark + alias Pleroma.User + alias Pleroma.Web.ActivityPub.ActivityPub + alias Pleroma.Web.ActivityPub.Transmogrifier + alias Pleroma.Web.ActivityPub.UserView + + import Ecto.Query + + def run(user) do + with {:ok, dir} <- create_dir(), + :ok <- actor(dir, user), + :ok <- statuses(dir, user), + :ok <- likes(dir, user), + :ok <- bookmarks(dir, user) do + IO.inspect({"DONE", dir}) + else + err -> IO.inspect({"export error", err}) + end + end + + def actor(dir, user) do + with {:ok, json} <- + UserView.render("user.json", %{user: user}) + |> Map.merge(%{"likes" => "likes.json", "bookmarks" => "bookmarks.json"}) + |> Jason.encode() do + File.write(dir <> "/actor.json", json) + end + end + + defp create_dir do + datetime = Calendar.NaiveDateTime.Format.iso8601_basic(NaiveDateTime.utc_now()) + dir = Path.join(System.tmp_dir!(), "archive-" <> datetime) + + with :ok <- File.mkdir(dir), do: {:ok, dir} + end + + defp write_header(file, name) do + IO.write( + file, + """ + { + "@context": "https://www.w3.org/ns/activitystreams", + "id": "#{name}.json", + "type": "OrderedCollection", + "orderedItems": [ + """ + ) + end + + defp write(query, dir, name, fun) do + path = dir <> "/#{name}.json" + + with {:ok, file} <- File.open(path, [:write, :utf8]), + :ok <- write_header(file, name) do + counter = :counters.new(1, []) + + query + |> Pleroma.RepoStreamer.chunk_stream(100) + |> Stream.each(fn items -> + Enum.each(items, fn i -> + with {:ok, str} <- fun.(i), + :ok <- IO.write(file, str <> ",\n") do + :counters.add(counter, 1, 1) + end + end) + end) + |> Stream.run() + + total = :counters.get(counter, 1) + + with :ok <- :file.pwrite(file, {:eof, -2}, "\n],\n \"totalItems\": #{total}}") do + File.close(file) + end + end + end + + def bookmarks(dir, %{id: user_id} = _user) do + Bookmark + |> where(user_id: ^user_id) + |> join(:inner, [b], activity in assoc(b, :activity)) + |> select([b, a], %{id: b.id, object: fragment("(?)->>'object'", a.data)}) + |> write(dir, "bookmarks", fn a -> {:ok, "\"#{a.object}\""} end) + end + + def likes(dir, user) do + user.ap_id + |> Activity.Queries.by_actor() + |> Activity.Queries.by_type("Like") + |> select([like], %{id: like.id, object: fragment("(?)->>'object'", like.data)}) + |> write(dir, "likes", fn a -> {:ok, "\"#{a.object}\""} end) + end + + def statuses(dir, user) do + opts = + %{} + |> Map.put(:type, ["Create", "Announce"]) + |> Map.put(:blocking_user, user) + |> Map.put(:muting_user, user) + |> Map.put(:reply_filtering_user, user) + |> Map.put(:announce_filtering_user, user) + |> Map.put(:user, user) + + [[user.ap_id], User.following(user), Pleroma.List.memberships(user)] + |> Enum.concat() + |> ActivityPub.fetch_activities_query(opts) + |> write(dir, "outbox", fn a -> + with {:ok, activity} <- Transmogrifier.prepare_outgoing(a.data) do + activity |> Map.delete("@context") |> Jason.encode() + end + end) + end +end -- cgit v1.2.3 From 9d564ffc2988f145bc9cf26477eea93b1bf01cb0 Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Mon, 24 Aug 2020 20:59:57 +0400 Subject: Zip exported files --- lib/pleroma/export.ex | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/export.ex b/lib/pleroma/export.ex index 82a4b7ace..f0f1ef093 100644 --- a/lib/pleroma/export.ex +++ b/lib/pleroma/export.ex @@ -12,15 +12,17 @@ defmodule Pleroma.Export do import Ecto.Query + @files ['actor.json', 'outbox.json', 'likes.json', 'bookmarks.json'] + def run(user) do - with {:ok, dir} <- create_dir(), - :ok <- actor(dir, user), - :ok <- statuses(dir, user), - :ok <- likes(dir, user), - :ok <- bookmarks(dir, user) do - IO.inspect({"DONE", dir}) - else - err -> IO.inspect({"export error", err}) + with {:ok, path} <- create_dir(user), + :ok <- actor(path, user), + :ok <- statuses(path, user), + :ok <- likes(path, user), + :ok <- bookmarks(path, user), + {:ok, zip_path} <- :zip.create('#{path}.zip', @files, cwd: path), + {:ok, _} <- File.rm_rf(path) do + {:ok, zip_path} end end @@ -33,9 +35,9 @@ defmodule Pleroma.Export do end end - defp create_dir do + defp create_dir(user) do datetime = Calendar.NaiveDateTime.Format.iso8601_basic(NaiveDateTime.utc_now()) - dir = Path.join(System.tmp_dir!(), "archive-" <> datetime) + dir = Path.join(System.tmp_dir!(), "archive-#{user.id}-#{datetime}") with :ok <- File.mkdir(dir), do: {:ok, dir} end -- cgit v1.2.3 From c01a81804835fb92c145b90e3a264c5d4cf9c886 Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Tue, 25 Aug 2020 18:51:09 +0400 Subject: Add tests --- lib/pleroma/export.ex | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/export.ex b/lib/pleroma/export.ex index f0f1ef093..45b8ce749 100644 --- a/lib/pleroma/export.ex +++ b/lib/pleroma/export.ex @@ -26,7 +26,7 @@ defmodule Pleroma.Export do end end - def actor(dir, user) do + defp actor(dir, user) do with {:ok, json} <- UserView.render("user.json", %{user: user}) |> Map.merge(%{"likes" => "likes.json", "bookmarks" => "bookmarks.json"}) @@ -82,7 +82,7 @@ defmodule Pleroma.Export do end end - def bookmarks(dir, %{id: user_id} = _user) do + defp bookmarks(dir, %{id: user_id} = _user) do Bookmark |> where(user_id: ^user_id) |> join(:inner, [b], activity in assoc(b, :activity)) @@ -90,7 +90,7 @@ defmodule Pleroma.Export do |> write(dir, "bookmarks", fn a -> {:ok, "\"#{a.object}\""} end) end - def likes(dir, user) do + defp likes(dir, user) do user.ap_id |> Activity.Queries.by_actor() |> Activity.Queries.by_type("Like") @@ -98,7 +98,7 @@ defmodule Pleroma.Export do |> write(dir, "likes", fn a -> {:ok, "\"#{a.object}\""} end) end - def statuses(dir, user) do + defp statuses(dir, user) do opts = %{} |> Map.put(:type, ["Create", "Announce"]) -- cgit v1.2.3 From be42ab70dc9538df54ac6f30ee123666223b7287 Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Mon, 31 Aug 2020 20:31:21 +0400 Subject: Add backup upload --- lib/pleroma/export.ex | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/export.ex b/lib/pleroma/export.ex index 45b8ce749..b84eccd78 100644 --- a/lib/pleroma/export.ex +++ b/lib/pleroma/export.ex @@ -22,7 +22,25 @@ defmodule Pleroma.Export do :ok <- bookmarks(path, user), {:ok, zip_path} <- :zip.create('#{path}.zip', @files, cwd: path), {:ok, _} <- File.rm_rf(path) do - {:ok, zip_path} + {:ok, :binary.list_to_bin(zip_path)} + end + end + + def upload(zip_path) do + uploader = Pleroma.Config.get([Pleroma.Upload, :uploader]) + file_name = zip_path |> String.split("/") |> List.last() + id = Ecto.UUID.generate() + + upload = %Pleroma.Upload{ + id: id, + name: file_name, + tempfile: zip_path, + content_type: "application/zip", + path: id <> "/" <> file_name + } + + with :ok <- uploader.put_file(upload), :ok <- File.rm(zip_path) do + {:ok, upload} end end -- cgit v1.2.3 From 75e07ba206b94155c5210151a49e29a11bce6e50 Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Mon, 31 Aug 2020 23:07:14 +0400 Subject: Fix tests --- lib/pleroma/export.ex | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/export.ex b/lib/pleroma/export.ex index b84eccd78..8b1bfefe2 100644 --- a/lib/pleroma/export.ex +++ b/lib/pleroma/export.ex @@ -39,7 +39,8 @@ defmodule Pleroma.Export do path: id <> "/" <> file_name } - with :ok <- uploader.put_file(upload), :ok <- File.rm(zip_path) do + with {:ok, _} <- Pleroma.Uploaders.Uploader.put_file(uploader, upload), + :ok <- File.rm(zip_path) do {:ok, upload} end end -- cgit v1.2.3 From 4f3a6337454807f4145bbc1830c3d55dd883d46d Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Wed, 2 Sep 2020 20:21:33 +0400 Subject: Add `backups` table --- lib/pleroma/backup.ex | 201 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/pleroma/export.ex | 139 ---------------------------------- 2 files changed, 201 insertions(+), 139 deletions(-) create mode 100644 lib/pleroma/backup.ex delete mode 100644 lib/pleroma/export.ex (limited to 'lib') diff --git a/lib/pleroma/backup.ex b/lib/pleroma/backup.ex new file mode 100644 index 000000000..4580d8f92 --- /dev/null +++ b/lib/pleroma/backup.ex @@ -0,0 +1,201 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Backup do + use Ecto.Schema + + import Ecto.Changeset + import Ecto.Query + + alias Pleroma.Activity + alias Pleroma.Bookmark + alias Pleroma.Repo + alias Pleroma.User + alias Pleroma.Web.ActivityPub.ActivityPub + alias Pleroma.Web.ActivityPub.Transmogrifier + alias Pleroma.Web.ActivityPub.UserView + + schema "backups" do + field(:content_type, :string) + field(:file_name, :string) + field(:file_size, :integer, default: 0) + field(:processed, :boolean, default: false) + + belongs_to(:user, User, type: FlakeId.Ecto.CompatType) + + timestamps() + end + + def create(user) do + with :ok <- validate_limit(user), + {:ok, backup} <- user |> new() |> Repo.insert() do + {:ok, backup} + end + end + + def new(user) do + rand_str = :crypto.strong_rand_bytes(32) |> Base.url_encode64(padding: false) + datetime = Calendar.NaiveDateTime.Format.iso8601_basic(NaiveDateTime.utc_now()) + name = "archive-#{user.nickname}-#{datetime}-#{rand_str}.zip" + + %__MODULE__{ + user_id: user.id, + content_type: "application/zip", + file_name: name + } + end + + defp validate_limit(user) do + case get_last(user.id) do + %__MODULE__{inserted_at: inserted_at} -> + days = 7 + diff = Timex.diff(NaiveDateTime.utc_now(), inserted_at, :days) + + if diff > days do + :ok + else + {:error, "Last export was less than #{days} days ago"} + end + + nil -> + :ok + end + end + + def get_last(user_id) do + __MODULE__ + |> where(user_id: ^user_id) + |> order_by(desc: :id) + |> limit(1) + |> Repo.one() + end + + def process(%__MODULE__{} = backup) do + with {:ok, zip_file} <- zip(backup), + {:ok, %{size: size}} <- File.stat(zip_file), + {:ok, _upload} <- upload(backup, zip_file) do + backup + |> cast(%{file_size: size, processed: true}, [:file_size, :processed]) + |> Repo.update() + end + end + + @files ['actor.json', 'outbox.json', 'likes.json', 'bookmarks.json'] + def zip(%__MODULE__{} = backup) do + backup = Repo.preload(backup, :user) + name = String.trim_trailing(backup.file_name, ".zip") + dir = Path.join(System.tmp_dir!(), name) + + with :ok <- File.mkdir(dir), + :ok <- actor(dir, backup.user), + :ok <- statuses(dir, backup.user), + :ok <- likes(dir, backup.user), + :ok <- bookmarks(dir, backup.user), + {:ok, zip_path} <- :zip.create(String.to_charlist(dir <> ".zip"), @files, cwd: dir), + {:ok, _} <- File.rm_rf(dir) do + {:ok, :binary.list_to_bin(zip_path)} + end + end + + def upload(%__MODULE__{} = backup, zip_path) do + uploader = Pleroma.Config.get([Pleroma.Upload, :uploader]) + + upload = %Pleroma.Upload{ + name: backup.file_name, + tempfile: zip_path, + content_type: backup.content_type, + path: "backups/" <> backup.file_name + } + + with {:ok, _} <- Pleroma.Uploaders.Uploader.put_file(uploader, upload), + :ok <- File.rm(zip_path) do + {:ok, upload} + end + end + + defp actor(dir, user) do + with {:ok, json} <- + UserView.render("user.json", %{user: user}) + |> Map.merge(%{"likes" => "likes.json", "bookmarks" => "bookmarks.json"}) + |> Jason.encode() do + File.write(dir <> "/actor.json", json) + end + end + + defp write_header(file, name) do + IO.write( + file, + """ + { + "@context": "https://www.w3.org/ns/activitystreams", + "id": "#{name}.json", + "type": "OrderedCollection", + "orderedItems": [ + """ + ) + end + + defp write(query, dir, name, fun) do + path = dir <> "/#{name}.json" + + with {:ok, file} <- File.open(path, [:write, :utf8]), + :ok <- write_header(file, name) do + counter = :counters.new(1, []) + + query + |> Pleroma.RepoStreamer.chunk_stream(100) + |> Stream.each(fn items -> + Enum.each(items, fn i -> + with {:ok, str} <- fun.(i), + :ok <- IO.write(file, str <> ",\n") do + :counters.add(counter, 1, 1) + end + end) + end) + |> Stream.run() + + total = :counters.get(counter, 1) + + with :ok <- :file.pwrite(file, {:eof, -2}, "\n],\n \"totalItems\": #{total}}") do + File.close(file) + end + end + end + + defp bookmarks(dir, %{id: user_id} = _user) do + Bookmark + |> where(user_id: ^user_id) + |> join(:inner, [b], activity in assoc(b, :activity)) + |> select([b, a], %{id: b.id, object: fragment("(?)->>'object'", a.data)}) + |> write(dir, "bookmarks", fn a -> {:ok, "\"#{a.object}\""} end) + end + + defp likes(dir, user) do + user.ap_id + |> Activity.Queries.by_actor() + |> Activity.Queries.by_type("Like") + |> select([like], %{id: like.id, object: fragment("(?)->>'object'", like.data)}) + |> write(dir, "likes", fn a -> {:ok, "\"#{a.object}\""} end) + end + + defp statuses(dir, user) do + opts = + %{} + |> Map.put(:type, ["Create", "Announce"]) + |> Map.put(:blocking_user, user) + |> Map.put(:muting_user, user) + |> Map.put(:reply_filtering_user, user) + |> Map.put(:announce_filtering_user, user) + |> Map.put(:user, user) + + [[user.ap_id], User.following(user), Pleroma.List.memberships(user)] + |> Enum.concat() + |> ActivityPub.fetch_activities_query(opts) + |> write(dir, "outbox", fn a -> + with {:ok, activity} <- Transmogrifier.prepare_outgoing(a.data) do + activity |> Map.delete("@context") |> Jason.encode() + end + end) + end +end diff --git a/lib/pleroma/export.ex b/lib/pleroma/export.ex deleted file mode 100644 index 8b1bfefe2..000000000 --- a/lib/pleroma/export.ex +++ /dev/null @@ -1,139 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2020 Pleroma Authors -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Export do - alias Pleroma.Activity - alias Pleroma.Bookmark - alias Pleroma.User - alias Pleroma.Web.ActivityPub.ActivityPub - alias Pleroma.Web.ActivityPub.Transmogrifier - alias Pleroma.Web.ActivityPub.UserView - - import Ecto.Query - - @files ['actor.json', 'outbox.json', 'likes.json', 'bookmarks.json'] - - def run(user) do - with {:ok, path} <- create_dir(user), - :ok <- actor(path, user), - :ok <- statuses(path, user), - :ok <- likes(path, user), - :ok <- bookmarks(path, user), - {:ok, zip_path} <- :zip.create('#{path}.zip', @files, cwd: path), - {:ok, _} <- File.rm_rf(path) do - {:ok, :binary.list_to_bin(zip_path)} - end - end - - def upload(zip_path) do - uploader = Pleroma.Config.get([Pleroma.Upload, :uploader]) - file_name = zip_path |> String.split("/") |> List.last() - id = Ecto.UUID.generate() - - upload = %Pleroma.Upload{ - id: id, - name: file_name, - tempfile: zip_path, - content_type: "application/zip", - path: id <> "/" <> file_name - } - - with {:ok, _} <- Pleroma.Uploaders.Uploader.put_file(uploader, upload), - :ok <- File.rm(zip_path) do - {:ok, upload} - end - end - - defp actor(dir, user) do - with {:ok, json} <- - UserView.render("user.json", %{user: user}) - |> Map.merge(%{"likes" => "likes.json", "bookmarks" => "bookmarks.json"}) - |> Jason.encode() do - File.write(dir <> "/actor.json", json) - end - end - - defp create_dir(user) do - datetime = Calendar.NaiveDateTime.Format.iso8601_basic(NaiveDateTime.utc_now()) - dir = Path.join(System.tmp_dir!(), "archive-#{user.id}-#{datetime}") - - with :ok <- File.mkdir(dir), do: {:ok, dir} - end - - defp write_header(file, name) do - IO.write( - file, - """ - { - "@context": "https://www.w3.org/ns/activitystreams", - "id": "#{name}.json", - "type": "OrderedCollection", - "orderedItems": [ - """ - ) - end - - defp write(query, dir, name, fun) do - path = dir <> "/#{name}.json" - - with {:ok, file} <- File.open(path, [:write, :utf8]), - :ok <- write_header(file, name) do - counter = :counters.new(1, []) - - query - |> Pleroma.RepoStreamer.chunk_stream(100) - |> Stream.each(fn items -> - Enum.each(items, fn i -> - with {:ok, str} <- fun.(i), - :ok <- IO.write(file, str <> ",\n") do - :counters.add(counter, 1, 1) - end - end) - end) - |> Stream.run() - - total = :counters.get(counter, 1) - - with :ok <- :file.pwrite(file, {:eof, -2}, "\n],\n \"totalItems\": #{total}}") do - File.close(file) - end - end - end - - defp bookmarks(dir, %{id: user_id} = _user) do - Bookmark - |> where(user_id: ^user_id) - |> join(:inner, [b], activity in assoc(b, :activity)) - |> select([b, a], %{id: b.id, object: fragment("(?)->>'object'", a.data)}) - |> write(dir, "bookmarks", fn a -> {:ok, "\"#{a.object}\""} end) - end - - defp likes(dir, user) do - user.ap_id - |> Activity.Queries.by_actor() - |> Activity.Queries.by_type("Like") - |> select([like], %{id: like.id, object: fragment("(?)->>'object'", like.data)}) - |> write(dir, "likes", fn a -> {:ok, "\"#{a.object}\""} end) - end - - defp statuses(dir, user) do - opts = - %{} - |> Map.put(:type, ["Create", "Announce"]) - |> Map.put(:blocking_user, user) - |> Map.put(:muting_user, user) - |> Map.put(:reply_filtering_user, user) - |> Map.put(:announce_filtering_user, user) - |> Map.put(:user, user) - - [[user.ap_id], User.following(user), Pleroma.List.memberships(user)] - |> Enum.concat() - |> ActivityPub.fetch_activities_query(opts) - |> write(dir, "outbox", fn a -> - with {:ok, activity} <- Transmogrifier.prepare_outgoing(a.data) do - activity |> Map.delete("@context") |> Jason.encode() - end - end) - end -end -- cgit v1.2.3 From a0ad9bd734e9af0ce912c32c7480a60ff87a4368 Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Wed, 2 Sep 2020 21:45:22 +0400 Subject: Add BackupWorker --- lib/pleroma/backup.ex | 11 ++++++++++- lib/pleroma/workers/backup_worker.ex | 17 +++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 lib/pleroma/workers/backup_worker.ex (limited to 'lib') diff --git a/lib/pleroma/backup.ex b/lib/pleroma/backup.ex index 4580d8f92..9b5d2625f 100644 --- a/lib/pleroma/backup.ex +++ b/lib/pleroma/backup.ex @@ -30,7 +30,7 @@ defmodule Pleroma.Backup do def create(user) do with :ok <- validate_limit(user), {:ok, backup} <- user |> new() |> Repo.insert() do - {:ok, backup} + Pleroma.Workers.BackupWorker.enqueue("process", %{"backup_id" => backup.id}) end end @@ -71,6 +71,15 @@ defmodule Pleroma.Backup do |> Repo.one() end + def remove_outdated(%__MODULE__{id: latest_id, user_id: user_id}) do + __MODULE__ + |> where(user_id: ^user_id) + |> where([b], b.id != ^latest_id) + |> Repo.delete_all() + end + + def get(id), do: Repo.get(__MODULE__, id) + def process(%__MODULE__{} = backup) do with {:ok, zip_file} <- zip(backup), {:ok, %{size: size}} <- File.stat(zip_file), diff --git a/lib/pleroma/workers/backup_worker.ex b/lib/pleroma/workers/backup_worker.ex new file mode 100644 index 000000000..c982ffa3a --- /dev/null +++ b/lib/pleroma/workers/backup_worker.ex @@ -0,0 +1,17 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Workers.BackupWorker do + alias Pleroma.Backup + + use Pleroma.Workers.WorkerHelper, queue: "backup" + + @impl Oban.Worker + def perform(%Job{args: %{"op" => "process", "backup_id" => backup_id}}) do + with {:ok, %Backup{} = backup} <- + backup_id |> Backup.get() |> Backup.process() do + {:ok, backup} + end + end +end -- cgit v1.2.3 From 3ad7492f9dd1c76cdbc64ad2246f8e9c8c5c4ae6 Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Fri, 4 Sep 2020 18:30:39 +0400 Subject: Add config for Pleroma.Backup --- lib/pleroma/backup.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/backup.ex b/lib/pleroma/backup.ex index 9b5d2625f..e384b6b00 100644 --- a/lib/pleroma/backup.ex +++ b/lib/pleroma/backup.ex @@ -49,7 +49,7 @@ defmodule Pleroma.Backup do defp validate_limit(user) do case get_last(user.id) do %__MODULE__{inserted_at: inserted_at} -> - days = 7 + days = Pleroma.Config.get([Pleroma.Backup, :limit_days]) diff = Timex.diff(NaiveDateTime.utc_now(), inserted_at, :days) if diff > days do -- cgit v1.2.3 From 739cb1463ba07513f047b2ac8f7e22a16c89ef4e Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Fri, 4 Sep 2020 21:48:52 +0400 Subject: Add backups deletion --- lib/pleroma/backup.ex | 14 ++++++++++++-- lib/pleroma/workers/backup_worker.ex | 37 +++++++++++++++++++++++++++++++++--- 2 files changed, 46 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/backup.ex b/lib/pleroma/backup.ex index e384b6b00..bd50fd910 100644 --- a/lib/pleroma/backup.ex +++ b/lib/pleroma/backup.ex @@ -15,6 +15,7 @@ defmodule Pleroma.Backup do alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.Transmogrifier alias Pleroma.Web.ActivityPub.UserView + alias Pleroma.Workers.BackupWorker schema "backups" do field(:content_type, :string) @@ -30,7 +31,7 @@ defmodule Pleroma.Backup do def create(user) do with :ok <- validate_limit(user), {:ok, backup} <- user |> new() |> Repo.insert() do - Pleroma.Workers.BackupWorker.enqueue("process", %{"backup_id" => backup.id}) + BackupWorker.process(backup) end end @@ -46,6 +47,14 @@ defmodule Pleroma.Backup do } end + def delete(backup) do + uploader = Pleroma.Config.get([Pleroma.Upload, :uploader]) + + with :ok <- uploader.delete_file("backups/" <> backup.file_name) do + Repo.delete(backup) + end + end + defp validate_limit(user) do case get_last(user.id) do %__MODULE__{inserted_at: inserted_at} -> @@ -75,7 +84,8 @@ defmodule Pleroma.Backup do __MODULE__ |> where(user_id: ^user_id) |> where([b], b.id != ^latest_id) - |> Repo.delete_all() + |> Repo.all() + |> Enum.each(&BackupWorker.delete/1) end def get(id), do: Repo.get(__MODULE__, id) diff --git a/lib/pleroma/workers/backup_worker.ex b/lib/pleroma/workers/backup_worker.ex index c982ffa3a..f40020794 100644 --- a/lib/pleroma/workers/backup_worker.ex +++ b/lib/pleroma/workers/backup_worker.ex @@ -3,15 +3,46 @@ # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Workers.BackupWorker do + use Oban.Worker, queue: :backup, max_attempts: 1 + + alias Oban.Job alias Pleroma.Backup - use Pleroma.Workers.WorkerHelper, queue: "backup" + def process(backup) do + %{"op" => "process", "backup_id" => backup.id} + |> new() + |> Oban.insert() + end + + def schedule_deletion(backup) do + days = Pleroma.Config.get([Pleroma.Backup, :purge_after_days]) + time = 60 * 60 * 24 * days + scheduled_at = Calendar.NaiveDateTime.add!(backup.inserted_at, time) + + %{"op" => "delete", "backup_id" => backup.id} + |> new(scheduled_at: scheduled_at) + |> Oban.insert() + end + + def delete(backup) do + %{"op" => "delete", "backup_id" => backup.id} + |> new() + |> Oban.insert() + end - @impl Oban.Worker def perform(%Job{args: %{"op" => "process", "backup_id" => backup_id}}) do with {:ok, %Backup{} = backup} <- - backup_id |> Backup.get() |> Backup.process() do + backup_id |> Backup.get() |> Backup.process(), + {:ok, _job} <- schedule_deletion(backup), + :ok <- Backup.remove_outdated(backup) do {:ok, backup} end end + + def perform(%Job{args: %{"op" => "delete", "backup_id" => backup_id}}) do + case Backup.get(backup_id) do + %Backup{} = backup -> Backup.delete(backup) + nil -> :ok + end + end end -- cgit v1.2.3 From 2c73bfe1227065fa203b0b78c9eb12cf86ab3948 Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Wed, 9 Sep 2020 01:04:00 +0400 Subject: Add API endpoints for Backups --- lib/pleroma/backup.ex | 7 ++ .../operations/pleroma_backup_operation.ex | 79 ++++++++++++++++++++++ .../pleroma_api/controllers/backup_controller.ex | 27 ++++++++ lib/pleroma/web/pleroma_api/views/backup_view.ex | 24 +++++++ lib/pleroma/web/router.ex | 3 + 5 files changed, 140 insertions(+) create mode 100644 lib/pleroma/web/api_spec/operations/pleroma_backup_operation.ex create mode 100644 lib/pleroma/web/pleroma_api/controllers/backup_controller.ex create mode 100644 lib/pleroma/web/pleroma_api/views/backup_view.ex (limited to 'lib') diff --git a/lib/pleroma/backup.ex b/lib/pleroma/backup.ex index bd50fd910..348e537a8 100644 --- a/lib/pleroma/backup.ex +++ b/lib/pleroma/backup.ex @@ -80,6 +80,13 @@ defmodule Pleroma.Backup do |> Repo.one() end + def list(%User{id: user_id}) do + __MODULE__ + |> where(user_id: ^user_id) + |> order_by(desc: :id) + |> Repo.all() + end + def remove_outdated(%__MODULE__{id: latest_id, user_id: user_id}) do __MODULE__ |> where(user_id: ^user_id) diff --git a/lib/pleroma/web/api_spec/operations/pleroma_backup_operation.ex b/lib/pleroma/web/api_spec/operations/pleroma_backup_operation.ex new file mode 100644 index 000000000..f877ca31b --- /dev/null +++ b/lib/pleroma/web/api_spec/operations/pleroma_backup_operation.ex @@ -0,0 +1,79 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ApiSpec.PleromaBackupOperation do + alias OpenApiSpex.Operation + alias OpenApiSpex.Schema + alias Pleroma.Web.ApiSpec.Schemas.ApiError + + def open_api_operation(action) do + operation = String.to_existing_atom("#{action}_operation") + apply(__MODULE__, operation, []) + end + + def index_operation do + %Operation{ + tags: ["Backups"], + summary: "List backups", + security: [%{"oAuth" => ["read:account"]}], + operationId: "PleromaAPI.BackupController.index", + responses: %{ + 200 => + Operation.response( + "An array of backups", + "application/json", + %Schema{ + type: :array, + items: backup() + } + ), + 400 => Operation.response("Bad Request", "application/json", ApiError) + } + } + end + + def create_operation do + %Operation{ + tags: ["Backups"], + summary: "Create a backup", + security: [%{"oAuth" => ["read:account"]}], + operationId: "PleromaAPI.BackupController.create", + responses: %{ + 200 => + Operation.response( + "An array of backups", + "application/json", + %Schema{ + type: :array, + items: backup() + } + ), + 400 => Operation.response("Bad Request", "application/json", ApiError) + } + } + end + + defp backup do + %Schema{ + title: "Backup", + description: "Response schema for a backup", + type: :object, + properties: %{ + inserted_at: %Schema{type: :string, format: :"date-time"}, + content_type: %Schema{type: :string}, + file_name: %Schema{type: :string}, + file_size: %Schema{type: :integer}, + processed: %Schema{type: :boolean} + }, + example: %{ + "content_type" => "application/zip", + "file_name" => + "archive-cofe-20200908T195819-1lWrJyJqpsj8-KuHFr7N03lfsYYa5nf2NL-7A9-ddFU.zip", + "file_size" => 1024, + "inserted_at" => "2020-09-08T19:58:20", + "processed" => true + } + } + end +end diff --git a/lib/pleroma/web/pleroma_api/controllers/backup_controller.ex b/lib/pleroma/web/pleroma_api/controllers/backup_controller.ex new file mode 100644 index 000000000..e52c77ff2 --- /dev/null +++ b/lib/pleroma/web/pleroma_api/controllers/backup_controller.ex @@ -0,0 +1,27 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.PleromaAPI.BackupController do + use Pleroma.Web, :controller + + alias Pleroma.Plugs.OAuthScopesPlug + + action_fallback(Pleroma.Web.MastodonAPI.FallbackController) + plug(OAuthScopesPlug, %{scopes: ["read:accounts"]} when action in [:index, :create]) + plug(OpenApiSpex.Plug.CastAndValidate, render_error: Pleroma.Web.ApiSpec.RenderError) + + defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.PleromaBackupOperation + + def index(%{assigns: %{user: user}} = conn, _params) do + backups = Pleroma.Backup.list(user) + render(conn, "index.json", backups: backups) + end + + def create(%{assigns: %{user: user}} = conn, _params) do + with {:ok, _} <- Pleroma.Backup.create(user) do + backups = Pleroma.Backup.list(user) + render(conn, "index.json", backups: backups) + end + end +end diff --git a/lib/pleroma/web/pleroma_api/views/backup_view.ex b/lib/pleroma/web/pleroma_api/views/backup_view.ex new file mode 100644 index 000000000..02b94ce4f --- /dev/null +++ b/lib/pleroma/web/pleroma_api/views/backup_view.ex @@ -0,0 +1,24 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.PleromaAPI.BackupView do + use Pleroma.Web, :view + + alias Pleroma.Backup + alias Pleroma.Web.CommonAPI.Utils + + def render("show.json", %{backup: %Backup{} = backup}) do + %{ + content_type: backup.content_type, + file_name: backup.file_name, + file_size: backup.file_size, + processed: backup.processed, + inserted_at: Utils.to_masto_date(backup.inserted_at) + } + end + + def render("index.json", %{backups: backups}) do + render_many(backups, __MODULE__, "show.json") + end +end diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index e22b31b4c..a1a5a1cb5 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -293,6 +293,9 @@ defmodule Pleroma.Web.Router do get("/accounts/mfa/setup/:method", TwoFactorAuthenticationController, :setup) post("/accounts/mfa/confirm/:method", TwoFactorAuthenticationController, :confirm) delete("/accounts/mfa/:method", TwoFactorAuthenticationController, :disable) + + get("/backups", BackupController, :index) + post("/backups", BackupController, :create) end scope "/oauth", Pleroma.Web.OAuth do -- cgit v1.2.3 From 86ce4afd9338d81f741fa57f962509a6f0f50aff Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Wed, 9 Sep 2020 20:02:20 +0400 Subject: Improve backup urls --- lib/pleroma/web/api_spec/operations/pleroma_backup_operation.ex | 6 +++--- lib/pleroma/web/pleroma_api/views/backup_view.ex | 6 +++++- 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/api_spec/operations/pleroma_backup_operation.ex b/lib/pleroma/web/api_spec/operations/pleroma_backup_operation.ex index f877ca31b..6993794db 100644 --- a/lib/pleroma/web/api_spec/operations/pleroma_backup_operation.ex +++ b/lib/pleroma/web/api_spec/operations/pleroma_backup_operation.ex @@ -69,9 +69,9 @@ defmodule Pleroma.Web.ApiSpec.PleromaBackupOperation do example: %{ "content_type" => "application/zip", "file_name" => - "archive-cofe-20200908T195819-1lWrJyJqpsj8-KuHFr7N03lfsYYa5nf2NL-7A9-ddFU.zip", - "file_size" => 1024, - "inserted_at" => "2020-09-08T19:58:20", + "https://cofe.fe:4000/media/backups/archive-foobar-20200908T164207-Yr7vuT5Wycv-sN3kSN2iJ0k-9pMo60j9qmvRCdDqIew.zip", + "file_size" => 4105, + "inserted_at" => "2020-09-08T16:42:07.000Z", "processed" => true } } diff --git a/lib/pleroma/web/pleroma_api/views/backup_view.ex b/lib/pleroma/web/pleroma_api/views/backup_view.ex index 02b94ce4f..bf40a001e 100644 --- a/lib/pleroma/web/pleroma_api/views/backup_view.ex +++ b/lib/pleroma/web/pleroma_api/views/backup_view.ex @@ -11,7 +11,7 @@ defmodule Pleroma.Web.PleromaAPI.BackupView do def render("show.json", %{backup: %Backup{} = backup}) do %{ content_type: backup.content_type, - file_name: backup.file_name, + url: download_url(backup), file_size: backup.file_size, processed: backup.processed, inserted_at: Utils.to_masto_date(backup.inserted_at) @@ -21,4 +21,8 @@ defmodule Pleroma.Web.PleromaAPI.BackupView do def render("index.json", %{backups: backups}) do render_many(backups, __MODULE__, "show.json") end + + def download_url(%Backup{file_name: file_name}) do + Pleroma.Web.Endpoint.url() <> "/media/backups/" <> file_name + end end -- cgit v1.2.3 From cd13613db3f675b6a9171dea56fc5b03e43ae6b0 Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Thu, 10 Sep 2020 20:53:06 +0400 Subject: Fix query --- lib/pleroma/backup.ex | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/backup.ex b/lib/pleroma/backup.ex index 348e537a8..ce54a413a 100644 --- a/lib/pleroma/backup.ex +++ b/lib/pleroma/backup.ex @@ -8,6 +8,8 @@ defmodule Pleroma.Backup do import Ecto.Changeset import Ecto.Query + require Pleroma.Constants + alias Pleroma.Activity alias Pleroma.Bookmark alias Pleroma.Repo @@ -158,6 +160,7 @@ defmodule Pleroma.Backup do "id": "#{name}.json", "type": "OrderedCollection", "orderedItems": [ + """ ) end @@ -209,13 +212,13 @@ defmodule Pleroma.Backup do opts = %{} |> Map.put(:type, ["Create", "Announce"]) - |> Map.put(:blocking_user, user) - |> Map.put(:muting_user, user) - |> Map.put(:reply_filtering_user, user) - |> Map.put(:announce_filtering_user, user) - |> Map.put(:user, user) + |> Map.put(:actor_id, user.ap_id) - [[user.ap_id], User.following(user), Pleroma.List.memberships(user)] + [ + [Pleroma.Constants.as_public(), user.ap_id], + User.following(user), + Pleroma.List.memberships(user) + ] |> Enum.concat() |> ActivityPub.fetch_activities_query(opts) |> write(dir, "outbox", fn a -> -- cgit v1.2.3 From 27bc121ec00a7b088030d6fb36c7e731f5b072b6 Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Tue, 15 Sep 2020 18:07:28 +0400 Subject: Require email --- lib/pleroma/backup.ex | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/backup.ex b/lib/pleroma/backup.ex index ce54a413a..3b85dd1c1 100644 --- a/lib/pleroma/backup.ex +++ b/lib/pleroma/backup.ex @@ -31,7 +31,9 @@ defmodule Pleroma.Backup do end def create(user) do - with :ok <- validate_limit(user), + with :ok <- validate_email_enabled(), + :ok <- validate_user_email(user), + :ok <- validate_limit(user), {:ok, backup} <- user |> new() |> Repo.insert() do BackupWorker.process(backup) end @@ -74,6 +76,17 @@ defmodule Pleroma.Backup do end end + defp validate_email_enabled do + if Pleroma.Config.get([Pleroma.Emails.Mailer, :enabled]) do + :ok + else + {:error, "Backups require enabled email"} + end + end + + defp validate_user_email(%User{email: nil}), do: {:error, "Email is required"} + defp validate_user_email(%User{email: email}) when is_binary(email), do: :ok + def get_last(user_id) do __MODULE__ |> where(user_id: ^user_id) @@ -100,7 +113,7 @@ defmodule Pleroma.Backup do def get(id), do: Repo.get(__MODULE__, id) def process(%__MODULE__{} = backup) do - with {:ok, zip_file} <- zip(backup), + with {:ok, zip_file} <- export(backup), {:ok, %{size: size}} <- File.stat(zip_file), {:ok, _upload} <- upload(backup, zip_file) do backup @@ -110,7 +123,7 @@ defmodule Pleroma.Backup do end @files ['actor.json', 'outbox.json', 'likes.json', 'bookmarks.json'] - def zip(%__MODULE__{} = backup) do + def export(%__MODULE__{} = backup) do backup = Repo.preload(backup, :user) name = String.trim_trailing(backup.file_name, ".zip") dir = Path.join(System.tmp_dir!(), name) -- cgit v1.2.3 From e52dd62e14a956a28a706124464f3ac4b985080d Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Wed, 16 Sep 2020 23:21:13 +0400 Subject: Add configurable temporary directory --- lib/pleroma/backup.ex | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/backup.ex b/lib/pleroma/backup.ex index 3b85dd1c1..450dd5b84 100644 --- a/lib/pleroma/backup.ex +++ b/lib/pleroma/backup.ex @@ -126,7 +126,7 @@ defmodule Pleroma.Backup do def export(%__MODULE__{} = backup) do backup = Repo.preload(backup, :user) name = String.trim_trailing(backup.file_name, ".zip") - dir = Path.join(System.tmp_dir!(), name) + dir = dir(name) with :ok <- File.mkdir(dir), :ok <- actor(dir, backup.user), @@ -139,6 +139,11 @@ defmodule Pleroma.Backup do end end + def dir(name) do + dir = Pleroma.Config.get([__MODULE__, :dir]) || System.tmp_dir!() + Path.join(dir, name) + end + def upload(%__MODULE__{} = backup, zip_path) do uploader = Pleroma.Config.get([Pleroma.Upload, :uploader]) -- cgit v1.2.3 From 7fdd81d000d857cbcd5bf442f68c91b1c5b1cebb Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Thu, 17 Sep 2020 18:42:24 +0400 Subject: Add "Your backup is ready" email --- lib/pleroma/emails/user_email.ex | 16 ++++++++++++++++ lib/pleroma/workers/backup_worker.ex | 6 +++++- 2 files changed, 21 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/emails/user_email.ex b/lib/pleroma/emails/user_email.ex index 1d8c72ae9..f943dda0d 100644 --- a/lib/pleroma/emails/user_email.ex +++ b/lib/pleroma/emails/user_email.ex @@ -189,4 +189,20 @@ defmodule Pleroma.Emails.UserEmail do Router.Helpers.subscription_url(Endpoint, :unsubscribe, token) end + + def backup_is_ready_email(backup) do + %{user: user} = Pleroma.Repo.preload(backup, :user) + download_url = Pleroma.Web.PleromaAPI.BackupView.download_url(backup) + + html_body = """ +

You requested a full backup of your Pleroma account. It's ready for download:

+

+ """ + + new() + |> to(recipient(user)) + |> from(sender()) + |> subject("Your account archive is ready") + |> html_body(html_body) + end end diff --git a/lib/pleroma/workers/backup_worker.ex b/lib/pleroma/workers/backup_worker.ex index f40020794..405d55269 100644 --- a/lib/pleroma/workers/backup_worker.ex +++ b/lib/pleroma/workers/backup_worker.ex @@ -34,7 +34,11 @@ defmodule Pleroma.Workers.BackupWorker do with {:ok, %Backup{} = backup} <- backup_id |> Backup.get() |> Backup.process(), {:ok, _job} <- schedule_deletion(backup), - :ok <- Backup.remove_outdated(backup) do + :ok <- Backup.remove_outdated(backup), + {:ok, _} <- + backup + |> Pleroma.Emails.UserEmail.backup_is_ready_email() + |> Pleroma.Emails.Mailer.deliver() do {:ok, backup} end end -- cgit v1.2.3 From 7c22c9afb410668d87dcd4a90651d62d9a1e9e4d Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Fri, 18 Sep 2020 22:18:34 +0400 Subject: Allow admins request user backups --- lib/pleroma/backup.ex | 4 ++-- lib/pleroma/emails/user_email.ex | 20 +++++++++++++++----- .../admin_api/controllers/admin_api_controller.ex | 12 +++++++++++- lib/pleroma/web/router.ex | 2 ++ lib/pleroma/workers/backup_worker.ex | 10 ++++++---- 5 files changed, 36 insertions(+), 12 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/backup.ex b/lib/pleroma/backup.ex index 450dd5b84..d589f12f1 100644 --- a/lib/pleroma/backup.ex +++ b/lib/pleroma/backup.ex @@ -30,12 +30,12 @@ defmodule Pleroma.Backup do timestamps() end - def create(user) do + def create(user, admin_user_id \\ nil) do with :ok <- validate_email_enabled(), :ok <- validate_user_email(user), :ok <- validate_limit(user), {:ok, backup} <- user |> new() |> Repo.insert() do - BackupWorker.process(backup) + BackupWorker.process(backup, admin_user_id) end end diff --git a/lib/pleroma/emails/user_email.ex b/lib/pleroma/emails/user_email.ex index f943dda0d..5745794ec 100644 --- a/lib/pleroma/emails/user_email.ex +++ b/lib/pleroma/emails/user_email.ex @@ -190,14 +190,24 @@ defmodule Pleroma.Emails.UserEmail do Router.Helpers.subscription_url(Endpoint, :unsubscribe, token) end - def backup_is_ready_email(backup) do + def backup_is_ready_email(backup, admin_user_id \\ nil) do %{user: user} = Pleroma.Repo.preload(backup, :user) download_url = Pleroma.Web.PleromaAPI.BackupView.download_url(backup) - html_body = """ -

You requested a full backup of your Pleroma account. It's ready for download:

-

- """ + html_body = + if is_nil(admin_user_id) do + """ +

You requested a full backup of your Pleroma account. It's ready for download:

+

+ """ + else + admin = Pleroma.Repo.get(User, admin_user_id) + + """ +

Admin @#{admin.nickname} requested a full backup of your Pleroma account. It's ready for download:

+

+ """ + end new() |> to(recipient(user)) 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 d5713c3dd..f7d2fe5b1 100644 --- a/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex +++ b/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex @@ -23,12 +23,14 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do alias Pleroma.Web.Endpoint alias Pleroma.Web.Router + require Logger + @users_page_size 50 plug( OAuthScopesPlug, %{scopes: ["read:accounts"], admin: true} - when action in [:list_users, :user_show, :right_get, :show_user_credentials] + when action in [:list_users, :user_show, :right_get, :show_user_credentials, :create_backup] ) plug( @@ -681,6 +683,14 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do json(conn, %{"status_visibility" => counters}) end + def create_backup(%{assigns: %{user: admin}} = conn, %{"nickname" => nickname}) do + with %User{} = user <- User.get_by_nickname(nickname), + {:ok, _} <- Pleroma.Backup.create(user, admin.id) do + Logger.info("Admin @#{admin.nickname} requested account backup for @{nickname}") + json(conn, "") + end + end + defp page_params(params) do {get_page(params["page"]), get_page_size(params["page_size"])} end diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index a1a5a1cb5..e539eeeeb 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -129,6 +129,8 @@ defmodule Pleroma.Web.Router do scope "/api/pleroma/admin", Pleroma.Web.AdminAPI do pipe_through(:admin_api) + post("/backups", AdminAPIController, :create_backup) + post("/users/follow", AdminAPIController, :user_follow) post("/users/unfollow", AdminAPIController, :user_unfollow) diff --git a/lib/pleroma/workers/backup_worker.ex b/lib/pleroma/workers/backup_worker.ex index 405d55269..65754b6a2 100644 --- a/lib/pleroma/workers/backup_worker.ex +++ b/lib/pleroma/workers/backup_worker.ex @@ -8,8 +8,8 @@ defmodule Pleroma.Workers.BackupWorker do alias Oban.Job alias Pleroma.Backup - def process(backup) do - %{"op" => "process", "backup_id" => backup.id} + def process(backup, admin_user_id \\ nil) do + %{"op" => "process", "backup_id" => backup.id, "admin_user_id" => admin_user_id} |> new() |> Oban.insert() end @@ -30,14 +30,16 @@ defmodule Pleroma.Workers.BackupWorker do |> Oban.insert() end - def perform(%Job{args: %{"op" => "process", "backup_id" => backup_id}}) do + def perform(%Job{ + args: %{"op" => "process", "backup_id" => backup_id, "admin_user_id" => admin_user_id} + }) do with {:ok, %Backup{} = backup} <- backup_id |> Backup.get() |> Backup.process(), {:ok, _job} <- schedule_deletion(backup), :ok <- Backup.remove_outdated(backup), {:ok, _} <- backup - |> Pleroma.Emails.UserEmail.backup_is_ready_email() + |> Pleroma.Emails.UserEmail.backup_is_ready_email(admin_user_id) |> Pleroma.Emails.Mailer.deliver() do {:ok, backup} end -- cgit v1.2.3 From e50314d9d342dbf9a03ca484654b07717592d4bd Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Fri, 18 Sep 2020 22:33:12 +0400 Subject: Fix export --- lib/pleroma/backup.ex | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/backup.ex b/lib/pleroma/backup.ex index d589f12f1..242773bdb 100644 --- a/lib/pleroma/backup.ex +++ b/lib/pleroma/backup.ex @@ -191,16 +191,13 @@ defmodule Pleroma.Backup do counter = :counters.new(1, []) query - |> Pleroma.RepoStreamer.chunk_stream(100) - |> Stream.each(fn items -> - Enum.each(items, fn i -> - with {:ok, str} <- fun.(i), - :ok <- IO.write(file, str <> ",\n") do - :counters.add(counter, 1, 1) - end - end) + |> Pleroma.Repo.chunk_stream(100) + |> Enum.each(fn i -> + with {:ok, str} <- fun.(i), + :ok <- IO.write(file, str <> ",\n") do + :counters.add(counter, 1, 1) + end end) - |> Stream.run() total = :counters.get(counter, 1) -- cgit v1.2.3 From a9efd441e242f1d8ac608b866d0cfafe4833243a Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Sun, 20 Sep 2020 19:57:09 +0400 Subject: Use `Pleroma.Repo.chunk_stream/2` instead of `Pleroma.RepoStreamer.chunk_stream/2` --- lib/pleroma/backup.ex | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/backup.ex b/lib/pleroma/backup.ex index 242773bdb..f5f39431d 100644 --- a/lib/pleroma/backup.ex +++ b/lib/pleroma/backup.ex @@ -188,18 +188,17 @@ defmodule Pleroma.Backup do with {:ok, file} <- File.open(path, [:write, :utf8]), :ok <- write_header(file, name) do - counter = :counters.new(1, []) - - query - |> Pleroma.Repo.chunk_stream(100) - |> Enum.each(fn i -> - with {:ok, str} <- fun.(i), - :ok <- IO.write(file, str <> ",\n") do - :counters.add(counter, 1, 1) - end - end) - - total = :counters.get(counter, 1) + total = + query + |> Pleroma.Repo.chunk_stream(100) + |> Enum.reduce(0, fn i, acc -> + with {:ok, str} <- fun.(i), + :ok <- IO.write(file, str <> ",\n") do + acc + 1 + else + _ -> acc + end + end) with :ok <- :file.pwrite(file, {:eof, -2}, "\n],\n \"totalItems\": #{total}}") do File.close(file) -- cgit v1.2.3 From 17562bf4147ab03e171b1f1d365a512f2e5b3202 Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Sun, 20 Sep 2020 20:43:27 +0400 Subject: Move API endpoints to `/api/v1/pleroma/backups` --- lib/pleroma/web/router.ex | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index e539eeeeb..ad7e315c7 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -295,9 +295,6 @@ defmodule Pleroma.Web.Router do get("/accounts/mfa/setup/:method", TwoFactorAuthenticationController, :setup) post("/accounts/mfa/confirm/:method", TwoFactorAuthenticationController, :confirm) delete("/accounts/mfa/:method", TwoFactorAuthenticationController, :disable) - - get("/backups", BackupController, :index) - post("/backups", BackupController, :create) end scope "/oauth", Pleroma.Web.OAuth do @@ -358,6 +355,9 @@ defmodule Pleroma.Web.Router do put("/mascot", MascotController, :update) post("/scrobble", ScrobbleController, :create) + + get("/backups", BackupController, :index) + post("/backups", BackupController, :create) end scope [] do -- cgit v1.2.3 From e4792ce76af3094d378a3a201ca429ae38203696 Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Sun, 20 Sep 2020 21:06:16 +0400 Subject: Do not limit admins --- lib/pleroma/backup.ex | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/backup.ex b/lib/pleroma/backup.ex index f5f39431d..e2673db80 100644 --- a/lib/pleroma/backup.ex +++ b/lib/pleroma/backup.ex @@ -30,12 +30,12 @@ defmodule Pleroma.Backup do timestamps() end - def create(user, admin_user_id \\ nil) do + def create(user, admin_id \\ nil) do with :ok <- validate_email_enabled(), :ok <- validate_user_email(user), - :ok <- validate_limit(user), + :ok <- validate_limit(user, admin_id), {:ok, backup} <- user |> new() |> Repo.insert() do - BackupWorker.process(backup, admin_user_id) + BackupWorker.process(backup, admin_id) end end @@ -59,7 +59,9 @@ defmodule Pleroma.Backup do end end - defp validate_limit(user) do + defp validate_limit(_user, admin_id) when is_binary(admin_id), do: :ok + + defp validate_limit(user, nil) do case get_last(user.id) do %__MODULE__{inserted_at: inserted_at} -> days = Pleroma.Config.get([Pleroma.Backup, :limit_days]) -- cgit v1.2.3 From 8baee855d90530def46dc62b81e6a0cb0c315914 Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Mon, 21 Sep 2020 21:47:36 +0400 Subject: Fix emails --- lib/pleroma/emails/user_email.ex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/emails/user_email.ex b/lib/pleroma/emails/user_email.ex index 5745794ec..806a61fd2 100644 --- a/lib/pleroma/emails/user_email.ex +++ b/lib/pleroma/emails/user_email.ex @@ -198,14 +198,14 @@ defmodule Pleroma.Emails.UserEmail do if is_nil(admin_user_id) do """

You requested a full backup of your Pleroma account. It's ready for download:

-

+

#{download_url}

""" else admin = Pleroma.Repo.get(User, admin_user_id) """

Admin @#{admin.nickname} requested a full backup of your Pleroma account. It's ready for download:

-

+

#{download_url}

""" end -- cgit v1.2.3 From d7a5291b4fa3b7568674c0f7643fe287fcd21eff Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Sat, 26 Sep 2020 21:24:35 +0400 Subject: Use `Jason.encode/1` for likes and bookmarks --- lib/pleroma/backup.ex | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/backup.ex b/lib/pleroma/backup.ex index e2673db80..b43dc94d6 100644 --- a/lib/pleroma/backup.ex +++ b/lib/pleroma/backup.ex @@ -194,7 +194,8 @@ defmodule Pleroma.Backup do query |> Pleroma.Repo.chunk_stream(100) |> Enum.reduce(0, fn i, acc -> - with {:ok, str} <- fun.(i), + with {:ok, data} <- fun.(i), + {:ok, str} <- Jason.encode(data), :ok <- IO.write(file, str <> ",\n") do acc + 1 else @@ -213,7 +214,7 @@ defmodule Pleroma.Backup do |> where(user_id: ^user_id) |> join(:inner, [b], activity in assoc(b, :activity)) |> select([b, a], %{id: b.id, object: fragment("(?)->>'object'", a.data)}) - |> write(dir, "bookmarks", fn a -> {:ok, "\"#{a.object}\""} end) + |> write(dir, "bookmarks", fn a -> {:ok, a.object} end) end defp likes(dir, user) do @@ -221,7 +222,7 @@ defmodule Pleroma.Backup do |> Activity.Queries.by_actor() |> Activity.Queries.by_type("Like") |> select([like], %{id: like.id, object: fragment("(?)->>'object'", like.data)}) - |> write(dir, "likes", fn a -> {:ok, "\"#{a.object}\""} end) + |> write(dir, "likes", fn a -> {:ok, a.object} end) end defp statuses(dir, user) do @@ -239,7 +240,7 @@ defmodule Pleroma.Backup do |> ActivityPub.fetch_activities_query(opts) |> write(dir, "outbox", fn a -> with {:ok, activity} <- Transmogrifier.prepare_outgoing(a.data) do - activity |> Map.delete("@context") |> Jason.encode() + {:ok, Map.delete(activity, "@context")} end end) end -- cgit v1.2.3 From 9af9f02f4b3c4eac859a69ab9b2f546a91110287 Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Sat, 26 Sep 2020 21:45:03 +0400 Subject: Use Gettext for error messages --- lib/pleroma/backup.ex | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/backup.ex b/lib/pleroma/backup.ex index b43dc94d6..0ebaf02e5 100644 --- a/lib/pleroma/backup.ex +++ b/lib/pleroma/backup.ex @@ -7,6 +7,7 @@ defmodule Pleroma.Backup do import Ecto.Changeset import Ecto.Query + import Pleroma.Web.Gettext require Pleroma.Constants @@ -70,7 +71,14 @@ defmodule Pleroma.Backup do if diff > days do :ok else - {:error, "Last export was less than #{days} days ago"} + {:error, + dngettext( + "errors", + "Last export was less than a day ago", + "Last export was less than %{days} days ago", + days, + days: days + )} end nil -> @@ -82,11 +90,14 @@ defmodule Pleroma.Backup do if Pleroma.Config.get([Pleroma.Emails.Mailer, :enabled]) do :ok else - {:error, "Backups require enabled email"} + {:error, dgettext("errors", "Backups require enabled email")} end end - defp validate_user_email(%User{email: nil}), do: {:error, "Email is required"} + defp validate_user_email(%User{email: nil}) do + {:error, dgettext("errors", "Email is required")} + end + defp validate_user_email(%User{email: email}) when is_binary(email), do: :ok def get_last(user_id) do -- cgit v1.2.3 From 08972dd135c200073f5de0c8731b886cc2e72eeb Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Sat, 26 Sep 2020 21:50:31 +0400 Subject: Use Path.join/2 --- lib/pleroma/backup.ex | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/backup.ex b/lib/pleroma/backup.ex index 0ebaf02e5..cee51d7c1 100644 --- a/lib/pleroma/backup.ex +++ b/lib/pleroma/backup.ex @@ -55,7 +55,7 @@ defmodule Pleroma.Backup do def delete(backup) do uploader = Pleroma.Config.get([Pleroma.Upload, :uploader]) - with :ok <- uploader.delete_file("backups/" <> backup.file_name) do + with :ok <- uploader.delete_file(Path.join("backups", backup.file_name)) do Repo.delete(backup) end end @@ -164,7 +164,7 @@ defmodule Pleroma.Backup do name: backup.file_name, tempfile: zip_path, content_type: backup.content_type, - path: "backups/" <> backup.file_name + path: Path.join("backups", backup.file_name) } with {:ok, _} <- Pleroma.Uploaders.Uploader.put_file(uploader, upload), @@ -178,7 +178,7 @@ defmodule Pleroma.Backup do UserView.render("user.json", %{user: user}) |> Map.merge(%{"likes" => "likes.json", "bookmarks" => "bookmarks.json"}) |> Jason.encode() do - File.write(dir <> "/actor.json", json) + File.write(Path.join(dir, "actor.json"), json) end end @@ -197,7 +197,7 @@ defmodule Pleroma.Backup do end defp write(query, dir, name, fun) do - path = dir <> "/#{name}.json" + path = Path.join(dir, "#{name}.json") with {:ok, file} <- File.open(path, [:write, :utf8]), :ok <- write_header(file, name) do -- cgit v1.2.3 From 8545d533ddee2978e9bf7f3284cc7dcb822a77e6 Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Sat, 26 Sep 2020 21:53:04 +0400 Subject: Use to_string/1 instead of :binary.list_to_bin/1 --- lib/pleroma/backup.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/backup.ex b/lib/pleroma/backup.ex index cee51d7c1..629e879a7 100644 --- a/lib/pleroma/backup.ex +++ b/lib/pleroma/backup.ex @@ -148,7 +148,7 @@ defmodule Pleroma.Backup do :ok <- bookmarks(dir, backup.user), {:ok, zip_path} <- :zip.create(String.to_charlist(dir <> ".zip"), @files, cwd: dir), {:ok, _} <- File.rm_rf(dir) do - {:ok, :binary.list_to_bin(zip_path)} + {:ok, to_string(zip_path)} end end -- cgit v1.2.3 From bc3db724030707e9903d161a70b10fe217a83212 Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Sat, 26 Sep 2020 23:16:56 +0400 Subject: Use ModerationLog instead of Logger --- lib/pleroma/moderation_log.ex | 10 ++++++++++ lib/pleroma/web/admin_api/controllers/admin_api_controller.ex | 3 ++- 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/moderation_log.ex b/lib/pleroma/moderation_log.ex index 47036a6f6..be1e81467 100644 --- a/lib/pleroma/moderation_log.ex +++ b/lib/pleroma/moderation_log.ex @@ -651,6 +651,16 @@ defmodule Pleroma.ModerationLog do "@#{actor_nickname} deleted chat message ##{subject_id}" end + def get_log_entry_message(%ModerationLog{ + data: %{ + "actor" => %{"nickname" => actor_nickname}, + "action" => "create_backup", + "subject" => %{"nickname" => user_nickname} + } + }) do + "@#{actor_nickname} requested account backup for @#{user_nickname}" + end + defp nicknames_to_string(nicknames) do nicknames |> Enum.map(&"@#{&1}") 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 f7d2fe5b1..8b5310d80 100644 --- a/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex +++ b/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex @@ -686,7 +686,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do def create_backup(%{assigns: %{user: admin}} = conn, %{"nickname" => nickname}) do with %User{} = user <- User.get_by_nickname(nickname), {:ok, _} <- Pleroma.Backup.create(user, admin.id) do - Logger.info("Admin @#{admin.nickname} requested account backup for @{nickname}") + ModerationLog.insert_log(%{actor: admin, subject: user, action: "create_backup"}) + json(conn, "") end end -- cgit v1.2.3 From 636c00037d797161c4ecd654345a436452f99415 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Wed, 7 Oct 2020 09:58:45 -0500 Subject: Fix duplicate @doc entries --- lib/pleroma/web/activity_pub/publisher.ex | 4 +--- lib/pleroma/web/common_api/utils.ex | 11 +---------- lib/pleroma/web/mastodon_api/controllers/auth_controller.ex | 4 ++-- lib/pleroma/web/mastodon_api/controllers/status_controller.ex | 8 ++------ 4 files changed, 6 insertions(+), 21 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/activity_pub/publisher.ex b/lib/pleroma/web/activity_pub/publisher.ex index 9c3956683..a2930c1cd 100644 --- a/lib/pleroma/web/activity_pub/publisher.ex +++ b/lib/pleroma/web/activity_pub/publisher.ex @@ -242,9 +242,7 @@ defmodule Pleroma.Web.ActivityPub.Publisher do end) end - @doc """ - Publishes an activity to all relevant peers. - """ + # Publishes an activity to all relevant peers. def publish(%User{} = actor, %Activity{} = activity) do public = is_public?(activity) diff --git a/lib/pleroma/web/common_api/utils.ex b/lib/pleroma/web/common_api/utils.ex index 9d7b24eb2..85dcd89dc 100644 --- a/lib/pleroma/web/common_api/utils.ex +++ b/lib/pleroma/web/common_api/utils.ex @@ -274,7 +274,7 @@ defmodule Pleroma.Web.CommonAPI.Utils do def format_input(text, format, options \\ []) @doc """ - Formatting text to plain text. + Formatting text to plain text, BBCode, HTML, or Markdown """ def format_input(text, "text/plain", options) do text @@ -285,9 +285,6 @@ defmodule Pleroma.Web.CommonAPI.Utils do end).() end - @doc """ - Formatting text as BBCode. - """ def format_input(text, "text/bbcode", options) do text |> String.replace(~r/\r/, "") @@ -297,18 +294,12 @@ defmodule Pleroma.Web.CommonAPI.Utils do |> Formatter.linkify(options) end - @doc """ - Formatting text to html. - """ def format_input(text, "text/html", options) do text |> Formatter.html_escape("text/html") |> Formatter.linkify(options) end - @doc """ - Formatting text to markdown. - """ def format_input(text, "text/markdown", options) do text |> Formatter.mentions_escape(options) diff --git a/lib/pleroma/web/mastodon_api/controllers/auth_controller.ex b/lib/pleroma/web/mastodon_api/controllers/auth_controller.ex index 57c0be5fe..a278ca622 100644 --- a/lib/pleroma/web/mastodon_api/controllers/auth_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/auth_controller.ex @@ -24,7 +24,7 @@ defmodule Pleroma.Web.MastodonAPI.AuthController do redirect(conn, to: local_mastodon_root_path(conn)) end - @doc "Local Mastodon FE login init action" + # Local Mastodon FE login init action def login(conn, %{"code" => auth_token}) do with {:ok, app} <- get_or_make_app(), {:ok, auth} <- Authorization.get_by_token(app, auth_token), @@ -35,7 +35,7 @@ defmodule Pleroma.Web.MastodonAPI.AuthController do end end - @doc "Local Mastodon FE callback action" + # Local Mastodon FE callback action def login(conn, _) do with {:ok, app} <- get_or_make_app() do path = diff --git a/lib/pleroma/web/mastodon_api/controllers/status_controller.ex b/lib/pleroma/web/mastodon_api/controllers/status_controller.ex index ecfa38489..c85757f26 100644 --- a/lib/pleroma/web/mastodon_api/controllers/status_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/status_controller.ex @@ -123,9 +123,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do @doc """ POST /api/v1/statuses - - Creates a scheduled status when `scheduled_at` param is present and it's far enough """ + # Creates a scheduled status when `scheduled_at` param is present and it's far enough def create( %{ assigns: %{user: user}, @@ -156,11 +155,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do end end - @doc """ - POST /api/v1/statuses - Creates a regular status - """ + # Creates a regular status def create(%{assigns: %{user: user}, body_params: %{status: _} = params} = conn, _) do params = Map.put(params, :in_reply_to_status_id, params[:in_reply_to_id]) -- cgit v1.2.3 From d3106c69c80af58244faa0373b01c618371f84e0 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Wed, 7 Oct 2020 10:02:20 -0500 Subject: Fix incompatible type (Elixir 1.11) --- lib/pleroma/web/media_proxy/invalidations/http.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/web/media_proxy/invalidations/http.ex b/lib/pleroma/web/media_proxy/invalidations/http.ex index bb81d8888..694eb559b 100644 --- a/lib/pleroma/web/media_proxy/invalidations/http.ex +++ b/lib/pleroma/web/media_proxy/invalidations/http.ex @@ -30,7 +30,7 @@ defmodule Pleroma.Web.MediaProxy.Invalidation.Http do {:ok, %{status: status} = env} when 400 <= status and status < 500 -> {:error, env} - {:error, error} = error -> + {:error, error} -> error _ -> -- cgit v1.2.3 From 218a3e61e1692058aaf5f16506cbf276d2260722 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Wed, 7 Oct 2020 10:04:25 -0500 Subject: Fix incompatible types warning (Elixir 1.11) --- lib/pleroma/web/activity_pub/activity_pub_controller.ex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/activity_pub/activity_pub_controller.ex b/lib/pleroma/web/activity_pub/activity_pub_controller.ex index 732c44271..8916aba5f 100644 --- a/lib/pleroma/web/activity_pub/activity_pub_controller.ex +++ b/lib/pleroma/web/activity_pub/activity_pub_controller.ex @@ -412,7 +412,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do object = object |> Map.merge(Map.take(params, ["to", "cc"])) - |> Map.put("attributedTo", user.ap_id()) + |> Map.put("attributedTo", user.ap_id) |> Transmogrifier.fix_object() ActivityPub.create(%{ @@ -456,7 +456,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do %{assigns: %{user: %User{nickname: nickname} = user}} = conn, %{"nickname" => nickname} = params ) do - actor = user.ap_id() + actor = user.ap_id params = params -- cgit v1.2.3 From 6d1666a080ad97ba1233d50ba36d3b8a136f75a7 Mon Sep 17 00:00:00 2001 From: feld Date: Wed, 7 Oct 2020 16:44:52 +0000 Subject: Apply 1 suggestion(s) to 1 file(s) --- lib/pleroma/web/media_proxy/invalidations/http.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/web/media_proxy/invalidations/http.ex b/lib/pleroma/web/media_proxy/invalidations/http.ex index 694eb559b..0b0cde68c 100644 --- a/lib/pleroma/web/media_proxy/invalidations/http.ex +++ b/lib/pleroma/web/media_proxy/invalidations/http.ex @@ -30,7 +30,7 @@ defmodule Pleroma.Web.MediaProxy.Invalidation.Http do {:ok, %{status: status} = env} when 400 <= status and status < 500 -> {:error, env} - {:error, error} -> + {:error, _} = error -> error _ -> -- cgit v1.2.3 From 8caa6cf91d0d354ce64c1d923112d358295222a2 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Wed, 7 Oct 2020 11:47:10 -0500 Subject: Transport.connect/7 is deprecated --- lib/transports.ex | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/transports.ex b/lib/transports.ex index aab7fad99..1ed3a942d 100644 --- a/lib/transports.ex +++ b/lib/transports.ex @@ -31,7 +31,12 @@ defmodule Phoenix.Transports.WebSocket.Raw do case conn do %{halted: false} = conn -> - case Transport.connect(endpoint, handler, transport, __MODULE__, nil, conn.params) do + case Transport.connect(%{ + endpoint: endpoint, + transport: transport, + options: [serializer: nil], + params: conn.params + }) do {:ok, socket} -> {:ok, conn, {__MODULE__, {socket, opts}}} -- cgit v1.2.3 From 42e78a08b28f3faee21b803c1e621e96bbf5c731 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Wed, 7 Oct 2020 12:30:55 -0500 Subject: Fix rendering of reports --- lib/pleroma/web/admin_api/views/report_view.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/web/admin_api/views/report_view.ex b/lib/pleroma/web/admin_api/views/report_view.ex index 773f798fe..535556370 100644 --- a/lib/pleroma/web/admin_api/views/report_view.ex +++ b/lib/pleroma/web/admin_api/views/report_view.ex @@ -52,7 +52,7 @@ defmodule Pleroma.Web.AdminAPI.ReportView do end def render("index_notes.json", %{notes: notes}) when is_list(notes) do - Enum.map(notes, &render(__MODULE__, "show_note.json", &1)) + Enum.map(notes, &render(__MODULE__, "show_note.json", Map.from_struct(&1))) end def render("index_notes.json", _), do: [] -- cgit v1.2.3 From 70880d54f85a96d07b6c72adfbf3f1a7c50f95a2 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Wed, 7 Oct 2020 12:55:16 -0500 Subject: @env is not used --- lib/pleroma/application.ex | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/application.ex b/lib/pleroma/application.ex index e73d89350..02dd39939 100644 --- a/lib/pleroma/application.ex +++ b/lib/pleroma/application.ex @@ -99,7 +99,7 @@ defmodule Pleroma.Application do ] ++ task_children(@env) ++ dont_run_in_test(@env) ++ - chat_child(@env, chat_enabled?()) ++ + chat_child(chat_enabled?()) ++ [ Pleroma.Web.Endpoint, Pleroma.Gopher.Server @@ -201,11 +201,11 @@ defmodule Pleroma.Application do ] end - defp chat_child(_env, true) do + defp chat_child(true) do [Pleroma.Web.ChatChannel.ChatChannelState] end - defp chat_child(_, _), do: [] + defp chat_child(_), do: [] defp task_children(:test) do [ -- cgit v1.2.3 From 8156940a49df17c00c05bfe60223b165f9dc034b Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Wed, 7 Oct 2020 13:28:39 -0500 Subject: Compatibility with phoenix_pubsub 2.0.0 --- lib/pleroma/application.ex | 5 ++++- lib/pleroma/web/web.ex | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/application.ex b/lib/pleroma/application.ex index 02dd39939..fe94b56f4 100644 --- a/lib/pleroma/application.ex +++ b/lib/pleroma/application.ex @@ -202,7 +202,10 @@ defmodule Pleroma.Application do end defp chat_child(true) do - [Pleroma.Web.ChatChannel.ChatChannelState] + [ + Pleroma.Web.ChatChannel.ChatChannelState, + {Phoenix.PubSub, [name: Pleroma.PubSub, adapter: Phoenix.PubSub.PG2]} + ] end defp chat_child(_), do: [] diff --git a/lib/pleroma/web/web.ex b/lib/pleroma/web/web.ex index 4f9281851..c319d223c 100644 --- a/lib/pleroma/web/web.ex +++ b/lib/pleroma/web/web.ex @@ -177,7 +177,7 @@ defmodule Pleroma.Web do def channel do quote do # credo:disable-for-next-line Credo.Check.Consistency.MultiAliasImportRequireUse - use Phoenix.Channel + import Phoenix.Channel import Pleroma.Web.Gettext end end -- cgit v1.2.3 From 822e4472f3de1492aed6948514bc357c9adb934c Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Wed, 7 Oct 2020 15:06:16 -0500 Subject: Fix incorrect use of connect/1 Hint from Phoenix 1.4.17, which has a connect/7 shim: lib/phoenix/socket/transport.ex: def connect(endpoint, handler, _transport_name, transport, serializers, params, _pid \\ self()) do IO.warn "Phoenix.Socket.Transport.connect/7 is deprecated" handler.connect(%{ endpoint: endpoint, transport: transport, options: [serializer: serializers], params: params }) end --- lib/transports.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/transports.ex b/lib/transports.ex index 1ed3a942d..c3665bebe 100644 --- a/lib/transports.ex +++ b/lib/transports.ex @@ -31,7 +31,7 @@ defmodule Phoenix.Transports.WebSocket.Raw do case conn do %{halted: false} = conn -> - case Transport.connect(%{ + case handler.connect(%{ endpoint: endpoint, transport: transport, options: [serializer: nil], -- cgit v1.2.3 From ed6511a086694fc163b488d807f17d246f80ad5b Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Wed, 7 Oct 2020 15:28:29 -0500 Subject: Lint --- lib/pleroma/web/mastodon_api/controllers/status_controller.ex | 1 - 1 file changed, 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/web/mastodon_api/controllers/status_controller.ex b/lib/pleroma/web/mastodon_api/controllers/status_controller.ex index c85757f26..a47a7af95 100644 --- a/lib/pleroma/web/mastodon_api/controllers/status_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/status_controller.ex @@ -155,7 +155,6 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do end end - # Creates a regular status def create(%{assigns: %{user: user}, body_params: %{status: _} = params} = conn, _) do params = Map.put(params, :in_reply_to_status_id, params[:in_reply_to_id]) -- cgit v1.2.3 From e1eb54d3899883b5af6a43687a2345543d69ad4a Mon Sep 17 00:00:00 2001 From: Ivan Tashkinov Date: Sun, 11 Oct 2020 13:37:19 +0300 Subject: [#3053] Rollback of access control changes in ActivityPubController (base actions: :user, :object, :activity). --- .../web/activity_pub/activity_pub_controller.ex | 56 ++++++++++------------ 1 file changed, 25 insertions(+), 31 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/activity_pub/activity_pub_controller.ex b/lib/pleroma/web/activity_pub/activity_pub_controller.ex index c78edfb4c..732c44271 100644 --- a/lib/pleroma/web/activity_pub/activity_pub_controller.ex +++ b/lib/pleroma/web/activity_pub/activity_pub_controller.ex @@ -32,23 +32,17 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do @federating_only_actions [:internal_fetch, :relay, :relay_following, :relay_followers] - # Note: :following and :followers must be served even without authentication (as via :api) - @auth_only_actions [:read_inbox, :update_outbox, :whoami, :upload_media] - - # Always accessible actions (must perform entity accessibility checks) - @no_auth_no_federation_actions [:user, :activity, :object] - - @authenticated_or_federating_actions @federating_only_actions ++ - @auth_only_actions ++ @no_auth_no_federation_actions - plug(FederatingPlug when action in @federating_only_actions) - plug(EnsureAuthenticatedPlug when action in @auth_only_actions) - plug( EnsureAuthenticatedPlug, - [unless_func: &FederatingPlug.federating?/1] - when action not in @authenticated_or_federating_actions + [unless_func: &FederatingPlug.federating?/1] when action not in @federating_only_actions + ) + + # Note: :following and :followers must be served even without authentication (as via :api) + plug( + EnsureAuthenticatedPlug + when action in [:read_inbox, :update_outbox, :whoami, :upload_media] ) plug( @@ -72,22 +66,21 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do def user(conn, %{"nickname" => nickname}) do with %User{local: true} = user <- User.get_cached_by_nickname(nickname), - {_, :visible} <- {:visibility, User.visible_for(user, _reading_user = nil)}, {:ok, user} <- User.ensure_keys_present(user) do conn |> put_resp_content_type("application/activity+json") |> put_view(UserView) |> render("user.json", %{user: user}) else - _ -> {:error, :not_found} + nil -> {:error, :not_found} + %{local: false} -> {:error, :not_found} end end def object(conn, _) do with ap_id <- Endpoint.url() <> conn.request_path, %Object{} = object <- Object.get_cached_by_ap_id(ap_id), - {_, true} <- {:public?, Visibility.is_public?(object)}, - {_, false} <- {:restricted?, Visibility.restrict_unauthenticated_access?(object)} do + {_, true} <- {:public?, Visibility.is_public?(object)} do conn |> assign(:tracking_fun_data, object.id) |> set_cache_ttl_for(object) @@ -95,15 +88,25 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do |> put_view(ObjectView) |> render("object.json", object: object) else - _ -> {:error, :not_found} + {:public?, false} -> + {:error, :not_found} end end + def track_object_fetch(conn, nil), do: conn + + def track_object_fetch(conn, object_id) do + with %{assigns: %{user: %User{id: user_id}}} <- conn do + Delivery.create(object_id, user_id) + end + + conn + end + def activity(conn, _params) do with ap_id <- Endpoint.url() <> conn.request_path, %Activity{} = activity <- Activity.normalize(ap_id), - {_, true} <- {:public?, Visibility.is_public?(activity)}, - {_, true} <- {:visible?, Visibility.visible_for_user?(activity, _reading_user = nil)} do + {_, true} <- {:public?, Visibility.is_public?(activity)} do conn |> maybe_set_tracking_data(activity) |> set_cache_ttl_for(activity) @@ -111,7 +114,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do |> put_view(ObjectView) |> render("object.json", object: activity) else - _ -> {:error, :not_found} + {:public?, false} -> {:error, :not_found} + nil -> {:error, :not_found} end end @@ -546,14 +550,4 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do |> json(object.data) end end - - def track_object_fetch(conn, nil), do: conn - - def track_object_fetch(conn, object_id) do - with %{assigns: %{user: %User{id: user_id}}} <- conn do - Delivery.create(object_id, user_id) - end - - conn - end end -- cgit v1.2.3 From 89c595b772eaaa8809f5339d708d7dc22e51b662 Mon Sep 17 00:00:00 2001 From: Ivan Tashkinov Date: Sun, 11 Oct 2020 22:34:28 +0300 Subject: [#3053] Removed target accessibility checks for OStatus endpoints delegating to RedirectController. Added tests. --- lib/pleroma/web/ostatus/ostatus_controller.ex | 13 ++++----- lib/pleroma/web/router.ex | 38 +++++++++++++-------------- 2 files changed, 24 insertions(+), 27 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/ostatus/ostatus_controller.ex b/lib/pleroma/web/ostatus/ostatus_controller.ex index b4dc2a87f..e03ca8c0a 100644 --- a/lib/pleroma/web/ostatus/ostatus_controller.ex +++ b/lib/pleroma/web/ostatus/ostatus_controller.ex @@ -37,11 +37,10 @@ defmodule Pleroma.Web.OStatus.OStatusController do with id <- Endpoint.url() <> conn.request_path, {_, %Activity{} = activity} <- {:activity, Activity.get_create_by_object_ap_id_with_object(id)}, - {_, true} <- {:public?, Visibility.is_public?(activity)}, - {_, true} <- {:visible?, Visibility.visible_for_user?(activity, _reading_user = nil)} do + {_, true} <- {:public?, Visibility.is_public?(activity)} do redirect(conn, to: "/notice/#{activity.id}") else - reason when reason in [{:public?, false}, {:visible?, false}, {:activity, nil}] -> + reason when reason in [{:public?, false}, {:activity, nil}] -> {:error, :not_found} e -> @@ -57,11 +56,10 @@ defmodule Pleroma.Web.OStatus.OStatusController do def activity(conn, _params) do with id <- Endpoint.url() <> conn.request_path, {_, %Activity{} = activity} <- {:activity, Activity.normalize(id)}, - {_, true} <- {:public?, Visibility.is_public?(activity)}, - {_, true} <- {:visible?, Visibility.visible_for_user?(activity, _reading_user = nil)} do + {_, true} <- {:public?, Visibility.is_public?(activity)} do redirect(conn, to: "/notice/#{activity.id}") else - reason when reason in [{:public?, false}, {:visible?, false}, {:activity, nil}] -> + reason when reason in [{:public?, false}, {:activity, nil}] -> {:error, :not_found} e -> @@ -72,7 +70,6 @@ defmodule Pleroma.Web.OStatus.OStatusController do def notice(%{assigns: %{format: format}} = conn, %{"id" => id}) do with {_, %Activity{} = activity} <- {:activity, Activity.get_by_id_with_object(id)}, {_, true} <- {:public?, Visibility.is_public?(activity)}, - {_, true} <- {:visible?, Visibility.visible_for_user?(activity, _reading_user = nil)}, %User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]) do cond do format in ["json", "activity+json"] -> @@ -100,7 +97,7 @@ defmodule Pleroma.Web.OStatus.OStatusController do RedirectController.redirector(conn, nil) end else - reason when reason in [{:public?, false}, {:visible?, false}, {:activity, nil}] -> + reason when reason in [{:public?, false}, {:activity, nil}] -> conn |> put_status(404) |> RedirectController.redirector(nil, 404) diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index 97fcaafd5..ef56360ed 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -9,6 +9,18 @@ defmodule Pleroma.Web.Router do plug(:accepts, ["html"]) end + pipeline :accepts_html_xml do + plug(:accepts, ["html", "xml", "rss", "atom"]) + end + + pipeline :accepts_html_json do + plug(:accepts, ["html", "activity+json", "json"]) + end + + pipeline :accepts_html_xml_json do + plug(:accepts, ["html", "xml", "rss", "atom", "activity+json", "json"]) + end + pipeline :accepts_xml_rss_atom do plug(:accepts, ["xml", "rss", "atom"]) end @@ -574,24 +586,10 @@ defmodule Pleroma.Web.Router do ) end - pipeline :ostatus_html_json do - plug(:accepts, ["html", "activity+json", "json"]) - plug(Pleroma.Plugs.StaticFEPlug) - end - - pipeline :ostatus_html_xml do - plug(:accepts, ["html", "xml", "rss", "atom"]) - plug(Pleroma.Plugs.StaticFEPlug) - end - - pipeline :ostatus_html_xml_json do - plug(:accepts, ["html", "xml", "rss", "atom", "activity+json", "json"]) - plug(Pleroma.Plugs.StaticFEPlug) - end - scope "/", Pleroma.Web do # Note: html format is supported only if static FE is enabled - pipe_through(:ostatus_html_json) + # Note: http signature is only considered for json requests (no auth for non-json requests) + pipe_through([:accepts_html_json, :http_signature, Pleroma.Plugs.StaticFEPlug]) get("/objects/:uuid", OStatus.OStatusController, :object) get("/activities/:uuid", OStatus.OStatusController, :activity) @@ -604,15 +602,17 @@ defmodule Pleroma.Web.Router do scope "/", Pleroma.Web do # Note: html format is supported only if static FE is enabled - pipe_through(:ostatus_html_xml_json) + # Note: http signature is only considered for json requests (no auth for non-json requests) + pipe_through([:accepts_html_xml_json, :http_signature, Pleroma.Plugs.StaticFEPlug]) - # Note: for json format responds with user profile (not user feed) + # Note: returns user _profile_ for json requests, redirects to user _feed_ for non-json ones get("/users/:nickname", Feed.UserController, :feed_redirect, as: :user_feed) end scope "/", Pleroma.Web do # Note: html format is supported only if static FE is enabled - pipe_through(:ostatus_html_xml) + pipe_through([:accepts_html_xml, Pleroma.Plugs.StaticFEPlug]) + get("/users/:nickname/feed", Feed.UserController, :feed, as: :user_feed) end -- cgit v1.2.3 From 9968b7efedc64d0239db5578de7fc66ff4ce894d Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Tue, 13 Oct 2020 09:31:13 -0500 Subject: Change user.locked field to user.is_locked --- lib/mix/tasks/pleroma/user.ex | 6 +++--- lib/pleroma/user.ex | 12 ++++++------ lib/pleroma/web/activity_pub/activity_pub.ex | 4 ++-- lib/pleroma/web/activity_pub/side_effects.ex | 2 +- lib/pleroma/web/activity_pub/views/user_view.ex | 2 +- lib/pleroma/web/admin_api/views/account_view.ex | 2 +- lib/pleroma/web/api_spec/operations/account_operation.ex | 2 +- lib/pleroma/web/api_spec/operations/chat_operation.ex | 2 +- lib/pleroma/web/api_spec/schemas/account.ex | 4 ++-- lib/pleroma/web/api_spec/schemas/chat.ex | 2 +- lib/pleroma/web/api_spec/schemas/status.ex | 2 +- .../web/mastodon_api/controllers/account_controller.ex | 2 +- lib/pleroma/web/mastodon_api/views/account_view.ex | 2 +- 13 files changed, 22 insertions(+), 22 deletions(-) (limited to 'lib') diff --git a/lib/mix/tasks/pleroma/user.ex b/lib/mix/tasks/pleroma/user.ex index e06262804..a8d251411 100644 --- a/lib/mix/tasks/pleroma/user.ex +++ b/lib/mix/tasks/pleroma/user.ex @@ -419,7 +419,7 @@ defmodule Mix.Tasks.Pleroma.User do |> Enum.each(fn user -> shell_info( "#{user.nickname} moderator: #{user.is_moderator}, admin: #{user.is_admin}, locked: #{ - user.locked + user.is_locked }, deactivated: #{user.deactivated}" ) end) @@ -447,10 +447,10 @@ defmodule Mix.Tasks.Pleroma.User do defp set_locked(user, value) do {:ok, user} = user - |> Changeset.change(%{locked: value}) + |> Changeset.change(%{is_locked: value}) |> User.update_and_set_cache() - shell_info("Locked status of #{user.nickname}: #{user.locked}") + shell_info("Locked status of #{user.nickname}: #{user.is_locked}") user end diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 09ea80793..87c8bfbd1 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -107,7 +107,7 @@ defmodule Pleroma.User do field(:note_count, :integer, default: 0) field(:follower_count, :integer, default: 0) field(:following_count, :integer, default: 0) - field(:locked, :boolean, default: false) + field(:is_locked, :boolean, default: false) field(:confirmation_pending, :boolean, default: false) field(:password_reset_pending, :boolean, default: false) field(:approval_pending, :boolean, default: false) @@ -436,7 +436,7 @@ defmodule Pleroma.User do :avatar, :ap_enabled, :banner, - :locked, + :is_locked, :last_refreshed_at, :uri, :follower_address, @@ -479,7 +479,7 @@ defmodule Pleroma.User do :public_key, :inbox, :shared_inbox, - :locked, + :is_locked, :no_rich_text, :default_scope, :banner, @@ -847,7 +847,7 @@ defmodule Pleroma.User do @spec maybe_direct_follow(User.t(), User.t()) :: {:ok, User.t()} | {:error, String.t()} # "Locked" (self-locked) users demand explicit authorization of follow requests - def maybe_direct_follow(%User{} = follower, %User{local: true, locked: true} = followed) do + def maybe_direct_follow(%User{} = follower, %User{local: true, is_locked: true} = followed) do follow(follower, followed, :follow_pending) end @@ -954,7 +954,7 @@ defmodule Pleroma.User do end def locked?(%User{} = user) do - user.locked || false + user.is_locked || false end def get_by_id(id) do @@ -1601,7 +1601,7 @@ defmodule Pleroma.User do note_count: 0, follower_count: 0, following_count: 0, - locked: false, + is_locked: false, confirmation_pending: false, password_reset_pending: false, approval_pending: false, diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index eb44cffec..8022f0402 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -1228,7 +1228,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do {String.trim(name, ":"), url} end) - locked = data["manuallyApprovesFollowers"] || false + is_locked = data["manuallyApprovesFollowers"] || false capabilities = data["capabilities"] || %{} accepts_chat_messages = capabilities["acceptsChatMessages"] data = Transmogrifier.maybe_fix_user_object(data) @@ -1257,7 +1257,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do banner: banner, fields: fields, emoji: emojis, - locked: locked, + is_locked: is_locked, discoverable: discoverable, invisible: invisible, avatar: avatar, diff --git a/lib/pleroma/web/activity_pub/side_effects.ex b/lib/pleroma/web/activity_pub/side_effects.ex index 2eec0ce86..d421ca7af 100644 --- a/lib/pleroma/web/activity_pub/side_effects.ex +++ b/lib/pleroma/web/activity_pub/side_effects.ex @@ -102,7 +102,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do %User{} = followed <- User.get_cached_by_ap_id(followed_user), {_, {:ok, _}, _, _} <- {:following, User.follow(follower, followed, :follow_pending), follower, followed} do - if followed.local && !followed.locked do + if followed.local && !followed.is_locked do {:ok, accept_data, _} = Builder.accept(followed, object) {:ok, _activity, _} = Pipeline.common_pipeline(accept_data, local: true) end diff --git a/lib/pleroma/web/activity_pub/views/user_view.ex b/lib/pleroma/web/activity_pub/views/user_view.ex index 3a4564912..c6dee61db 100644 --- a/lib/pleroma/web/activity_pub/views/user_view.ex +++ b/lib/pleroma/web/activity_pub/views/user_view.ex @@ -101,7 +101,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do "name" => user.name, "summary" => user.bio, "url" => user.ap_id, - "manuallyApprovesFollowers" => user.locked, + "manuallyApprovesFollowers" => user.is_locked, "publicKey" => %{ "id" => "#{user.ap_id}#main-key", "owner" => user.ap_id, diff --git a/lib/pleroma/web/admin_api/views/account_view.ex b/lib/pleroma/web/admin_api/views/account_view.ex index 9c477feab..bda7ea19c 100644 --- a/lib/pleroma/web/admin_api/views/account_view.ex +++ b/lib/pleroma/web/admin_api/views/account_view.ex @@ -39,7 +39,7 @@ defmodule Pleroma.Web.AdminAPI.AccountView do :fields, :name, :nickname, - :locked, + :is_locked, :no_rich_text, :default_scope, :hide_follows, diff --git a/lib/pleroma/web/api_spec/operations/account_operation.ex b/lib/pleroma/web/api_spec/operations/account_operation.ex index d90ddb787..57f25e1d8 100644 --- a/lib/pleroma/web/api_spec/operations/account_operation.ex +++ b/lib/pleroma/web/api_spec/operations/account_operation.ex @@ -519,7 +519,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do description: "Header image encoded using multipart/form-data", format: :binary }, - locked: %Schema{ + is_locked: %Schema{ allOf: [BooleanLike], nullable: true, description: "Whether manual approval of follow requests is required." diff --git a/lib/pleroma/web/api_spec/operations/chat_operation.ex b/lib/pleroma/web/api_spec/operations/chat_operation.ex index 0dcfdb354..df786e480 100644 --- a/lib/pleroma/web/api_spec/operations/chat_operation.ex +++ b/lib/pleroma/web/api_spec/operations/chat_operation.ex @@ -259,7 +259,7 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do "fields" => [] }, "statuses_count" => 1, - "locked" => false, + "is_locked" => false, "created_at" => "2020-04-16T13:40:15.000Z", "display_name" => "lain", "fields" => [], diff --git a/lib/pleroma/web/api_spec/schemas/account.ex b/lib/pleroma/web/api_spec/schemas/account.ex index ca79f0747..b8ddf4ab8 100644 --- a/lib/pleroma/web/api_spec/schemas/account.ex +++ b/lib/pleroma/web/api_spec/schemas/account.ex @@ -32,7 +32,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Account do header_static: %Schema{type: :string, format: :uri}, header: %Schema{type: :string, format: :uri}, id: FlakeID, - locked: %Schema{type: :boolean}, + is_locked: %Schema{type: :boolean}, note: %Schema{type: :string, format: :html}, statuses_count: %Schema{type: :integer}, url: %Schema{type: :string, format: :uri}, @@ -159,7 +159,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Account do "header" => "https://mypleroma.com/images/banner.png", "header_static" => "https://mypleroma.com/images/banner.png", "id" => "9tKi3esbG7OQgZ2920", - "locked" => false, + "is_locked" => false, "note" => "cofe", "pleroma" => %{ "allow_following_move" => true, diff --git a/lib/pleroma/web/api_spec/schemas/chat.ex b/lib/pleroma/web/api_spec/schemas/chat.ex index b4986b734..65f908e33 100644 --- a/lib/pleroma/web/api_spec/schemas/chat.ex +++ b/lib/pleroma/web/api_spec/schemas/chat.ex @@ -50,7 +50,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Chat do "fields" => [] }, "statuses_count" => 1, - "locked" => false, + "is_locked" => false, "created_at" => "2020-04-16T13:40:15.000Z", "display_name" => "lain", "fields" => [], diff --git a/lib/pleroma/web/api_spec/schemas/status.ex b/lib/pleroma/web/api_spec/schemas/status.ex index 947e42890..e6890df2d 100644 --- a/lib/pleroma/web/api_spec/schemas/status.ex +++ b/lib/pleroma/web/api_spec/schemas/status.ex @@ -252,7 +252,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Status do "header" => "http://localhost:4001/images/banner.png", "header_static" => "http://localhost:4001/images/banner.png", "id" => "9toJCsKN7SmSf3aj5c", - "locked" => false, + "is_locked" => false, "note" => "Tester Number 6", "pleroma" => %{ "background_image" => nil, diff --git a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex index 95d8452df..145b46ea1 100644 --- a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex @@ -177,7 +177,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do user_params = [ :no_rich_text, - :locked, + :is_locked, :hide_followers_count, :hide_follows_count, :hide_followers, diff --git a/lib/pleroma/web/mastodon_api/views/account_view.ex b/lib/pleroma/web/mastodon_api/views/account_view.ex index 121ba1693..f382c05a3 100644 --- a/lib/pleroma/web/mastodon_api/views/account_view.ex +++ b/lib/pleroma/web/mastodon_api/views/account_view.ex @@ -242,7 +242,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do username: username_from_nickname(user.nickname), acct: user.nickname, display_name: display_name, - locked: user.locked, + is_locked: user.is_locked, created_at: Utils.to_masto_date(user.inserted_at), followers_count: followers_count, following_count: following_count, -- cgit v1.2.3 From 8bacdc36806efd01a7897359ff0fd2c8e24730d2 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Tue, 13 Oct 2020 09:45:08 -0500 Subject: Change user.discoverable field to user.is_discoverable --- lib/pleroma/user.ex | 8 ++++---- lib/pleroma/user/search.ex | 2 +- lib/pleroma/web/activity_pub/activity_pub.ex | 4 ++-- lib/pleroma/web/activity_pub/views/user_view.ex | 2 +- lib/pleroma/web/admin_api/views/account_view.ex | 2 +- lib/pleroma/web/api_spec/operations/account_operation.ex | 4 ++-- lib/pleroma/web/api_spec/operations/chat_operation.ex | 2 +- lib/pleroma/web/api_spec/schemas/account.ex | 4 ++-- lib/pleroma/web/api_spec/schemas/chat.ex | 2 +- lib/pleroma/web/api_spec/schemas/status.ex | 2 +- lib/pleroma/web/mastodon_api/controllers/account_controller.ex | 2 +- lib/pleroma/web/mastodon_api/views/account_view.ex | 2 +- lib/pleroma/web/metadata/restrict_indexing.ex | 2 +- 13 files changed, 19 insertions(+), 19 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 09ea80793..c4640f928 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -136,7 +136,7 @@ defmodule Pleroma.User do field(:pleroma_settings_store, :map, default: %{}) field(:fields, {:array, :map}, default: []) field(:raw_fields, {:array, :map}, default: []) - field(:discoverable, :boolean, default: false) + field(:is_discoverable, :boolean, default: false) field(:invisible, :boolean, default: false) field(:allow_following_move, :boolean, default: true) field(:skip_thread_containment, :boolean, default: false) @@ -448,7 +448,7 @@ defmodule Pleroma.User do :follower_count, :fields, :following_count, - :discoverable, + :is_discoverable, :invisible, :actor_type, :also_known_as, @@ -495,7 +495,7 @@ defmodule Pleroma.User do :fields, :raw_fields, :pleroma_settings_store, - :discoverable, + :is_discoverable, :actor_type, :also_known_as, :accepts_chat_messages @@ -1618,7 +1618,7 @@ defmodule Pleroma.User do pleroma_settings_store: %{}, fields: [], raw_fields: [], - discoverable: false, + is_discoverable: false, also_known_as: [] }) end diff --git a/lib/pleroma/user/search.ex b/lib/pleroma/user/search.ex index 35a828008..2dab67211 100644 --- a/lib/pleroma/user/search.ex +++ b/lib/pleroma/user/search.ex @@ -164,7 +164,7 @@ defmodule Pleroma.User.Search do end defp filter_discoverable_users(query) do - from(q in query, where: q.discoverable == true) + from(q in query, where: q.is_discoverable == true) end defp filter_internal_users(query) do diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index eb44cffec..236fefbb6 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -1232,7 +1232,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do capabilities = data["capabilities"] || %{} accepts_chat_messages = capabilities["acceptsChatMessages"] data = Transmogrifier.maybe_fix_user_object(data) - discoverable = data["discoverable"] || false + is_discoverable = data["is_discoverable"] || false invisible = data["invisible"] || false actor_type = data["type"] || "Person" @@ -1258,7 +1258,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do fields: fields, emoji: emojis, locked: locked, - discoverable: discoverable, + is_discoverable: is_discoverable, invisible: invisible, avatar: avatar, name: data["name"], diff --git a/lib/pleroma/web/activity_pub/views/user_view.ex b/lib/pleroma/web/activity_pub/views/user_view.ex index 3a4564912..81cd7e81d 100644 --- a/lib/pleroma/web/activity_pub/views/user_view.ex +++ b/lib/pleroma/web/activity_pub/views/user_view.ex @@ -110,7 +110,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do "endpoints" => endpoints, "attachment" => fields, "tag" => emoji_tags, - "discoverable" => user.discoverable, + "is_discoverable" => user.is_discoverable, "capabilities" => capabilities } |> Map.merge(maybe_make_image(&User.avatar_url/2, "icon", user)) diff --git a/lib/pleroma/web/admin_api/views/account_view.ex b/lib/pleroma/web/admin_api/views/account_view.ex index 9c477feab..5f3a78a0f 100644 --- a/lib/pleroma/web/admin_api/views/account_view.ex +++ b/lib/pleroma/web/admin_api/views/account_view.ex @@ -52,7 +52,7 @@ defmodule Pleroma.Web.AdminAPI.AccountView do :skip_thread_containment, :pleroma_settings_store, :raw_fields, - :discoverable, + :is_discoverable, :actor_type ]) |> Map.merge(%{ diff --git a/lib/pleroma/web/api_spec/operations/account_operation.ex b/lib/pleroma/web/api_spec/operations/account_operation.ex index d90ddb787..1696b19a5 100644 --- a/lib/pleroma/web/api_spec/operations/account_operation.ex +++ b/lib/pleroma/web/api_spec/operations/account_operation.ex @@ -606,7 +606,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do description: "Sets the background image of the user.", format: :binary }, - discoverable: %Schema{ + is_discoverable: %Schema{ allOf: [BooleanLike], nullable: true, description: @@ -630,7 +630,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do pleroma_settings_store: %{"pleroma-fe" => %{"key" => "val"}}, skip_thread_containment: false, allow_following_move: false, - discoverable: false, + is_discoverable: false, actor_type: "Person" } } diff --git a/lib/pleroma/web/api_spec/operations/chat_operation.ex b/lib/pleroma/web/api_spec/operations/chat_operation.ex index 0dcfdb354..18693a5d7 100644 --- a/lib/pleroma/web/api_spec/operations/chat_operation.ex +++ b/lib/pleroma/web/api_spec/operations/chat_operation.ex @@ -253,7 +253,7 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do "sensitive" => false, "note" => "lain", "pleroma" => %{ - "discoverable" => false, + "is_discoverable" => false, "actor_type" => "Person" }, "fields" => [] diff --git a/lib/pleroma/web/api_spec/schemas/account.ex b/lib/pleroma/web/api_spec/schemas/account.ex index ca79f0747..459e7dba6 100644 --- a/lib/pleroma/web/api_spec/schemas/account.ex +++ b/lib/pleroma/web/api_spec/schemas/account.ex @@ -124,7 +124,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Account do type: :object, properties: %{ actor_type: ActorType, - discoverable: %Schema{ + is_discoverable: %Schema{ type: :boolean, description: "whether the user allows discovery of the account in search results and other services." @@ -205,7 +205,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Account do "note" => "foobar", "pleroma" => %{ "actor_type" => "Person", - "discoverable" => false, + "is_discoverable" => false, "no_rich_text" => false, "show_role" => true }, diff --git a/lib/pleroma/web/api_spec/schemas/chat.ex b/lib/pleroma/web/api_spec/schemas/chat.ex index b4986b734..da245d0de 100644 --- a/lib/pleroma/web/api_spec/schemas/chat.ex +++ b/lib/pleroma/web/api_spec/schemas/chat.ex @@ -44,7 +44,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Chat do "sensitive" => false, "note" => "lain", "pleroma" => %{ - "discoverable" => false, + "is_discoverable" => false, "actor_type" => "Person" }, "fields" => [] diff --git a/lib/pleroma/web/api_spec/schemas/status.ex b/lib/pleroma/web/api_spec/schemas/status.ex index 947e42890..52b870d63 100644 --- a/lib/pleroma/web/api_spec/schemas/status.ex +++ b/lib/pleroma/web/api_spec/schemas/status.ex @@ -284,7 +284,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Status do "source" => %{ "fields" => [], "note" => "Tester Number 6", - "pleroma" => %{"actor_type" => "Person", "discoverable" => false}, + "pleroma" => %{"actor_type" => "Person", "is_discoverable" => false}, "sensitive" => false }, "statuses_count" => 1, diff --git a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex index 95d8452df..e06ff9307 100644 --- a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex @@ -186,7 +186,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do :show_role, :skip_thread_containment, :allow_following_move, - :discoverable, + :is_discoverable, :accepts_chat_messages ] |> Enum.reduce(%{}, fn key, acc -> diff --git a/lib/pleroma/web/mastodon_api/views/account_view.ex b/lib/pleroma/web/mastodon_api/views/account_view.ex index 121ba1693..0636d9cc1 100644 --- a/lib/pleroma/web/mastodon_api/views/account_view.ex +++ b/lib/pleroma/web/mastodon_api/views/account_view.ex @@ -261,7 +261,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do sensitive: false, fields: user.raw_fields, pleroma: %{ - discoverable: user.discoverable, + is_discoverable: user.is_discoverable, actor_type: user.actor_type } }, diff --git a/lib/pleroma/web/metadata/restrict_indexing.ex b/lib/pleroma/web/metadata/restrict_indexing.ex index a1dcb6e15..900c2434d 100644 --- a/lib/pleroma/web/metadata/restrict_indexing.ex +++ b/lib/pleroma/web/metadata/restrict_indexing.ex @@ -10,7 +10,7 @@ defmodule Pleroma.Web.Metadata.Providers.RestrictIndexing do """ @impl true - def build_tags(%{user: %{local: true, discoverable: true}}), do: [] + def build_tags(%{user: %{local: true, is_discoverable: true}}), do: [] def build_tags(_) do [ -- cgit v1.2.3 From 33f4f39b1cf3a6d8ce350da194696b19ca6f3a05 Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Tue, 13 Oct 2020 21:39:41 +0400 Subject: Add pagination for Blocks --- lib/pleroma/web/api_spec/operations/account_operation.ex | 1 + .../web/mastodon_api/controllers/account_controller.ex | 12 +++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/api_spec/operations/account_operation.ex b/lib/pleroma/web/api_spec/operations/account_operation.ex index d90ddb787..9cd516f05 100644 --- a/lib/pleroma/web/api_spec/operations/account_operation.ex +++ b/lib/pleroma/web/api_spec/operations/account_operation.ex @@ -348,6 +348,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do operationId: "AccountController.blocks", description: "View your blocks. See also accounts/:id/{block,unblock}", security: [%{"oAuth" => ["read:blocks"]}], + parameters: pagination_params(), responses: %{ 200 => Operation.response("Accounts", "application/json", array_of_accounts()) } diff --git a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex index 4f9696d52..1b221e3a1 100644 --- a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex @@ -448,9 +448,15 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do end @doc "GET /api/v1/blocks" - def blocks(%{assigns: %{user: user}} = conn, _) do - users = User.blocked_users(user, _restrict_deactivated = true) - render(conn, "index.json", users: users, for: user, as: :user) + def blocks(%{assigns: %{user: user}} = conn, params) do + users = + user + |> User.blocked_users_relation(_restrict_deactivated = true) + |> Pleroma.Pagination.fetch_paginated(Map.put(params, :skip_order, true)) + + conn + |> add_link_headers(users) + |> render("index.json", users: users, for: user, as: :user) end @doc "GET /api/v1/endorsements" -- cgit v1.2.3 From 6734abcbd448b92d57ec376b796fea1fad18b792 Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Tue, 13 Oct 2020 21:58:18 +0400 Subject: Add pagination for Mutes --- lib/pleroma/web/api_spec/operations/account_operation.ex | 1 + .../web/mastodon_api/controllers/account_controller.ex | 12 +++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/api_spec/operations/account_operation.ex b/lib/pleroma/web/api_spec/operations/account_operation.ex index 9cd516f05..4934b7788 100644 --- a/lib/pleroma/web/api_spec/operations/account_operation.ex +++ b/lib/pleroma/web/api_spec/operations/account_operation.ex @@ -335,6 +335,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do operationId: "AccountController.mutes", description: "Accounts the user has muted.", security: [%{"oAuth" => ["follow", "read:mutes"]}], + parameters: pagination_params(), responses: %{ 200 => Operation.response("Accounts", "application/json", array_of_accounts()) } diff --git a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex index 1b221e3a1..c8606e5d6 100644 --- a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex @@ -442,9 +442,15 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do end @doc "GET /api/v1/mutes" - def mutes(%{assigns: %{user: user}} = conn, _) do - users = User.muted_users(user, _restrict_deactivated = true) - render(conn, "index.json", users: users, for: user, as: :user) + def mutes(%{assigns: %{user: user}} = conn, params) do + users = + user + |> User.muted_users_relation(_restrict_deactivated = true) + |> Pleroma.Pagination.fetch_paginated(Map.put(params, :skip_order, true)) + + conn + |> add_link_headers(users) + |> render("index.json", users: users, for: user, as: :user) end @doc "GET /api/v1/blocks" -- cgit v1.2.3 From 3242cfef20ea05bae53761ffaf54347c4c6f7bda Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Wed, 14 Oct 2020 09:54:07 -0500 Subject: Undo API breaking changes --- lib/pleroma/web/api_spec/operations/account_operation.ex | 4 ++-- lib/pleroma/web/api_spec/operations/chat_operation.ex | 2 +- lib/pleroma/web/api_spec/schemas/account.ex | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/api_spec/operations/account_operation.ex b/lib/pleroma/web/api_spec/operations/account_operation.ex index 1696b19a5..d90ddb787 100644 --- a/lib/pleroma/web/api_spec/operations/account_operation.ex +++ b/lib/pleroma/web/api_spec/operations/account_operation.ex @@ -606,7 +606,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do description: "Sets the background image of the user.", format: :binary }, - is_discoverable: %Schema{ + discoverable: %Schema{ allOf: [BooleanLike], nullable: true, description: @@ -630,7 +630,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do pleroma_settings_store: %{"pleroma-fe" => %{"key" => "val"}}, skip_thread_containment: false, allow_following_move: false, - is_discoverable: false, + discoverable: false, actor_type: "Person" } } diff --git a/lib/pleroma/web/api_spec/operations/chat_operation.ex b/lib/pleroma/web/api_spec/operations/chat_operation.ex index 18693a5d7..0dcfdb354 100644 --- a/lib/pleroma/web/api_spec/operations/chat_operation.ex +++ b/lib/pleroma/web/api_spec/operations/chat_operation.ex @@ -253,7 +253,7 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do "sensitive" => false, "note" => "lain", "pleroma" => %{ - "is_discoverable" => false, + "discoverable" => false, "actor_type" => "Person" }, "fields" => [] diff --git a/lib/pleroma/web/api_spec/schemas/account.ex b/lib/pleroma/web/api_spec/schemas/account.ex index 459e7dba6..ca79f0747 100644 --- a/lib/pleroma/web/api_spec/schemas/account.ex +++ b/lib/pleroma/web/api_spec/schemas/account.ex @@ -124,7 +124,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Account do type: :object, properties: %{ actor_type: ActorType, - is_discoverable: %Schema{ + discoverable: %Schema{ type: :boolean, description: "whether the user allows discovery of the account in search results and other services." @@ -205,7 +205,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Account do "note" => "foobar", "pleroma" => %{ "actor_type" => "Person", - "is_discoverable" => false, + "discoverable" => false, "no_rich_text" => false, "show_role" => true }, -- cgit v1.2.3 From b001237b79d50eef1f0636951cddc7b6da20260d Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Wed, 14 Oct 2020 10:44:18 -0500 Subject: Finish undoing API breakage --- lib/pleroma/web/activity_pub/views/user_view.ex | 2 +- lib/pleroma/web/mastodon_api/controllers/account_controller.ex | 2 +- lib/pleroma/web/mastodon_api/views/account_view.ex | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/activity_pub/views/user_view.ex b/lib/pleroma/web/activity_pub/views/user_view.ex index 81cd7e81d..e57c91149 100644 --- a/lib/pleroma/web/activity_pub/views/user_view.ex +++ b/lib/pleroma/web/activity_pub/views/user_view.ex @@ -110,7 +110,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do "endpoints" => endpoints, "attachment" => fields, "tag" => emoji_tags, - "is_discoverable" => user.is_discoverable, + "discoverable" => user.is_discoverable, "capabilities" => capabilities } |> Map.merge(maybe_make_image(&User.avatar_url/2, "icon", user)) diff --git a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex index 6453880dc..9d2f42da9 100644 --- a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex @@ -186,7 +186,6 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do :show_role, :skip_thread_containment, :allow_following_move, - :is_discoverable, :accepts_chat_messages ] |> Enum.reduce(%{}, fn key, acc -> @@ -210,6 +209,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do if bot, do: {:ok, "Service"}, else: {:ok, "Person"} end) |> Maps.put_if_present(:actor_type, params[:actor_type]) + |> Maps.put_if_present(:is_discoverable, params[:discoverable]) # What happens here: # diff --git a/lib/pleroma/web/mastodon_api/views/account_view.ex b/lib/pleroma/web/mastodon_api/views/account_view.ex index 0636d9cc1..d57537ee3 100644 --- a/lib/pleroma/web/mastodon_api/views/account_view.ex +++ b/lib/pleroma/web/mastodon_api/views/account_view.ex @@ -261,7 +261,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do sensitive: false, fields: user.raw_fields, pleroma: %{ - is_discoverable: user.is_discoverable, + discoverable: user.is_discoverable, actor_type: user.actor_type } }, -- cgit v1.2.3 From ed61002815a65962cd4eba8522f090c2998741d4 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Wed, 14 Oct 2020 11:03:17 -0500 Subject: Undo API breaking changes --- lib/pleroma/web/api_spec/operations/account_operation.ex | 2 +- lib/pleroma/web/api_spec/operations/chat_operation.ex | 2 +- lib/pleroma/web/api_spec/schemas/account.ex | 4 ++-- lib/pleroma/web/mastodon_api/controllers/account_controller.ex | 2 +- lib/pleroma/web/mastodon_api/views/account_view.ex | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/api_spec/operations/account_operation.ex b/lib/pleroma/web/api_spec/operations/account_operation.ex index 57f25e1d8..d90ddb787 100644 --- a/lib/pleroma/web/api_spec/operations/account_operation.ex +++ b/lib/pleroma/web/api_spec/operations/account_operation.ex @@ -519,7 +519,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do description: "Header image encoded using multipart/form-data", format: :binary }, - is_locked: %Schema{ + locked: %Schema{ allOf: [BooleanLike], nullable: true, description: "Whether manual approval of follow requests is required." diff --git a/lib/pleroma/web/api_spec/operations/chat_operation.ex b/lib/pleroma/web/api_spec/operations/chat_operation.ex index df786e480..0dcfdb354 100644 --- a/lib/pleroma/web/api_spec/operations/chat_operation.ex +++ b/lib/pleroma/web/api_spec/operations/chat_operation.ex @@ -259,7 +259,7 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do "fields" => [] }, "statuses_count" => 1, - "is_locked" => false, + "locked" => false, "created_at" => "2020-04-16T13:40:15.000Z", "display_name" => "lain", "fields" => [], diff --git a/lib/pleroma/web/api_spec/schemas/account.ex b/lib/pleroma/web/api_spec/schemas/account.ex index b8ddf4ab8..ca79f0747 100644 --- a/lib/pleroma/web/api_spec/schemas/account.ex +++ b/lib/pleroma/web/api_spec/schemas/account.ex @@ -32,7 +32,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Account do header_static: %Schema{type: :string, format: :uri}, header: %Schema{type: :string, format: :uri}, id: FlakeID, - is_locked: %Schema{type: :boolean}, + locked: %Schema{type: :boolean}, note: %Schema{type: :string, format: :html}, statuses_count: %Schema{type: :integer}, url: %Schema{type: :string, format: :uri}, @@ -159,7 +159,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Account do "header" => "https://mypleroma.com/images/banner.png", "header_static" => "https://mypleroma.com/images/banner.png", "id" => "9tKi3esbG7OQgZ2920", - "is_locked" => false, + "locked" => false, "note" => "cofe", "pleroma" => %{ "allow_following_move" => true, diff --git a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex index 5b3980c71..97858a93c 100644 --- a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex @@ -177,7 +177,6 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do user_params = [ :no_rich_text, - :is_locked, :hide_followers_count, :hide_follows_count, :hide_followers, @@ -210,6 +209,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do if bot, do: {:ok, "Service"}, else: {:ok, "Person"} end) |> Maps.put_if_present(:actor_type, params[:actor_type]) + |> Maps.put_if_present(:is_locked, params[:locked]) # What happens here: # diff --git a/lib/pleroma/web/mastodon_api/views/account_view.ex b/lib/pleroma/web/mastodon_api/views/account_view.ex index f382c05a3..d54cae732 100644 --- a/lib/pleroma/web/mastodon_api/views/account_view.ex +++ b/lib/pleroma/web/mastodon_api/views/account_view.ex @@ -242,7 +242,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do username: username_from_nickname(user.nickname), acct: user.nickname, display_name: display_name, - is_locked: user.is_locked, + locked: user.is_locked, created_at: Utils.to_masto_date(user.inserted_at), followers_count: followers_count, following_count: following_count, -- cgit v1.2.3 From 77bca415951be516f1b48dc6346600856c96ef5c Mon Sep 17 00:00:00 2001 From: feld Date: Wed, 14 Oct 2020 19:33:54 +0000 Subject: Apply 3 suggestion(s) to 3 file(s) --- lib/pleroma/web/activity_pub/activity_pub.ex | 2 +- lib/pleroma/web/api_spec/schemas/chat.ex | 2 +- lib/pleroma/web/api_spec/schemas/status.ex | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 236fefbb6..b04b72106 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -1232,7 +1232,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do capabilities = data["capabilities"] || %{} accepts_chat_messages = capabilities["acceptsChatMessages"] data = Transmogrifier.maybe_fix_user_object(data) - is_discoverable = data["is_discoverable"] || false + is_discoverable = data["discoverable"] || false invisible = data["invisible"] || false actor_type = data["type"] || "Person" diff --git a/lib/pleroma/web/api_spec/schemas/chat.ex b/lib/pleroma/web/api_spec/schemas/chat.ex index da245d0de..b4986b734 100644 --- a/lib/pleroma/web/api_spec/schemas/chat.ex +++ b/lib/pleroma/web/api_spec/schemas/chat.ex @@ -44,7 +44,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Chat do "sensitive" => false, "note" => "lain", "pleroma" => %{ - "is_discoverable" => false, + "discoverable" => false, "actor_type" => "Person" }, "fields" => [] diff --git a/lib/pleroma/web/api_spec/schemas/status.ex b/lib/pleroma/web/api_spec/schemas/status.ex index 52b870d63..947e42890 100644 --- a/lib/pleroma/web/api_spec/schemas/status.ex +++ b/lib/pleroma/web/api_spec/schemas/status.ex @@ -284,7 +284,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Status do "source" => %{ "fields" => [], "note" => "Tester Number 6", - "pleroma" => %{"actor_type" => "Person", "is_discoverable" => false}, + "pleroma" => %{"actor_type" => "Person", "discoverable" => false}, "sensitive" => false }, "statuses_count" => 1, -- cgit v1.2.3 From 7a2f100061913ec59db9957893eb92bb2d150dc4 Mon Sep 17 00:00:00 2001 From: lain Date: Thu, 15 Oct 2020 12:28:25 +0200 Subject: ActivityPub: Show own replies to muted users. Aligns mute with block behavior. --- lib/pleroma/web/activity_pub/activity_pub.ex | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 8022f0402..ff7b9e778 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -827,7 +827,14 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do query = from([activity] in query, where: fragment("not (? = ANY(?))", activity.actor, ^mutes), - where: fragment("not (?->'to' \\?| ?)", activity.data, ^mutes) + where: + fragment( + "not (?->'to' \\?| ?) or ? = ?", + activity.data, + ^mutes, + activity.actor, + ^user.ap_id + ) ) unless opts[:skip_preload] do -- cgit v1.2.3 From 3985c1b4501010b72b94072951f2ff64c0fd6310 Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Thu, 15 Oct 2020 16:54:59 +0400 Subject: Fix warnings --- lib/pleroma/web/templates/layout/app.html.eex | 2 +- lib/pleroma/web/templates/layout/email_styled.html.eex | 2 +- lib/pleroma/web/templates/layout/metadata_player.html.eex | 2 +- lib/pleroma/web/templates/layout/static_fe.html.eex | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/templates/layout/app.html.eex b/lib/pleroma/web/templates/layout/app.html.eex index 51603fe0c..3f28f1920 100644 --- a/lib/pleroma/web/templates/layout/app.html.eex +++ b/lib/pleroma/web/templates/layout/app.html.eex @@ -228,7 +228,7 @@

<%= Pleroma.Config.get([:instance, :name]) %>

- <%= render @view_module, @view_template, assigns %> + <%= @inner_content %>
diff --git a/lib/pleroma/web/templates/layout/email_styled.html.eex b/lib/pleroma/web/templates/layout/email_styled.html.eex index ca2caaf4d..82cabd889 100644 --- a/lib/pleroma/web/templates/layout/email_styled.html.eex +++ b/lib/pleroma/web/templates/layout/email_styled.html.eex @@ -181,7 +181,7 @@ <% end %> - <%= render @view_module, @view_template, assigns %> + <%= @inner_content %> diff --git a/lib/pleroma/web/templates/layout/metadata_player.html.eex b/lib/pleroma/web/templates/layout/metadata_player.html.eex index 460f28094..c00f6fa21 100644 --- a/lib/pleroma/web/templates/layout/metadata_player.html.eex +++ b/lib/pleroma/web/templates/layout/metadata_player.html.eex @@ -10,7 +10,7 @@ video, audio { } -<%= render @view_module, @view_template, assigns %> +<%= @inner_content %> diff --git a/lib/pleroma/web/templates/layout/static_fe.html.eex b/lib/pleroma/web/templates/layout/static_fe.html.eex index dc0ee2a5c..e6adb526b 100644 --- a/lib/pleroma/web/templates/layout/static_fe.html.eex +++ b/lib/pleroma/web/templates/layout/static_fe.html.eex @@ -9,7 +9,7 @@
- <%= render @view_module, @view_template, assigns %> + <%= @inner_content %>
-- cgit v1.2.3 From 20e68b30f08e0e0eae691dcf541968e344efdaae Mon Sep 17 00:00:00 2001 From: Maksim Pechnikov Date: Tue, 14 Jul 2020 07:31:21 +0300 Subject: added generated `pleroma.env` --- lib/mix/tasks/pleroma/release_env.ex | 64 ++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 lib/mix/tasks/pleroma/release_env.ex (limited to 'lib') diff --git a/lib/mix/tasks/pleroma/release_env.ex b/lib/mix/tasks/pleroma/release_env.ex new file mode 100644 index 000000000..cbbbdeff6 --- /dev/null +++ b/lib/mix/tasks/pleroma/release_env.ex @@ -0,0 +1,64 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Mix.Tasks.Pleroma.ReleaseEnv do + use Mix.Task + import Mix.Pleroma + + @shortdoc "Generate Pleroma environment file." + @moduledoc File.read!("docs/administration/CLI_tasks/release_environments.md") + + def run(["gen" | rest]) do + {options, [], []} = + OptionParser.parse( + rest, + strict: [ + force: :boolean, + path: :string + ], + aliases: [ + p: :path, + f: :force + ] + ) + + env_path = + get_option( + options, + :path, + "Environment file path", + "config/pleroma.env" + ) + |> Path.expand() + + proceed? = + if File.exists?(env_path) do + get_option( + options, + :force, + "Environment file is exist. Do you want overwritten the #{env_path} file? (y/n)", + "n" + ) === "y" + else + true + end + + if proceed? do + do_generate(env_path) + + shell_info( + "The file generated: #{env_path}.\nTo use the enviroment file need to add the line ';EnvironmentFile=#{ + env_path + }' in service file (/installation/pleroma.service)." + ) + end + end + + def do_generate(path) do + content = "RELEASE_COOKIE=#{Base.encode32(:crypto.strong_rand_bytes(32))}" + + File.mkdir_p!(Path.dirname(path)) + File.write!(path, content) + end +end -- cgit v1.2.3 From 14054cd004d91e89644c31d61b08d50ff0df09dd Mon Sep 17 00:00:00 2001 From: Maksim Pechnikov Date: Thu, 16 Jul 2020 08:52:14 +0300 Subject: update task messages --- lib/mix/tasks/pleroma/release_env.ex | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) (limited to 'lib') diff --git a/lib/mix/tasks/pleroma/release_env.ex b/lib/mix/tasks/pleroma/release_env.ex index cbbbdeff6..63030c5cc 100644 --- a/lib/mix/tasks/pleroma/release_env.ex +++ b/lib/mix/tasks/pleroma/release_env.ex @@ -23,14 +23,15 @@ defmodule Mix.Tasks.Pleroma.ReleaseEnv do ] ) - env_path = + file_path = get_option( options, :path, "Environment file path", - "config/pleroma.env" + "./config/pleroma.env" ) - |> Path.expand() + + env_path = Path.expand(file_path) proceed? = if File.exists?(env_path) do @@ -45,13 +46,24 @@ defmodule Mix.Tasks.Pleroma.ReleaseEnv do end if proceed? do - do_generate(env_path) + case do_generate(env_path) do + {:error, reason} -> + shell_error( + File.Error.message(%{action: "write to file", reason: reason, path: env_path}) + ) - shell_info( - "The file generated: #{env_path}.\nTo use the enviroment file need to add the line ';EnvironmentFile=#{ - env_path - }' in service file (/installation/pleroma.service)." - ) + _ -> + shell_info("\nThe file generated: #{env_path}.\n") + + shell_info(""" + WARNING: before start pleroma app please to made the file read-only and non-modifiable. + Example: + chmod 0444 #{file_path} + chattr +i #{file_path} + """) + end + else + shell_info("\nThe file is exist. #{env_path}.\n") end end @@ -59,6 +71,6 @@ defmodule Mix.Tasks.Pleroma.ReleaseEnv do content = "RELEASE_COOKIE=#{Base.encode32(:crypto.strong_rand_bytes(32))}" File.mkdir_p!(Path.dirname(path)) - File.write!(path, content) + File.write(path, content) end end -- cgit v1.2.3 From 499df7b73aa723aab9c623754b531307b98cf584 Mon Sep 17 00:00:00 2001 From: Maksim Date: Thu, 16 Jul 2020 13:30:17 +0000 Subject: Apply 1 suggestion(s) to 1 file(s) --- lib/mix/tasks/pleroma/release_env.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/mix/tasks/pleroma/release_env.ex b/lib/mix/tasks/pleroma/release_env.ex index 63030c5cc..4d8b6ff27 100644 --- a/lib/mix/tasks/pleroma/release_env.ex +++ b/lib/mix/tasks/pleroma/release_env.ex @@ -56,7 +56,7 @@ defmodule Mix.Tasks.Pleroma.ReleaseEnv do shell_info("\nThe file generated: #{env_path}.\n") shell_info(""" - WARNING: before start pleroma app please to made the file read-only and non-modifiable. + WARNING: before start pleroma app please make sure to make the file read-only and non-modifiable. Example: chmod 0444 #{file_path} chattr +i #{file_path} -- cgit v1.2.3 From e2333f757a763f7ec7105df6b4de4585fc3eee05 Mon Sep 17 00:00:00 2001 From: Maksim Date: Thu, 16 Jul 2020 13:30:28 +0000 Subject: Apply 1 suggestion(s) to 1 file(s) --- lib/mix/tasks/pleroma/release_env.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/mix/tasks/pleroma/release_env.ex b/lib/mix/tasks/pleroma/release_env.ex index 4d8b6ff27..9da74ffcf 100644 --- a/lib/mix/tasks/pleroma/release_env.ex +++ b/lib/mix/tasks/pleroma/release_env.ex @@ -38,7 +38,7 @@ defmodule Mix.Tasks.Pleroma.ReleaseEnv do get_option( options, :force, - "Environment file is exist. Do you want overwritten the #{env_path} file? (y/n)", + "Environment file already exists. Do you want to overwrite the #{env_path} file? (y/n)", "n" ) === "y" else -- cgit v1.2.3 From cf53e300f8e850aeacb88e6e6b4d465378acc199 Mon Sep 17 00:00:00 2001 From: Maksim Pechnikov Date: Fri, 7 Aug 2020 15:55:08 +0300 Subject: added generate the release env to `pleroma.instance gen` --- lib/mix/tasks/pleroma/instance.ex | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/mix/tasks/pleroma/instance.ex b/lib/mix/tasks/pleroma/instance.ex index fc21ae062..caa7dfbd3 100644 --- a/lib/mix/tasks/pleroma/instance.ex +++ b/lib/mix/tasks/pleroma/instance.ex @@ -36,7 +36,8 @@ defmodule Mix.Tasks.Pleroma.Instance do listen_port: :string, strip_uploads: :string, anonymize_uploads: :string, - dedupe_uploads: :string + dedupe_uploads: :string, + skip_release_env: :boolean ], aliases: [ o: :output, @@ -241,6 +242,16 @@ defmodule Mix.Tasks.Pleroma.Instance do write_robots_txt(static_dir, indexable, template_dir) + if Keyword.get(options, :skip_release_env, false) do + shell_info(""" + Release environment file is skip. Please generate the release env file before start. + `MIX_ENV=#{Mix.env()} mix pleroma.release_env gen` + """) + else + shell_info("Generation the environment file:") + Mix.Tasks.Pleroma.ReleaseEnv.run(["gen"]) + end + shell_info( "\n All files successfully written! Refer to the installation instructions for your platform for next steps." ) -- cgit v1.2.3 From 2030ffd4904b6ab5e99cefa62887154a49aaf4db Mon Sep 17 00:00:00 2001 From: Maksim Pechnikov Date: Sat, 8 Aug 2020 06:49:19 +0300 Subject: fix test --- lib/mix/tasks/pleroma/instance.ex | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/mix/tasks/pleroma/instance.ex b/lib/mix/tasks/pleroma/instance.ex index caa7dfbd3..1915aacd9 100644 --- a/lib/mix/tasks/pleroma/instance.ex +++ b/lib/mix/tasks/pleroma/instance.ex @@ -37,7 +37,8 @@ defmodule Mix.Tasks.Pleroma.Instance do strip_uploads: :string, anonymize_uploads: :string, dedupe_uploads: :string, - skip_release_env: :boolean + skip_release_env: :boolean, + release_env_file: :string ], aliases: [ o: :output, @@ -249,7 +250,15 @@ defmodule Mix.Tasks.Pleroma.Instance do """) else shell_info("Generation the environment file:") - Mix.Tasks.Pleroma.ReleaseEnv.run(["gen"]) + + release_env_args = + with path when not is_nil(path) <- Keyword.get(options, :release_env_file) do + ["gen", "--path", path] + else + _ -> ["gen"] + end + + Mix.Tasks.Pleroma.ReleaseEnv.run(release_env_args) end shell_info( -- cgit v1.2.3 From 724e4b7f00041667b9fa61fd1b7dd51c8eeaa102 Mon Sep 17 00:00:00 2001 From: Haelwenn Date: Thu, 15 Oct 2020 21:03:48 +0000 Subject: Apply 1 suggestion(s) to 1 file(s) --- lib/pleroma/web/admin_api/views/account_view.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/web/admin_api/views/account_view.ex b/lib/pleroma/web/admin_api/views/account_view.ex index 5f3a78a0f..9c477feab 100644 --- a/lib/pleroma/web/admin_api/views/account_view.ex +++ b/lib/pleroma/web/admin_api/views/account_view.ex @@ -52,7 +52,7 @@ defmodule Pleroma.Web.AdminAPI.AccountView do :skip_thread_containment, :pleroma_settings_store, :raw_fields, - :is_discoverable, + :discoverable, :actor_type ]) |> Map.merge(%{ -- cgit v1.2.3 From 1b8fd7e65af980c42b72f584c2a957b12ca5c78b Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Fri, 16 Oct 2020 17:32:05 +0000 Subject: Adds feature to permit e.g., local admins and community moderators to automatically follow all newly registered accounts --- lib/pleroma/user.ex | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'lib') diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index dc41d0001..2a3495103 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -765,6 +765,16 @@ defmodule Pleroma.User do follow_all(user, autofollowed_users) end + defp autofollowing_users(user) do + candidates = Config.get([:instance, :autofollowing_nicknames]) + + User.Query.build(%{nickname: candidates, local: true, deactivated: false}) + |> Repo.all() + |> Enum.each(&follow(&1, user, :follow_accept)) + + {:ok, :success} + end + @doc "Inserts provided changeset, performs post-registration actions (confirmation email sending etc.)" def register(%Ecto.Changeset{} = changeset) do with {:ok, user} <- Repo.insert(changeset) do @@ -774,6 +784,7 @@ defmodule Pleroma.User do def post_register_action(%User{} = user) do with {:ok, user} <- autofollow_users(user), + {:ok, _} <- autofollowing_users(user), {:ok, user} <- set_cache(user), {:ok, _} <- send_welcome_email(user), {:ok, _} <- send_welcome_message(user), -- cgit v1.2.3 From d54233760f4c006d89aa80e0ae78cb6910fc74ab Mon Sep 17 00:00:00 2001 From: Ivan Tashkinov Date: Sat, 17 Oct 2020 13:33:57 +0300 Subject: [#3053] Post-merge fix. --- lib/pleroma/web/feed/user_controller.ex | 1 + 1 file changed, 1 insertion(+) (limited to 'lib') diff --git a/lib/pleroma/web/feed/user_controller.ex b/lib/pleroma/web/feed/user_controller.ex index b66fdf275..a5013d2c0 100644 --- a/lib/pleroma/web/feed/user_controller.ex +++ b/lib/pleroma/web/feed/user_controller.ex @@ -5,6 +5,7 @@ defmodule Pleroma.Web.Feed.UserController do use Pleroma.Web, :controller + alias Pleroma.Config alias Pleroma.User alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.ActivityPubController -- cgit v1.2.3 From 524fb0e4c2561f4a2e4c8e58519df991f034c901 Mon Sep 17 00:00:00 2001 From: Ivan Tashkinov Date: Sun, 18 Oct 2020 21:22:21 +0300 Subject: [#1668] Restricted access to app metrics endpoint by default. Added ability to configure IP whitelist for this endpoint. Added tests and documentation. --- lib/pleroma/helpers/inet_helper.ex | 19 ++++++++++++++++++ lib/pleroma/web/endpoint.ex | 40 ++++++++++++++++++++++++++++++++------ 2 files changed, 53 insertions(+), 6 deletions(-) create mode 100644 lib/pleroma/helpers/inet_helper.ex (limited to 'lib') diff --git a/lib/pleroma/helpers/inet_helper.ex b/lib/pleroma/helpers/inet_helper.ex new file mode 100644 index 000000000..126f82381 --- /dev/null +++ b/lib/pleroma/helpers/inet_helper.ex @@ -0,0 +1,19 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Helpers.InetHelper do + def parse_address(ip) when is_tuple(ip) do + {:ok, ip} + end + + def parse_address(ip) when is_binary(ip) do + ip + |> String.to_charlist() + |> parse_address() + end + + def parse_address(ip) do + :inet.parse_address(ip) + end +end diff --git a/lib/pleroma/web/endpoint.ex b/lib/pleroma/web/endpoint.ex index 56562c12f..1a8fdd8b9 100644 --- a/lib/pleroma/web/endpoint.ex +++ b/lib/pleroma/web/endpoint.ex @@ -7,6 +7,8 @@ defmodule Pleroma.Web.Endpoint do require Pleroma.Constants + alias Pleroma.Config + socket("/socket", Pleroma.Web.UserSocket) plug(Pleroma.Web.Plugs.SetLocalePlug) @@ -86,19 +88,19 @@ defmodule Pleroma.Web.Endpoint do plug(Plug.Parsers, parsers: [ :urlencoded, - {:multipart, length: {Pleroma.Config, :get, [[:instance, :upload_limit]]}}, + {:multipart, length: {Config, :get, [[:instance, :upload_limit]]}}, :json ], pass: ["*/*"], json_decoder: Jason, - length: Pleroma.Config.get([:instance, :upload_limit]), + length: Config.get([:instance, :upload_limit]), body_reader: {Pleroma.Web.Plugs.DigestPlug, :read_body, []} ) plug(Plug.MethodOverride) plug(Plug.Head) - secure_cookies = Pleroma.Config.get([__MODULE__, :secure_cookie_flag]) + secure_cookies = Config.get([__MODULE__, :secure_cookie_flag]) cookie_name = if secure_cookies, @@ -106,7 +108,7 @@ defmodule Pleroma.Web.Endpoint do else: "pleroma_key" extra = - Pleroma.Config.get([__MODULE__, :extra_cookie_attrs]) + Config.get([__MODULE__, :extra_cookie_attrs]) |> Enum.join(";") # The session will be stored in the cookie and signed, @@ -116,7 +118,7 @@ defmodule Pleroma.Web.Endpoint do Plug.Session, store: :cookie, key: cookie_name, - signing_salt: Pleroma.Config.get([__MODULE__, :signing_salt], "CqaoopA2"), + signing_salt: Config.get([__MODULE__, :signing_salt], "CqaoopA2"), http_only: true, secure: secure_cookies, extra: extra @@ -136,8 +138,34 @@ defmodule Pleroma.Web.Endpoint do use Prometheus.PlugExporter end + defmodule MetricsExporterCaller do + @behaviour Plug + + def init(opts), do: opts + + def call(conn, opts) do + prometheus_config = Application.get_env(:prometheus, MetricsExporter, []) + ip_whitelist = List.wrap(prometheus_config[:ip_whitelist]) + + cond do + !prometheus_config[:enabled] -> + conn + + ip_whitelist != [] and + !Enum.find(ip_whitelist, fn ip -> + Pleroma.Helpers.InetHelper.parse_address(ip) == {:ok, conn.remote_ip} + end) -> + conn + + true -> + MetricsExporter.call(conn, opts) + end + end + end + plug(PipelineInstrumenter) - plug(MetricsExporter) + + plug(MetricsExporterCaller) plug(Pleroma.Web.Router) -- cgit v1.2.3 From 98f32cf8204113c6d019653c22e446e558147248 Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Mon, 19 Oct 2020 15:30:32 +0400 Subject: Fix tests --- lib/pleroma/web/pleroma_api/controllers/backup_controller.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/web/pleroma_api/controllers/backup_controller.ex b/lib/pleroma/web/pleroma_api/controllers/backup_controller.ex index e52c77ff2..8e3d081f3 100644 --- a/lib/pleroma/web/pleroma_api/controllers/backup_controller.ex +++ b/lib/pleroma/web/pleroma_api/controllers/backup_controller.ex @@ -5,7 +5,7 @@ defmodule Pleroma.Web.PleromaAPI.BackupController do use Pleroma.Web, :controller - alias Pleroma.Plugs.OAuthScopesPlug + alias Pleroma.Web.Plugs.OAuthScopesPlug action_fallback(Pleroma.Web.MastodonAPI.FallbackController) plug(OAuthScopesPlug, %{scopes: ["read:accounts"]} when action in [:index, :create]) -- cgit v1.2.3 From 39fd4d7639a0ab47bc5ae3839b10701fc301a1be Mon Sep 17 00:00:00 2001 From: lain Date: Mon, 19 Oct 2020 15:40:50 +0200 Subject: Transmogrifier: Downcase incoming Hashtags Also, set sensitive to true if we have an nsfw hashtag present. --- lib/pleroma/web/activity_pub/transmogrifier.ex | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index d7dd9fe6b..2f51f9e39 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -40,6 +40,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do |> fix_in_reply_to(options) |> fix_emoji |> fix_tag + |> set_sensitive |> fix_content_map |> fix_addressing |> fix_summary @@ -313,7 +314,11 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do tags = tag |> Enum.filter(fn data -> data["type"] == "Hashtag" and data["name"] end) - |> Enum.map(fn data -> String.slice(data["name"], 1..-1) end) + |> Enum.map(fn %{"name" => name} -> + name + |> String.slice(1..-1) + |> String.downcase() + end) Map.put(object, "tag", tag ++ tags) end @@ -927,7 +932,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do Map.put(object, "conversation", object["context"]) end - def set_sensitive(%{"sensitive" => true} = object) do + def set_sensitive(%{"sensitive" => _} = object) do object end -- cgit v1.2.3 From e97b254c6bb798d200f381e5adbde2177bcbc0df Mon Sep 17 00:00:00 2001 From: lain Date: Mon, 19 Oct 2020 15:46:24 +0200 Subject: Transmogrifier: Refactor and unify incoming tag handling --- lib/pleroma/web/activity_pub/transmogrifier.ex | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 2f51f9e39..39c8f7e39 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -323,14 +323,12 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do Map.put(object, "tag", tag ++ tags) end - def fix_tag(%{"tag" => %{"type" => "Hashtag", "name" => hashtag} = tag} = object) do - combined = [tag, String.slice(hashtag, 1..-1)] - - Map.put(object, "tag", combined) + def fix_tag(%{"tag" => %{} = tag} = object) do + object + |> Map.put("tag", [tag]) + |> fix_tag end - def fix_tag(%{"tag" => %{} = tag} = object), do: Map.put(object, "tag", [tag]) - def fix_tag(object), do: object # content map usually only has one language so this will do for now. -- cgit v1.2.3 From ad605e3e16ba3f6ee3df7a0a3e6705036fef369f Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Tue, 20 Oct 2020 17:16:58 +0400 Subject: Rename `Pleroma.Backup` to `Pleroma.User.Backup` --- lib/pleroma/backup.ex | 258 --------------------- lib/pleroma/user/backup.ex | 258 +++++++++++++++++++++ .../admin_api/controllers/admin_api_controller.ex | 2 +- .../pleroma_api/controllers/backup_controller.ex | 7 +- lib/pleroma/web/pleroma_api/views/backup_view.ex | 2 +- lib/pleroma/workers/backup_worker.ex | 4 +- 6 files changed, 266 insertions(+), 265 deletions(-) delete mode 100644 lib/pleroma/backup.ex create mode 100644 lib/pleroma/user/backup.ex (limited to 'lib') diff --git a/lib/pleroma/backup.ex b/lib/pleroma/backup.ex deleted file mode 100644 index 629e879a7..000000000 --- a/lib/pleroma/backup.ex +++ /dev/null @@ -1,258 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2020 Pleroma Authors -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Backup do - use Ecto.Schema - - import Ecto.Changeset - import Ecto.Query - import Pleroma.Web.Gettext - - require Pleroma.Constants - - alias Pleroma.Activity - alias Pleroma.Bookmark - alias Pleroma.Repo - alias Pleroma.User - alias Pleroma.Web.ActivityPub.ActivityPub - alias Pleroma.Web.ActivityPub.Transmogrifier - alias Pleroma.Web.ActivityPub.UserView - alias Pleroma.Workers.BackupWorker - - schema "backups" do - field(:content_type, :string) - field(:file_name, :string) - field(:file_size, :integer, default: 0) - field(:processed, :boolean, default: false) - - belongs_to(:user, User, type: FlakeId.Ecto.CompatType) - - timestamps() - end - - def create(user, admin_id \\ nil) do - with :ok <- validate_email_enabled(), - :ok <- validate_user_email(user), - :ok <- validate_limit(user, admin_id), - {:ok, backup} <- user |> new() |> Repo.insert() do - BackupWorker.process(backup, admin_id) - end - end - - def new(user) do - rand_str = :crypto.strong_rand_bytes(32) |> Base.url_encode64(padding: false) - datetime = Calendar.NaiveDateTime.Format.iso8601_basic(NaiveDateTime.utc_now()) - name = "archive-#{user.nickname}-#{datetime}-#{rand_str}.zip" - - %__MODULE__{ - user_id: user.id, - content_type: "application/zip", - file_name: name - } - end - - def delete(backup) do - uploader = Pleroma.Config.get([Pleroma.Upload, :uploader]) - - with :ok <- uploader.delete_file(Path.join("backups", backup.file_name)) do - Repo.delete(backup) - end - end - - defp validate_limit(_user, admin_id) when is_binary(admin_id), do: :ok - - defp validate_limit(user, nil) do - case get_last(user.id) do - %__MODULE__{inserted_at: inserted_at} -> - days = Pleroma.Config.get([Pleroma.Backup, :limit_days]) - diff = Timex.diff(NaiveDateTime.utc_now(), inserted_at, :days) - - if diff > days do - :ok - else - {:error, - dngettext( - "errors", - "Last export was less than a day ago", - "Last export was less than %{days} days ago", - days, - days: days - )} - end - - nil -> - :ok - end - end - - defp validate_email_enabled do - if Pleroma.Config.get([Pleroma.Emails.Mailer, :enabled]) do - :ok - else - {:error, dgettext("errors", "Backups require enabled email")} - end - end - - defp validate_user_email(%User{email: nil}) do - {:error, dgettext("errors", "Email is required")} - end - - defp validate_user_email(%User{email: email}) when is_binary(email), do: :ok - - def get_last(user_id) do - __MODULE__ - |> where(user_id: ^user_id) - |> order_by(desc: :id) - |> limit(1) - |> Repo.one() - end - - def list(%User{id: user_id}) do - __MODULE__ - |> where(user_id: ^user_id) - |> order_by(desc: :id) - |> Repo.all() - end - - def remove_outdated(%__MODULE__{id: latest_id, user_id: user_id}) do - __MODULE__ - |> where(user_id: ^user_id) - |> where([b], b.id != ^latest_id) - |> Repo.all() - |> Enum.each(&BackupWorker.delete/1) - end - - def get(id), do: Repo.get(__MODULE__, id) - - def process(%__MODULE__{} = backup) do - with {:ok, zip_file} <- export(backup), - {:ok, %{size: size}} <- File.stat(zip_file), - {:ok, _upload} <- upload(backup, zip_file) do - backup - |> cast(%{file_size: size, processed: true}, [:file_size, :processed]) - |> Repo.update() - end - end - - @files ['actor.json', 'outbox.json', 'likes.json', 'bookmarks.json'] - def export(%__MODULE__{} = backup) do - backup = Repo.preload(backup, :user) - name = String.trim_trailing(backup.file_name, ".zip") - dir = dir(name) - - with :ok <- File.mkdir(dir), - :ok <- actor(dir, backup.user), - :ok <- statuses(dir, backup.user), - :ok <- likes(dir, backup.user), - :ok <- bookmarks(dir, backup.user), - {:ok, zip_path} <- :zip.create(String.to_charlist(dir <> ".zip"), @files, cwd: dir), - {:ok, _} <- File.rm_rf(dir) do - {:ok, to_string(zip_path)} - end - end - - def dir(name) do - dir = Pleroma.Config.get([__MODULE__, :dir]) || System.tmp_dir!() - Path.join(dir, name) - end - - def upload(%__MODULE__{} = backup, zip_path) do - uploader = Pleroma.Config.get([Pleroma.Upload, :uploader]) - - upload = %Pleroma.Upload{ - name: backup.file_name, - tempfile: zip_path, - content_type: backup.content_type, - path: Path.join("backups", backup.file_name) - } - - with {:ok, _} <- Pleroma.Uploaders.Uploader.put_file(uploader, upload), - :ok <- File.rm(zip_path) do - {:ok, upload} - end - end - - defp actor(dir, user) do - with {:ok, json} <- - UserView.render("user.json", %{user: user}) - |> Map.merge(%{"likes" => "likes.json", "bookmarks" => "bookmarks.json"}) - |> Jason.encode() do - File.write(Path.join(dir, "actor.json"), json) - end - end - - defp write_header(file, name) do - IO.write( - file, - """ - { - "@context": "https://www.w3.org/ns/activitystreams", - "id": "#{name}.json", - "type": "OrderedCollection", - "orderedItems": [ - - """ - ) - end - - defp write(query, dir, name, fun) do - path = Path.join(dir, "#{name}.json") - - with {:ok, file} <- File.open(path, [:write, :utf8]), - :ok <- write_header(file, name) do - total = - query - |> Pleroma.Repo.chunk_stream(100) - |> Enum.reduce(0, fn i, acc -> - with {:ok, data} <- fun.(i), - {:ok, str} <- Jason.encode(data), - :ok <- IO.write(file, str <> ",\n") do - acc + 1 - else - _ -> acc - end - end) - - with :ok <- :file.pwrite(file, {:eof, -2}, "\n],\n \"totalItems\": #{total}}") do - File.close(file) - end - end - end - - defp bookmarks(dir, %{id: user_id} = _user) do - Bookmark - |> where(user_id: ^user_id) - |> join(:inner, [b], activity in assoc(b, :activity)) - |> select([b, a], %{id: b.id, object: fragment("(?)->>'object'", a.data)}) - |> write(dir, "bookmarks", fn a -> {:ok, a.object} end) - end - - defp likes(dir, user) do - user.ap_id - |> Activity.Queries.by_actor() - |> Activity.Queries.by_type("Like") - |> select([like], %{id: like.id, object: fragment("(?)->>'object'", like.data)}) - |> write(dir, "likes", fn a -> {:ok, a.object} end) - end - - defp statuses(dir, user) do - opts = - %{} - |> Map.put(:type, ["Create", "Announce"]) - |> Map.put(:actor_id, user.ap_id) - - [ - [Pleroma.Constants.as_public(), user.ap_id], - User.following(user), - Pleroma.List.memberships(user) - ] - |> Enum.concat() - |> ActivityPub.fetch_activities_query(opts) - |> write(dir, "outbox", fn a -> - with {:ok, activity} <- Transmogrifier.prepare_outgoing(a.data) do - {:ok, Map.delete(activity, "@context")} - end - end) - end -end diff --git a/lib/pleroma/user/backup.ex b/lib/pleroma/user/backup.ex new file mode 100644 index 000000000..a9041fd94 --- /dev/null +++ b/lib/pleroma/user/backup.ex @@ -0,0 +1,258 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.User.Backup do + use Ecto.Schema + + import Ecto.Changeset + import Ecto.Query + import Pleroma.Web.Gettext + + require Pleroma.Constants + + alias Pleroma.Activity + alias Pleroma.Bookmark + alias Pleroma.Repo + alias Pleroma.User + alias Pleroma.Web.ActivityPub.ActivityPub + alias Pleroma.Web.ActivityPub.Transmogrifier + alias Pleroma.Web.ActivityPub.UserView + alias Pleroma.Workers.BackupWorker + + schema "backups" do + field(:content_type, :string) + field(:file_name, :string) + field(:file_size, :integer, default: 0) + field(:processed, :boolean, default: false) + + belongs_to(:user, User, type: FlakeId.Ecto.CompatType) + + timestamps() + end + + def create(user, admin_id \\ nil) do + with :ok <- validate_email_enabled(), + :ok <- validate_user_email(user), + :ok <- validate_limit(user, admin_id), + {:ok, backup} <- user |> new() |> Repo.insert() do + BackupWorker.process(backup, admin_id) + end + end + + def new(user) do + rand_str = :crypto.strong_rand_bytes(32) |> Base.url_encode64(padding: false) + datetime = Calendar.NaiveDateTime.Format.iso8601_basic(NaiveDateTime.utc_now()) + name = "archive-#{user.nickname}-#{datetime}-#{rand_str}.zip" + + %__MODULE__{ + user_id: user.id, + content_type: "application/zip", + file_name: name + } + end + + def delete(backup) do + uploader = Pleroma.Config.get([Pleroma.Upload, :uploader]) + + with :ok <- uploader.delete_file(Path.join("backups", backup.file_name)) do + Repo.delete(backup) + end + end + + defp validate_limit(_user, admin_id) when is_binary(admin_id), do: :ok + + defp validate_limit(user, nil) do + case get_last(user.id) do + %__MODULE__{inserted_at: inserted_at} -> + days = Pleroma.Config.get([__MODULE__, :limit_days]) + diff = Timex.diff(NaiveDateTime.utc_now(), inserted_at, :days) + + if diff > days do + :ok + else + {:error, + dngettext( + "errors", + "Last export was less than a day ago", + "Last export was less than %{days} days ago", + days, + days: days + )} + end + + nil -> + :ok + end + end + + defp validate_email_enabled do + if Pleroma.Config.get([Pleroma.Emails.Mailer, :enabled]) do + :ok + else + {:error, dgettext("errors", "Backups require enabled email")} + end + end + + defp validate_user_email(%User{email: nil}) do + {:error, dgettext("errors", "Email is required")} + end + + defp validate_user_email(%User{email: email}) when is_binary(email), do: :ok + + def get_last(user_id) do + __MODULE__ + |> where(user_id: ^user_id) + |> order_by(desc: :id) + |> limit(1) + |> Repo.one() + end + + def list(%User{id: user_id}) do + __MODULE__ + |> where(user_id: ^user_id) + |> order_by(desc: :id) + |> Repo.all() + end + + def remove_outdated(%__MODULE__{id: latest_id, user_id: user_id}) do + __MODULE__ + |> where(user_id: ^user_id) + |> where([b], b.id != ^latest_id) + |> Repo.all() + |> Enum.each(&BackupWorker.delete/1) + end + + def get(id), do: Repo.get(__MODULE__, id) + + def process(%__MODULE__{} = backup) do + with {:ok, zip_file} <- export(backup), + {:ok, %{size: size}} <- File.stat(zip_file), + {:ok, _upload} <- upload(backup, zip_file) do + backup + |> cast(%{file_size: size, processed: true}, [:file_size, :processed]) + |> Repo.update() + end + end + + @files ['actor.json', 'outbox.json', 'likes.json', 'bookmarks.json'] + def export(%__MODULE__{} = backup) do + backup = Repo.preload(backup, :user) + name = String.trim_trailing(backup.file_name, ".zip") + dir = dir(name) + + with :ok <- File.mkdir(dir), + :ok <- actor(dir, backup.user), + :ok <- statuses(dir, backup.user), + :ok <- likes(dir, backup.user), + :ok <- bookmarks(dir, backup.user), + {:ok, zip_path} <- :zip.create(String.to_charlist(dir <> ".zip"), @files, cwd: dir), + {:ok, _} <- File.rm_rf(dir) do + {:ok, to_string(zip_path)} + end + end + + def dir(name) do + dir = Pleroma.Config.get([__MODULE__, :dir]) || System.tmp_dir!() + Path.join(dir, name) + end + + def upload(%__MODULE__{} = backup, zip_path) do + uploader = Pleroma.Config.get([Pleroma.Upload, :uploader]) + + upload = %Pleroma.Upload{ + name: backup.file_name, + tempfile: zip_path, + content_type: backup.content_type, + path: Path.join("backups", backup.file_name) + } + + with {:ok, _} <- Pleroma.Uploaders.Uploader.put_file(uploader, upload), + :ok <- File.rm(zip_path) do + {:ok, upload} + end + end + + defp actor(dir, user) do + with {:ok, json} <- + UserView.render("user.json", %{user: user}) + |> Map.merge(%{"likes" => "likes.json", "bookmarks" => "bookmarks.json"}) + |> Jason.encode() do + File.write(Path.join(dir, "actor.json"), json) + end + end + + defp write_header(file, name) do + IO.write( + file, + """ + { + "@context": "https://www.w3.org/ns/activitystreams", + "id": "#{name}.json", + "type": "OrderedCollection", + "orderedItems": [ + + """ + ) + end + + defp write(query, dir, name, fun) do + path = Path.join(dir, "#{name}.json") + + with {:ok, file} <- File.open(path, [:write, :utf8]), + :ok <- write_header(file, name) do + total = + query + |> Pleroma.Repo.chunk_stream(100) + |> Enum.reduce(0, fn i, acc -> + with {:ok, data} <- fun.(i), + {:ok, str} <- Jason.encode(data), + :ok <- IO.write(file, str <> ",\n") do + acc + 1 + else + _ -> acc + end + end) + + with :ok <- :file.pwrite(file, {:eof, -2}, "\n],\n \"totalItems\": #{total}}") do + File.close(file) + end + end + end + + defp bookmarks(dir, %{id: user_id} = _user) do + Bookmark + |> where(user_id: ^user_id) + |> join(:inner, [b], activity in assoc(b, :activity)) + |> select([b, a], %{id: b.id, object: fragment("(?)->>'object'", a.data)}) + |> write(dir, "bookmarks", fn a -> {:ok, a.object} end) + end + + defp likes(dir, user) do + user.ap_id + |> Activity.Queries.by_actor() + |> Activity.Queries.by_type("Like") + |> select([like], %{id: like.id, object: fragment("(?)->>'object'", like.data)}) + |> write(dir, "likes", fn a -> {:ok, a.object} end) + end + + defp statuses(dir, user) do + opts = + %{} + |> Map.put(:type, ["Create", "Announce"]) + |> Map.put(:actor_id, user.ap_id) + + [ + [Pleroma.Constants.as_public(), user.ap_id], + User.following(user), + Pleroma.List.memberships(user) + ] + |> Enum.concat() + |> ActivityPub.fetch_activities_query(opts) + |> write(dir, "outbox", fn a -> + with {:ok, activity} <- Transmogrifier.prepare_outgoing(a.data) do + {:ok, Map.delete(activity, "@context")} + end + end) + end +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 a4f0d7d34..0a27c5861 100644 --- a/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex +++ b/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex @@ -685,7 +685,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do def create_backup(%{assigns: %{user: admin}} = conn, %{"nickname" => nickname}) do with %User{} = user <- User.get_by_nickname(nickname), - {:ok, _} <- Pleroma.Backup.create(user, admin.id) do + {:ok, _} <- Pleroma.User.Backup.create(user, admin.id) do ModerationLog.insert_log(%{actor: admin, subject: user, action: "create_backup"}) json(conn, "") diff --git a/lib/pleroma/web/pleroma_api/controllers/backup_controller.ex b/lib/pleroma/web/pleroma_api/controllers/backup_controller.ex index 8e3d081f3..bd7b36880 100644 --- a/lib/pleroma/web/pleroma_api/controllers/backup_controller.ex +++ b/lib/pleroma/web/pleroma_api/controllers/backup_controller.ex @@ -6,6 +6,7 @@ defmodule Pleroma.Web.PleromaAPI.BackupController do use Pleroma.Web, :controller alias Pleroma.Web.Plugs.OAuthScopesPlug + alias Pleroma.User.Backup action_fallback(Pleroma.Web.MastodonAPI.FallbackController) plug(OAuthScopesPlug, %{scopes: ["read:accounts"]} when action in [:index, :create]) @@ -14,13 +15,13 @@ defmodule Pleroma.Web.PleromaAPI.BackupController do defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.PleromaBackupOperation def index(%{assigns: %{user: user}} = conn, _params) do - backups = Pleroma.Backup.list(user) + backups = Backup.list(user) render(conn, "index.json", backups: backups) end def create(%{assigns: %{user: user}} = conn, _params) do - with {:ok, _} <- Pleroma.Backup.create(user) do - backups = Pleroma.Backup.list(user) + with {:ok, _} <- Backup.create(user) do + backups = Backup.list(user) render(conn, "index.json", backups: backups) end end diff --git a/lib/pleroma/web/pleroma_api/views/backup_view.ex b/lib/pleroma/web/pleroma_api/views/backup_view.ex index bf40a001e..af75876aa 100644 --- a/lib/pleroma/web/pleroma_api/views/backup_view.ex +++ b/lib/pleroma/web/pleroma_api/views/backup_view.ex @@ -5,7 +5,7 @@ defmodule Pleroma.Web.PleromaAPI.BackupView do use Pleroma.Web, :view - alias Pleroma.Backup + alias Pleroma.User.Backup alias Pleroma.Web.CommonAPI.Utils def render("show.json", %{backup: %Backup{} = backup}) do diff --git a/lib/pleroma/workers/backup_worker.ex b/lib/pleroma/workers/backup_worker.ex index 65754b6a2..5b4985983 100644 --- a/lib/pleroma/workers/backup_worker.ex +++ b/lib/pleroma/workers/backup_worker.ex @@ -6,7 +6,7 @@ defmodule Pleroma.Workers.BackupWorker do use Oban.Worker, queue: :backup, max_attempts: 1 alias Oban.Job - alias Pleroma.Backup + alias Pleroma.User.Backup def process(backup, admin_user_id \\ nil) do %{"op" => "process", "backup_id" => backup.id, "admin_user_id" => admin_user_id} @@ -15,7 +15,7 @@ defmodule Pleroma.Workers.BackupWorker do end def schedule_deletion(backup) do - days = Pleroma.Config.get([Pleroma.Backup, :purge_after_days]) + days = Pleroma.Config.get([Backup, :purge_after_days]) time = 60 * 60 * 24 * days scheduled_at = Calendar.NaiveDateTime.add!(backup.inserted_at, time) -- cgit v1.2.3 From 034ac43f3a91178694d3c621c52ce68207ec4f69 Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Tue, 20 Oct 2020 17:47:04 +0400 Subject: Fix credo warnings --- lib/pleroma/web/pleroma_api/controllers/backup_controller.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/web/pleroma_api/controllers/backup_controller.ex b/lib/pleroma/web/pleroma_api/controllers/backup_controller.ex index bd7b36880..dd0a2e22f 100644 --- a/lib/pleroma/web/pleroma_api/controllers/backup_controller.ex +++ b/lib/pleroma/web/pleroma_api/controllers/backup_controller.ex @@ -5,8 +5,8 @@ defmodule Pleroma.Web.PleromaAPI.BackupController do use Pleroma.Web, :controller - alias Pleroma.Web.Plugs.OAuthScopesPlug alias Pleroma.User.Backup + alias Pleroma.Web.Plugs.OAuthScopesPlug action_fallback(Pleroma.Web.MastodonAPI.FallbackController) plug(OAuthScopesPlug, %{scopes: ["read:accounts"]} when action in [:index, :create]) -- cgit v1.2.3 From 9ef46ce4103f338d5bb75278013a63d3ae418d7e Mon Sep 17 00:00:00 2001 From: Maksim Pechnikov Date: Mon, 21 Sep 2020 09:33:51 +0300 Subject: added 'unconfirmed' filter to admin/users --- lib/pleroma/user/query.ex | 5 ++ .../admin_api/controllers/admin_api_controller.ex | 55 ++++++++-------------- 2 files changed, 25 insertions(+), 35 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/user/query.ex b/lib/pleroma/user/query.ex index 2440bf890..2933e7fb4 100644 --- a/lib/pleroma/user/query.ex +++ b/lib/pleroma/user/query.ex @@ -43,6 +43,7 @@ defmodule Pleroma.User.Query do active: boolean(), deactivated: boolean(), need_approval: boolean(), + need_confirmed: boolean(), is_admin: boolean(), is_moderator: boolean(), super_users: boolean(), @@ -156,6 +157,10 @@ defmodule Pleroma.User.Query do where(query, [u], u.approval_pending) end + defp compose_query({:need_confirmed, _}, query) do + where(query, [u], u.confirmation_pending) + end + defp compose_query({:followers, %User{id: id}}, query) do query |> where([u], u.id != ^id) 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 bdd3e195d..acfbeb0c8 100644 --- a/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex +++ b/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex @@ -5,7 +5,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do use Pleroma.Web, :controller - import Pleroma.Web.ControllerHelper, only: [json_response: 3] + import Pleroma.Web.ControllerHelper, + only: [json_response: 3, fetch_integer_param: 3] alias Pleroma.Config alias Pleroma.MFA @@ -100,12 +101,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do end def user_delete(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do - users = - nicknames - |> Enum.map(&User.get_cached_by_nickname/1) + users = Enum.map(nicknames, &User.get_cached_by_nickname/1) - users - |> Enum.each(fn user -> + Enum.each(users, fn user -> {:ok, delete_data, _} = Builder.delete(admin, user.ap_id) Pipeline.common_pipeline(delete_data, local: true) end) @@ -367,16 +365,18 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do {page, page_size} = page_params(params) filters = maybe_parse_filters(params["filters"]) - search_params = %{ - query: params["query"], - page: page, - page_size: page_size, - tags: params["tags"], - name: params["name"], - email: params["email"] - } + search_params = + %{ + query: params["query"], + page: page, + page_size: page_size, + tags: params["tags"], + name: params["name"], + email: params["email"] + } + |> Map.merge(filters) - with {:ok, users, count} <- Search.user(Map.merge(search_params, filters)) do + with {:ok, users, count} <- Search.user(search_params) do json( conn, AccountView.render("index.json", @@ -388,7 +388,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do end end - @filters ~w(local external active deactivated need_approval is_admin is_moderator) + @filters ~w(local external active deactivated need_approval need_confirmed is_admin is_moderator) @spec maybe_parse_filters(String.t()) :: %{required(String.t()) => true} | %{} defp maybe_parse_filters(filters) when is_nil(filters) or filters == "", do: %{} @@ -682,24 +682,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do end defp page_params(params) do - {get_page(params["page"]), get_page_size(params["page_size"])} - end - - defp get_page(page_string) when is_nil(page_string), do: 1 - - defp get_page(page_string) do - case Integer.parse(page_string) do - {page, _} -> page - :error -> 1 - end - end - - defp get_page_size(page_size_string) when is_nil(page_size_string), do: @users_page_size - - defp get_page_size(page_size_string) do - case Integer.parse(page_size_string) do - {page_size, _} -> page_size - :error -> @users_page_size - end + { + fetch_integer_param(params, "page", 1), + fetch_integer_param(params, "page_size", @users_page_size) + } end end -- cgit v1.2.3 From cf4f3937946eb0232be8bf8ddba08d365b4e17ee Mon Sep 17 00:00:00 2001 From: Maksim Pechnikov Date: Mon, 21 Sep 2020 15:01:03 +0300 Subject: added AdminApi.UserController --- .../admin_api/controllers/admin_api_controller.ex | 242 +----------------- .../web/admin_api/controllers/user_controller.ex | 280 +++++++++++++++++++++ lib/pleroma/web/router.ex | 22 +- 3 files changed, 292 insertions(+), 252 deletions(-) create mode 100644 lib/pleroma/web/admin_api/controllers/user_controller.ex (limited to 'lib') 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 acfbeb0c8..df5817cfa 100644 --- a/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex +++ b/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex @@ -14,12 +14,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do alias Pleroma.Stats alias Pleroma.User alias Pleroma.Web.ActivityPub.ActivityPub - alias Pleroma.Web.ActivityPub.Builder - alias Pleroma.Web.ActivityPub.Pipeline alias Pleroma.Web.AdminAPI alias Pleroma.Web.AdminAPI.AccountView alias Pleroma.Web.AdminAPI.ModerationLogView - alias Pleroma.Web.AdminAPI.Search alias Pleroma.Web.Endpoint alias Pleroma.Web.Plugs.OAuthScopesPlug alias Pleroma.Web.Router @@ -29,7 +26,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do plug( OAuthScopesPlug, %{scopes: ["read:accounts"], admin: true} - when action in [:list_users, :user_show, :right_get, :show_user_credentials] + when action in [:right_get, :show_user_credentials] ) plug( @@ -38,12 +35,6 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do when action in [ :get_password_reset, :force_password_reset, - :user_delete, - :users_create, - :user_toggle_activation, - :user_activate, - :user_deactivate, - :user_approve, :tag_users, :untag_users, :right_add, @@ -55,12 +46,6 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do ] ) - plug( - OAuthScopesPlug, - %{scopes: ["write:follows"], admin: true} - when action in [:user_follow, :user_unfollow] - ) - plug( OAuthScopesPlug, %{scopes: ["read:statuses"], admin: true} @@ -96,129 +81,6 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do action_fallback(AdminAPI.FallbackController) - def user_delete(conn, %{"nickname" => nickname}) do - user_delete(conn, %{"nicknames" => [nickname]}) - end - - def user_delete(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do - users = Enum.map(nicknames, &User.get_cached_by_nickname/1) - - Enum.each(users, fn user -> - {:ok, delete_data, _} = Builder.delete(admin, user.ap_id) - Pipeline.common_pipeline(delete_data, local: true) - end) - - ModerationLog.insert_log(%{ - actor: admin, - subject: users, - action: "delete" - }) - - json(conn, nicknames) - end - - def user_follow(%{assigns: %{user: admin}} = conn, %{ - "follower" => follower_nick, - "followed" => followed_nick - }) do - with %User{} = follower <- User.get_cached_by_nickname(follower_nick), - %User{} = followed <- User.get_cached_by_nickname(followed_nick) do - User.follow(follower, followed) - - ModerationLog.insert_log(%{ - actor: admin, - followed: followed, - follower: follower, - action: "follow" - }) - end - - json(conn, "ok") - end - - def user_unfollow(%{assigns: %{user: admin}} = conn, %{ - "follower" => follower_nick, - "followed" => followed_nick - }) do - with %User{} = follower <- User.get_cached_by_nickname(follower_nick), - %User{} = followed <- User.get_cached_by_nickname(followed_nick) do - User.unfollow(follower, followed) - - ModerationLog.insert_log(%{ - actor: admin, - followed: followed, - follower: follower, - action: "unfollow" - }) - end - - json(conn, "ok") - end - - def users_create(%{assigns: %{user: admin}} = conn, %{"users" => users}) do - changesets = - Enum.map(users, fn %{"nickname" => nickname, "email" => email, "password" => password} -> - user_data = %{ - nickname: nickname, - name: nickname, - email: email, - password: password, - password_confirmation: password, - bio: "." - } - - User.register_changeset(%User{}, user_data, need_confirmation: false) - end) - |> Enum.reduce(Ecto.Multi.new(), fn changeset, multi -> - Ecto.Multi.insert(multi, Ecto.UUID.generate(), changeset) - end) - - case Pleroma.Repo.transaction(changesets) do - {:ok, users} -> - res = - users - |> Map.values() - |> Enum.map(fn user -> - {:ok, user} = User.post_register_action(user) - - user - end) - |> Enum.map(&AccountView.render("created.json", %{user: &1})) - - ModerationLog.insert_log(%{ - actor: admin, - subjects: Map.values(users), - action: "create" - }) - - json(conn, res) - - {:error, id, changeset, _} -> - res = - Enum.map(changesets.operations, fn - {current_id, {:changeset, _current_changeset, _}} when current_id == id -> - AccountView.render("create-error.json", %{changeset: changeset}) - - {_, {:changeset, current_changeset, _}} -> - AccountView.render("create-error.json", %{changeset: current_changeset}) - end) - - conn - |> put_status(:conflict) - |> json(res) - end - end - - def user_show(%{assigns: %{user: admin}} = conn, %{"nickname" => nickname}) do - with %User{} = user <- User.get_cached_by_nickname_or_id(nickname, for: admin) do - conn - |> put_view(AccountView) - |> render("show.json", %{user: user}) - else - _ -> {:error, :not_found} - end - end - 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) @@ -272,69 +134,6 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do end end - def user_toggle_activation(%{assigns: %{user: admin}} = conn, %{"nickname" => nickname}) do - user = User.get_cached_by_nickname(nickname) - - {:ok, updated_user} = User.deactivate(user, !user.deactivated) - - action = if user.deactivated, do: "activate", else: "deactivate" - - ModerationLog.insert_log(%{ - actor: admin, - subject: [user], - action: action - }) - - conn - |> put_view(AccountView) - |> render("show.json", %{user: updated_user}) - end - - def user_activate(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do - users = Enum.map(nicknames, &User.get_cached_by_nickname/1) - {:ok, updated_users} = User.deactivate(users, false) - - ModerationLog.insert_log(%{ - actor: admin, - subject: users, - action: "activate" - }) - - conn - |> put_view(AccountView) - |> render("index.json", %{users: Keyword.values(updated_users)}) - end - - def user_deactivate(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do - users = Enum.map(nicknames, &User.get_cached_by_nickname/1) - {:ok, updated_users} = User.deactivate(users, true) - - ModerationLog.insert_log(%{ - actor: admin, - subject: users, - action: "deactivate" - }) - - conn - |> put_view(AccountView) - |> render("index.json", %{users: Keyword.values(updated_users)}) - end - - def user_approve(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do - users = Enum.map(nicknames, &User.get_cached_by_nickname/1) - {:ok, updated_users} = User.approve(users) - - ModerationLog.insert_log(%{ - actor: admin, - subject: users, - action: "approve" - }) - - conn - |> put_view(AccountView) - |> render("index.json", %{users: updated_users}) - end - def tag_users(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames, "tags" => tags}) do with {:ok, _} <- User.tag(nicknames, tags) do ModerationLog.insert_log(%{ @@ -361,45 +160,6 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do end end - def list_users(conn, params) do - {page, page_size} = page_params(params) - filters = maybe_parse_filters(params["filters"]) - - search_params = - %{ - query: params["query"], - page: page, - page_size: page_size, - tags: params["tags"], - name: params["name"], - email: params["email"] - } - |> Map.merge(filters) - - with {:ok, users, count} <- Search.user(search_params) do - json( - conn, - AccountView.render("index.json", - users: users, - count: count, - page_size: page_size - ) - ) - end - end - - @filters ~w(local external active deactivated need_approval need_confirmed is_admin is_moderator) - - @spec maybe_parse_filters(String.t()) :: %{required(String.t()) => true} | %{} - defp maybe_parse_filters(filters) when is_nil(filters) or filters == "", do: %{} - - defp maybe_parse_filters(filters) do - filters - |> String.split(",") - |> Enum.filter(&Enum.member?(@filters, &1)) - |> Map.new(&{String.to_existing_atom(&1), true}) - end - def right_add_multiple(%{assigns: %{user: admin}} = conn, %{ "permission_group" => permission_group, "nicknames" => nicknames diff --git a/lib/pleroma/web/admin_api/controllers/user_controller.ex b/lib/pleroma/web/admin_api/controllers/user_controller.ex new file mode 100644 index 000000000..5e049aa0f --- /dev/null +++ b/lib/pleroma/web/admin_api/controllers/user_controller.ex @@ -0,0 +1,280 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.AdminAPI.UserController do + use Pleroma.Web, :controller + + import Pleroma.Web.ControllerHelper, + only: [fetch_integer_param: 3] + + alias Pleroma.ModerationLog + alias Pleroma.Plugs.OAuthScopesPlug + alias Pleroma.User + alias Pleroma.Web.ActivityPub.Builder + alias Pleroma.Web.ActivityPub.Pipeline + alias Pleroma.Web.AdminAPI + alias Pleroma.Web.AdminAPI.AccountView + alias Pleroma.Web.AdminAPI.Search + + @users_page_size 50 + + plug( + OAuthScopesPlug, + %{scopes: ["read:accounts"], admin: true} + when action in [:list, :show] + ) + + plug( + OAuthScopesPlug, + %{scopes: ["write:accounts"], admin: true} + when action in [ + :delete, + :create, + :toggle_activation, + :activate, + :deactivate, + :approve + ] + ) + + plug( + OAuthScopesPlug, + %{scopes: ["write:follows"], admin: true} + when action in [:follow, :unfollow] + ) + + action_fallback(AdminAPI.FallbackController) + + def delete(conn, %{"nickname" => nickname}) do + delete(conn, %{"nicknames" => [nickname]}) + end + + def delete(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do + users = Enum.map(nicknames, &User.get_cached_by_nickname/1) + + Enum.each(users, fn user -> + {:ok, delete_data, _} = Builder.delete(admin, user.ap_id) + Pipeline.common_pipeline(delete_data, local: true) + end) + + ModerationLog.insert_log(%{ + actor: admin, + subject: users, + action: "delete" + }) + + json(conn, nicknames) + end + + def follow(%{assigns: %{user: admin}} = conn, %{ + "follower" => follower_nick, + "followed" => followed_nick + }) do + with %User{} = follower <- User.get_cached_by_nickname(follower_nick), + %User{} = followed <- User.get_cached_by_nickname(followed_nick) do + User.follow(follower, followed) + + ModerationLog.insert_log(%{ + actor: admin, + followed: followed, + follower: follower, + action: "follow" + }) + end + + json(conn, "ok") + end + + def unfollow(%{assigns: %{user: admin}} = conn, %{ + "follower" => follower_nick, + "followed" => followed_nick + }) do + with %User{} = follower <- User.get_cached_by_nickname(follower_nick), + %User{} = followed <- User.get_cached_by_nickname(followed_nick) do + User.unfollow(follower, followed) + + ModerationLog.insert_log(%{ + actor: admin, + followed: followed, + follower: follower, + action: "unfollow" + }) + end + + json(conn, "ok") + end + + def create(%{assigns: %{user: admin}} = conn, %{"users" => users}) do + changesets = + Enum.map(users, fn %{"nickname" => nickname, "email" => email, "password" => password} -> + user_data = %{ + nickname: nickname, + name: nickname, + email: email, + password: password, + password_confirmation: password, + bio: "." + } + + User.register_changeset(%User{}, user_data, need_confirmation: false) + end) + |> Enum.reduce(Ecto.Multi.new(), fn changeset, multi -> + Ecto.Multi.insert(multi, Ecto.UUID.generate(), changeset) + end) + + case Pleroma.Repo.transaction(changesets) do + {:ok, users} -> + res = + users + |> Map.values() + |> Enum.map(fn user -> + {:ok, user} = User.post_register_action(user) + + user + end) + |> Enum.map(&AccountView.render("created.json", %{user: &1})) + + ModerationLog.insert_log(%{ + actor: admin, + subjects: Map.values(users), + action: "create" + }) + + json(conn, res) + + {:error, id, changeset, _} -> + res = + Enum.map(changesets.operations, fn + {current_id, {:changeset, _current_changeset, _}} when current_id == id -> + AccountView.render("create-error.json", %{changeset: changeset}) + + {_, {:changeset, current_changeset, _}} -> + AccountView.render("create-error.json", %{changeset: current_changeset}) + end) + + conn + |> put_status(:conflict) + |> json(res) + end + end + + def show(%{assigns: %{user: admin}} = conn, %{"nickname" => nickname}) do + with %User{} = user <- User.get_cached_by_nickname_or_id(nickname, for: admin) do + conn + |> put_view(AccountView) + |> render("show.json", %{user: user}) + else + _ -> {:error, :not_found} + end + end + + def toggle_activation(%{assigns: %{user: admin}} = conn, %{"nickname" => nickname}) do + user = User.get_cached_by_nickname(nickname) + + {:ok, updated_user} = User.deactivate(user, !user.deactivated) + + action = if user.deactivated, do: "activate", else: "deactivate" + + ModerationLog.insert_log(%{ + actor: admin, + subject: [user], + action: action + }) + + conn + |> put_view(AccountView) + |> render("show.json", %{user: updated_user}) + end + + def activate(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do + users = Enum.map(nicknames, &User.get_cached_by_nickname/1) + {:ok, updated_users} = User.deactivate(users, false) + + ModerationLog.insert_log(%{ + actor: admin, + subject: users, + action: "activate" + }) + + conn + |> put_view(AccountView) + |> render("index.json", %{users: Keyword.values(updated_users)}) + end + + def deactivate(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do + users = Enum.map(nicknames, &User.get_cached_by_nickname/1) + {:ok, updated_users} = User.deactivate(users, true) + + ModerationLog.insert_log(%{ + actor: admin, + subject: users, + action: "deactivate" + }) + + conn + |> put_view(AccountView) + |> render("index.json", %{users: Keyword.values(updated_users)}) + end + + def approve(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do + users = Enum.map(nicknames, &User.get_cached_by_nickname/1) + {:ok, updated_users} = User.approve(users) + + ModerationLog.insert_log(%{ + actor: admin, + subject: users, + action: "approve" + }) + + conn + |> put_view(AccountView) + |> render("index.json", %{users: updated_users}) + end + + def list(conn, params) do + {page, page_size} = page_params(params) + filters = maybe_parse_filters(params["filters"]) + + search_params = + %{ + query: params["query"], + page: page, + page_size: page_size, + tags: params["tags"], + name: params["name"], + email: params["email"] + } + |> Map.merge(filters) + + with {:ok, users, count} <- Search.user(search_params) do + json( + conn, + AccountView.render("index.json", + users: users, + count: count, + page_size: page_size + ) + ) + end + end + + @filters ~w(local external active deactivated need_approval need_confirmed is_admin is_moderator) + + @spec maybe_parse_filters(String.t()) :: %{required(String.t()) => true} | %{} + defp maybe_parse_filters(filters) when is_nil(filters) or filters == "", do: %{} + + defp maybe_parse_filters(filters) do + filters + |> String.split(",") + |> Enum.filter(&Enum.member?(@filters, &1)) + |> Map.new(&{String.to_existing_atom(&1), true}) + end + + defp page_params(params) do + { + fetch_integer_param(params, "page", 1), + fetch_integer_param(params, "page_size", @users_page_size) + } + end +end diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index d2d939989..3a9605778 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -129,16 +129,7 @@ defmodule Pleroma.Web.Router do scope "/api/pleroma/admin", Pleroma.Web.AdminAPI do pipe_through(:admin_api) - post("/users/follow", AdminAPIController, :user_follow) - post("/users/unfollow", AdminAPIController, :user_unfollow) - put("/users/disable_mfa", AdminAPIController, :disable_mfa) - delete("/users", AdminAPIController, :user_delete) - post("/users", AdminAPIController, :users_create) - patch("/users/:nickname/toggle_activation", AdminAPIController, :user_toggle_activation) - patch("/users/activate", AdminAPIController, :user_activate) - patch("/users/deactivate", AdminAPIController, :user_deactivate) - patch("/users/approve", AdminAPIController, :user_approve) put("/users/tag", AdminAPIController, :tag_users) delete("/users/tag", AdminAPIController, :untag_users) @@ -161,6 +152,15 @@ defmodule Pleroma.Web.Router do :right_delete_multiple ) + post("/users/follow", UserController, :follow) + post("/users/unfollow", UserController, :unfollow) + delete("/users", UserController, :delete) + post("/users", UserController, :create) + patch("/users/:nickname/toggle_activation", UserController, :toggle_activation) + patch("/users/activate", UserController, :activate) + patch("/users/deactivate", UserController, :deactivate) + patch("/users/approve", UserController, :approve) + get("/relay", RelayController, :index) post("/relay", RelayController, :follow) delete("/relay", RelayController, :unfollow) @@ -175,8 +175,8 @@ defmodule Pleroma.Web.Router do get("/users/:nickname/credentials", AdminAPIController, :show_user_credentials) patch("/users/:nickname/credentials", AdminAPIController, :update_user_credentials) - get("/users", AdminAPIController, :list_users) - get("/users/:nickname", AdminAPIController, :user_show) + get("/users", UserController, :list) + get("/users/:nickname", UserController, :show) get("/users/:nickname/statuses", AdminAPIController, :list_user_statuses) get("/users/:nickname/chats", AdminAPIController, :list_user_chats) -- cgit v1.2.3 From 46b420aa602050d7b3bff33a6b51d54852b2adb3 Mon Sep 17 00:00:00 2001 From: Maksim Pechnikov Date: Fri, 25 Sep 2020 09:39:49 +0300 Subject: need_confirmed -> unconfirmed --- lib/pleroma/user/query.ex | 4 ++-- lib/pleroma/web/admin_api/controllers/user_controller.ex | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/user/query.ex b/lib/pleroma/user/query.ex index 2933e7fb4..711439eef 100644 --- a/lib/pleroma/user/query.ex +++ b/lib/pleroma/user/query.ex @@ -43,7 +43,7 @@ defmodule Pleroma.User.Query do active: boolean(), deactivated: boolean(), need_approval: boolean(), - need_confirmed: boolean(), + unconfirmed: boolean(), is_admin: boolean(), is_moderator: boolean(), super_users: boolean(), @@ -157,7 +157,7 @@ defmodule Pleroma.User.Query do where(query, [u], u.approval_pending) end - defp compose_query({:need_confirmed, _}, query) do + defp compose_query({:unconfirmed, _}, query) do where(query, [u], u.confirmation_pending) end diff --git a/lib/pleroma/web/admin_api/controllers/user_controller.ex b/lib/pleroma/web/admin_api/controllers/user_controller.ex index 5e049aa0f..db6ef3220 100644 --- a/lib/pleroma/web/admin_api/controllers/user_controller.ex +++ b/lib/pleroma/web/admin_api/controllers/user_controller.ex @@ -259,7 +259,7 @@ defmodule Pleroma.Web.AdminAPI.UserController do end end - @filters ~w(local external active deactivated need_approval need_confirmed is_admin is_moderator) + @filters ~w(local external active deactivated need_approval unconfirmed is_admin is_moderator) @spec maybe_parse_filters(String.t()) :: %{required(String.t()) => true} | %{} defp maybe_parse_filters(filters) when is_nil(filters) or filters == "", do: %{} -- cgit v1.2.3 From 60663150b5b936c831bdc0cfeade30867e536317 Mon Sep 17 00:00:00 2001 From: Maksim Pechnikov Date: Fri, 25 Sep 2020 16:04:01 +0300 Subject: admin user search: added filter by `actor_type` --- lib/pleroma/user/query.ex | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/user/query.ex b/lib/pleroma/user/query.ex index 711439eef..7ef2a1455 100644 --- a/lib/pleroma/user/query.ex +++ b/lib/pleroma/user/query.ex @@ -56,7 +56,8 @@ defmodule Pleroma.User.Query do ap_id: [String.t()], order_by: term(), select: term(), - limit: pos_integer() + limit: pos_integer(), + actor_types: [String.t()] } | map() @@ -115,6 +116,10 @@ defmodule Pleroma.User.Query do where(query, [u], u.is_admin == ^bool) end + defp compose_query({:actor_types, actor_types}, query) when is_list(actor_types) do + where(query, [u], u.actor_type in ^actor_types) + end + defp compose_query({:is_moderator, bool}, query) do where(query, [u], u.is_moderator == ^bool) end -- cgit v1.2.3 From 44e5a57d1a1b36ad2971763f3a8cab82bdb94b08 Mon Sep 17 00:00:00 2001 From: Maksim Pechnikov Date: Fri, 25 Sep 2020 16:37:55 +0300 Subject: admin api: added user filters by `actor_types` --- lib/pleroma/web/admin_api/controllers/user_controller.ex | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/web/admin_api/controllers/user_controller.ex b/lib/pleroma/web/admin_api/controllers/user_controller.ex index db6ef3220..15cec9b09 100644 --- a/lib/pleroma/web/admin_api/controllers/user_controller.ex +++ b/lib/pleroma/web/admin_api/controllers/user_controller.ex @@ -243,7 +243,8 @@ defmodule Pleroma.Web.AdminAPI.UserController do page_size: page_size, tags: params["tags"], name: params["name"], - email: params["email"] + email: params["email"], + actor_types: params["actor_types"] } |> Map.merge(filters) -- cgit v1.2.3 From ef627b9391e0dde8adf03c0132fbc2eeac6bdede Mon Sep 17 00:00:00 2001 From: Maksim Pechnikov Date: Thu, 22 Oct 2020 12:04:23 +0300 Subject: fix module name --- lib/pleroma/web/admin_api/controllers/user_controller.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/web/admin_api/controllers/user_controller.ex b/lib/pleroma/web/admin_api/controllers/user_controller.ex index 15cec9b09..a2a1c875d 100644 --- a/lib/pleroma/web/admin_api/controllers/user_controller.ex +++ b/lib/pleroma/web/admin_api/controllers/user_controller.ex @@ -9,13 +9,13 @@ defmodule Pleroma.Web.AdminAPI.UserController do only: [fetch_integer_param: 3] alias Pleroma.ModerationLog - alias Pleroma.Plugs.OAuthScopesPlug alias Pleroma.User alias Pleroma.Web.ActivityPub.Builder alias Pleroma.Web.ActivityPub.Pipeline alias Pleroma.Web.AdminAPI alias Pleroma.Web.AdminAPI.AccountView alias Pleroma.Web.AdminAPI.Search + alias Pleroma.Web.Plugs.OAuthScopesPlug @users_page_size 50 -- cgit v1.2.3 From 8d251096fe71d289cf6a50f3d5638fb43b07c24a Mon Sep 17 00:00:00 2001 From: lain Date: Thu, 22 Oct 2020 12:22:08 +0200 Subject: SideEffects: Correctly handle chat messages sent to yourself --- lib/pleroma/web/activity_pub/side_effects.ex | 1 + 1 file changed, 1 insertion(+) (limited to 'lib') diff --git a/lib/pleroma/web/activity_pub/side_effects.ex b/lib/pleroma/web/activity_pub/side_effects.ex index d421ca7af..0fff5faf2 100644 --- a/lib/pleroma/web/activity_pub/side_effects.ex +++ b/lib/pleroma/web/activity_pub/side_effects.ex @@ -306,6 +306,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do streamables = [[actor, recipient], [recipient, actor]] + |> Enum.uniq() |> Enum.map(fn [user, other_user] -> if user.local do {:ok, chat} = Chat.bump_or_create(user.id, other_user.ap_id) -- cgit v1.2.3 From 8a55de1d785178786b9ae7c185ea1d1f187f7470 Mon Sep 17 00:00:00 2001 From: Ivan Tashkinov Date: Thu, 22 Oct 2020 13:54:15 +0300 Subject: [#3059] Fixed Phoenix 1.5 telemetry processing. --- lib/pleroma/application.ex | 5 ++++- lib/pleroma/web/endpoint.ex | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/application.ex b/lib/pleroma/application.ex index d7e3a649f..51e9dda3b 100644 --- a/lib/pleroma/application.ex +++ b/lib/pleroma/application.ex @@ -151,7 +151,10 @@ defmodule Pleroma.Application do Pleroma.Web.Endpoint.MetricsExporter.setup() Pleroma.Web.Endpoint.PipelineInstrumenter.setup() - Pleroma.Web.Endpoint.Instrumenter.setup() + + # Note: disabled until prometheus-phx is integrated into prometheus-phoenix: + # Pleroma.Web.Endpoint.Instrumenter.setup() + PrometheusPhx.setup() end defp cachex_children do diff --git a/lib/pleroma/web/endpoint.ex b/lib/pleroma/web/endpoint.ex index 56562c12f..f15aab8cb 100644 --- a/lib/pleroma/web/endpoint.ex +++ b/lib/pleroma/web/endpoint.ex @@ -9,6 +9,8 @@ defmodule Pleroma.Web.Endpoint do socket("/socket", Pleroma.Web.UserSocket) + plug Plug.Telemetry, event_prefix: [:phoenix, :endpoint] + plug(Pleroma.Web.Plugs.SetLocalePlug) plug(CORSPlug) plug(Pleroma.Web.Plugs.HTTPSecurityPlug) -- cgit v1.2.3 From 8a68673eeda5bcf314051ef83d5a402cf280a52b Mon Sep 17 00:00:00 2001 From: Ivan Tashkinov Date: Thu, 22 Oct 2020 14:07:33 +0300 Subject: [#3059] Formatting fix. --- lib/pleroma/web/endpoint.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/web/endpoint.ex b/lib/pleroma/web/endpoint.ex index f15aab8cb..d0e01f3d9 100644 --- a/lib/pleroma/web/endpoint.ex +++ b/lib/pleroma/web/endpoint.ex @@ -9,7 +9,7 @@ defmodule Pleroma.Web.Endpoint do socket("/socket", Pleroma.Web.UserSocket) - plug Plug.Telemetry, event_prefix: [:phoenix, :endpoint] + plug(Plug.Telemetry, event_prefix: [:phoenix, :endpoint]) plug(Pleroma.Web.Plugs.SetLocalePlug) plug(CORSPlug) -- cgit v1.2.3 From 60e379ce0b74bbe1b0f40a954aec040beab20e4e Mon Sep 17 00:00:00 2001 From: lain Date: Fri, 23 Oct 2020 13:53:01 +0200 Subject: User: Correctly handle whitespace names. --- lib/pleroma/user.ex | 5 +++-- lib/pleroma/web/activity_pub/activity_pub.ex | 4 ---- 2 files changed, 3 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index dc41d0001..72f507f1e 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -426,7 +426,6 @@ defmodule Pleroma.User do params, [ :bio, - :name, :emoji, :ap_id, :inbox, @@ -455,7 +454,9 @@ defmodule Pleroma.User do :accepts_chat_messages ] ) - |> validate_required([:name, :ap_id]) + |> cast(params, [:name], empty_values: []) + |> validate_required([:ap_id]) + |> validate_required([:name], trim: false) |> unique_constraint(:nickname) |> validate_format(:nickname, @email_regex) |> validate_length(:bio, max: bio_limit) diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index d17c892a7..df18db603 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -1378,10 +1378,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do {:ok, data} <- user_data_from_user_object(data) do {:ok, maybe_update_follow_information(data)} else - {:error, "Object has been deleted" = e} -> - Logger.debug("Could not decode user at fetch #{ap_id}, #{inspect(e)}") - {:error, e} - {:error, {:reject, reason} = e} -> Logger.info("Rejected user #{ap_id}: #{inspect(reason)}") {:error, e} -- cgit v1.2.3 From de6d49c8cec84a530f2835313c95064ae8df3604 Mon Sep 17 00:00:00 2001 From: lain Date: Mon, 26 Oct 2020 16:33:26 +0100 Subject: ActivityPub: Add back debug call + explanation. --- lib/pleroma/web/activity_pub/activity_pub.ex | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'lib') diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index df18db603..13869f897 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -1378,6 +1378,11 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do {:ok, data} <- user_data_from_user_object(data) do {:ok, maybe_update_follow_information(data)} else + # If this has been deleted, only log a debug and not an error + {:error, "Object has been deleted" = e} -> + Logger.debug("Could not decode user at fetch #{ap_id}, #{inspect(e)}") + {:error, e} + {:error, {:reject, reason} = e} -> Logger.info("Rejected user #{ap_id}: #{inspect(reason)}") {:error, e} -- cgit v1.2.3 From d28f72a55af9442719ff01fe7052802c285f6ea8 Mon Sep 17 00:00:00 2001 From: Maksim Pechnikov Date: Tue, 27 Oct 2020 22:58:55 +0300 Subject: FrontStatic plug: excluded invalid url --- lib/pleroma/web/plugs/frontend_static.ex | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/plugs/frontend_static.ex b/lib/pleroma/web/plugs/frontend_static.ex index ceb10dcf8..1b0b36813 100644 --- a/lib/pleroma/web/plugs/frontend_static.ex +++ b/lib/pleroma/web/plugs/frontend_static.ex @@ -34,22 +34,26 @@ defmodule Pleroma.Web.Plugs.FrontendStatic do end def call(conn, opts) do - frontend_type = Map.get(opts, :frontend_type, :primary) - path = file_path("", frontend_type) - - if path do - conn - |> call_static(opts, path) + with false <- invalid_path?(conn.path_info), + frontend_type <- Map.get(opts, :frontend_type, :primary), + path when not is_nil(path) <- file_path("", frontend_type) do + call_static(conn, opts, path) else - conn + _ -> + conn end end - defp call_static(conn, opts, from) do - opts = - opts - |> Map.put(:from, from) + defp invalid_path?(list) do + invalid_path?(list, :binary.compile_pattern(["/", "\\", ":", "\0"])) + end + defp invalid_path?([h | _], _match) when h in [".", "..", ""], do: true + defp invalid_path?([h | t], match), do: String.contains?(h, match) or invalid_path?(t) + defp invalid_path?([], _match), do: false + + defp call_static(conn, opts, from) do + opts = Map.put(opts, :from, from) Plug.Static.call(conn, opts) end end -- cgit v1.2.3 From da4a1e57b11d5600788b90f21d18bbcd97f6849f Mon Sep 17 00:00:00 2001 From: Ivan Tashkinov Date: Wed, 28 Oct 2020 19:09:38 +0300 Subject: @doc fix. --- lib/pleroma/web/static_fe/static_fe_controller.ex | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/static_fe/static_fe_controller.ex b/lib/pleroma/web/static_fe/static_fe_controller.ex index 76b82589f..bdec0897a 100644 --- a/lib/pleroma/web/static_fe/static_fe_controller.ex +++ b/lib/pleroma/web/static_fe/static_fe_controller.ex @@ -19,7 +19,7 @@ defmodule Pleroma.Web.StaticFE.StaticFEController do @page_keys ["max_id", "min_id", "limit", "since_id", "order"] - @doc "Renders requested local public activity" + @doc "Renders requested local public activity or public activities of requested user" def show(%{assigns: %{notice_id: notice_id}} = conn, _params) do with %Activity{local: true} = activity <- Activity.get_by_id_with_object(notice_id), @@ -46,7 +46,6 @@ defmodule Pleroma.Web.StaticFE.StaticFEController do end end - @doc "Renders public activities of requested user" def show(%{assigns: %{username_or_id: username_or_id}} = conn, params) do with {_, %User{local: true} = user} <- {:fetch_user, User.get_cached_by_nickname_or_id(username_or_id)}, -- cgit v1.2.3 From 9f5f7dc9f956359204fc44a0627e20fd9765d8bd Mon Sep 17 00:00:00 2001 From: Ivan Tashkinov Date: Wed, 28 Oct 2020 22:29:52 +0300 Subject: Fixed User.is_discoverable attribute rendering in Admin API User view. --- lib/pleroma/web/admin_api/views/account_view.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/web/admin_api/views/account_view.ex b/lib/pleroma/web/admin_api/views/account_view.ex index bda7ea19c..8bac24d3e 100644 --- a/lib/pleroma/web/admin_api/views/account_view.ex +++ b/lib/pleroma/web/admin_api/views/account_view.ex @@ -52,7 +52,7 @@ defmodule Pleroma.Web.AdminAPI.AccountView do :skip_thread_containment, :pleroma_settings_store, :raw_fields, - :discoverable, + :is_discoverable, :actor_type ]) |> Map.merge(%{ -- cgit v1.2.3 From 241bd061fc60a5c90c172f46f3b4e576ba660aaf Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Fri, 16 Oct 2020 18:28:27 +0000 Subject: ConversationView: add current user to conversations, according to Mastodon behaviour --- lib/pleroma/web/mastodon_api/views/conversation_view.ex | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/mastodon_api/views/conversation_view.ex b/lib/pleroma/web/mastodon_api/views/conversation_view.ex index a91994915..cf34933ab 100644 --- a/lib/pleroma/web/mastodon_api/views/conversation_view.ex +++ b/lib/pleroma/web/mastodon_api/views/conversation_view.ex @@ -33,12 +33,10 @@ defmodule Pleroma.Web.MastodonAPI.ConversationView do end activity = Activity.get_by_id_with_object(last_activity_id) - # Conversations return all users except the current user. - users = Enum.reject(participation.recipients, &(&1.id == user.id)) %{ id: participation.id |> to_string(), - accounts: render(AccountView, "index.json", users: users, for: user), + accounts: render(AccountView, "index.json", users: participation.recipients, for: user), unread: !participation.read, last_status: render(StatusView, "show.json", -- cgit v1.2.3 From 9b93eef71550eabf55b9728b6c8925a4dede222d Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Fri, 30 Oct 2020 13:01:58 +0100 Subject: ConversationView: fix last_status.account being empty, fix current user being included in group conversations --- lib/pleroma/web/mastodon_api/views/conversation_view.ex | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/mastodon_api/views/conversation_view.ex b/lib/pleroma/web/mastodon_api/views/conversation_view.ex index cf34933ab..4636c00e3 100644 --- a/lib/pleroma/web/mastodon_api/views/conversation_view.ex +++ b/lib/pleroma/web/mastodon_api/views/conversation_view.ex @@ -34,14 +34,22 @@ defmodule Pleroma.Web.MastodonAPI.ConversationView do activity = Activity.get_by_id_with_object(last_activity_id) + # Conversations return all users except current user when current user is not only participant + users = if length(participation.recipients) > 1 do + Enum.reject(participation.recipients, &(&1.id == user.id)) + else + participation.recipients + end + %{ id: participation.id |> to_string(), - accounts: render(AccountView, "index.json", users: participation.recipients, for: user), + accounts: render(AccountView, "index.json", users: users, for: user), unread: !participation.read, last_status: render(StatusView, "show.json", activity: activity, - direct_conversation_id: participation.id + direct_conversation_id: participation.id, + for: user ) } end -- cgit v1.2.3 From d63ec02f31e5ee7bb278c4247a83900aceb9193a Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Fri, 30 Oct 2020 13:25:13 +0100 Subject: ConversationView: fix formatting --- lib/pleroma/web/mastodon_api/views/conversation_view.ex | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/mastodon_api/views/conversation_view.ex b/lib/pleroma/web/mastodon_api/views/conversation_view.ex index 4636c00e3..545778165 100644 --- a/lib/pleroma/web/mastodon_api/views/conversation_view.ex +++ b/lib/pleroma/web/mastodon_api/views/conversation_view.ex @@ -35,11 +35,12 @@ defmodule Pleroma.Web.MastodonAPI.ConversationView do activity = Activity.get_by_id_with_object(last_activity_id) # Conversations return all users except current user when current user is not only participant - users = if length(participation.recipients) > 1 do - Enum.reject(participation.recipients, &(&1.id == user.id)) - else - participation.recipients - end + users = + if length(participation.recipients) > 1 do + Enum.reject(participation.recipients, &(&1.id == user.id)) + else + participation.recipients + end %{ id: participation.id |> to_string(), -- cgit v1.2.3 From d1698267a27bd5084916f5f6f36d66b1ff2ffc5f Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Sat, 31 Oct 2020 00:26:11 +0400 Subject: Fix credo warning --- lib/pleroma/web/router.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index 9592d0f38..efe67ad7a 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -148,7 +148,7 @@ defmodule Pleroma.Web.Router do scope "/api/pleroma/admin", Pleroma.Web.AdminAPI do pipe_through(:admin_api) - + put("/users/disable_mfa", AdminAPIController, :disable_mfa) put("/users/tag", AdminAPIController, :tag_users) delete("/users/tag", AdminAPIController, :untag_users) -- cgit v1.2.3 From 8e41baff40555ef7c74c8842d6fbfebc2368631a Mon Sep 17 00:00:00 2001 From: eugenijm Date: Sat, 31 Oct 2020 05:50:48 +0300 Subject: Add idempotency_key to the chat_message entity. --- lib/pleroma/application.ex | 9 ++++++++- lib/pleroma/web/activity_pub/side_effects.ex | 6 ++++++ lib/pleroma/web/common_api.ex | 3 ++- lib/pleroma/web/pleroma_api/controllers/chat_controller.ex | 10 +++++++++- .../web/pleroma_api/views/chat/message_reference_view.ex | 11 +++++++++++ 5 files changed, 36 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/application.ex b/lib/pleroma/application.ex index 51e9dda3b..7c4cd9626 100644 --- a/lib/pleroma/application.ex +++ b/lib/pleroma/application.ex @@ -168,7 +168,11 @@ defmodule Pleroma.Application do build_cachex("web_resp", limit: 2500), build_cachex("emoji_packs", expiration: emoji_packs_expiration(), limit: 10), build_cachex("failed_proxy_url", limit: 2500), - build_cachex("banned_urls", default_ttl: :timer.hours(24 * 30), limit: 5_000) + build_cachex("banned_urls", default_ttl: :timer.hours(24 * 30), limit: 5_000), + build_cachex("chat_message_id_idempotency_key", + expiration: chat_message_id_idempotency_key_expiration(), + limit: 500_000 + ) ] end @@ -178,6 +182,9 @@ defmodule Pleroma.Application do defp idempotency_expiration, do: expiration(default: :timer.seconds(6 * 60 * 60), interval: :timer.seconds(60)) + defp chat_message_id_idempotency_key_expiration, + do: expiration(default: :timer.minutes(2), interval: :timer.seconds(60)) + defp seconds_valid_interval, do: :timer.seconds(Config.get!([Pleroma.Captcha, :seconds_valid])) diff --git a/lib/pleroma/web/activity_pub/side_effects.ex b/lib/pleroma/web/activity_pub/side_effects.ex index 0fff5faf2..d552e91fc 100644 --- a/lib/pleroma/web/activity_pub/side_effects.ex +++ b/lib/pleroma/web/activity_pub/side_effects.ex @@ -312,6 +312,12 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do {:ok, chat} = Chat.bump_or_create(user.id, other_user.ap_id) {:ok, cm_ref} = MessageReference.create(chat, object, user.ap_id != actor.ap_id) + Cachex.put( + :chat_message_id_idempotency_key_cache, + cm_ref.id, + meta[:idempotency_key] + ) + { ["user", "user:pleroma_chat"], {user, %{cm_ref | chat: chat, object: object}} diff --git a/lib/pleroma/web/common_api.ex b/lib/pleroma/web/common_api.ex index 60a50b027..318ffc5d0 100644 --- a/lib/pleroma/web/common_api.ex +++ b/lib/pleroma/web/common_api.ex @@ -45,7 +45,8 @@ defmodule Pleroma.Web.CommonAPI do {_, {:ok, %Activity{} = activity, _meta}} <- {:common_pipeline, Pipeline.common_pipeline(create_activity_data, - local: true + local: true, + idempotency_key: opts[:idempotency_key] )} do {:ok, activity} else diff --git a/lib/pleroma/web/pleroma_api/controllers/chat_controller.ex b/lib/pleroma/web/pleroma_api/controllers/chat_controller.ex index 6357148d0..2c4d3f135 100644 --- a/lib/pleroma/web/pleroma_api/controllers/chat_controller.ex +++ b/lib/pleroma/web/pleroma_api/controllers/chat_controller.ex @@ -80,7 +80,8 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do %User{} = recipient <- User.get_cached_by_ap_id(chat.recipient), {:ok, activity} <- CommonAPI.post_chat_message(user, recipient, params[:content], - media_id: params[:media_id] + media_id: params[:media_id], + idempotency_key: idempotency_key(conn) ), message <- Object.normalize(activity, false), cm_ref <- MessageReference.for_chat_and_object(chat, message) do @@ -169,4 +170,11 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do |> render("show.json", chat: chat) end end + + defp idempotency_key(conn) do + case get_req_header(conn, "idempotency-key") do + [key] -> key + _ -> nil + end + end end diff --git a/lib/pleroma/web/pleroma_api/views/chat/message_reference_view.ex b/lib/pleroma/web/pleroma_api/views/chat/message_reference_view.ex index d4e08b50d..c058fb340 100644 --- a/lib/pleroma/web/pleroma_api/views/chat/message_reference_view.ex +++ b/lib/pleroma/web/pleroma_api/views/chat/message_reference_view.ex @@ -5,6 +5,7 @@ defmodule Pleroma.Web.PleromaAPI.Chat.MessageReferenceView do use Pleroma.Web, :view + alias Pleroma.Maps alias Pleroma.User alias Pleroma.Web.CommonAPI.Utils alias Pleroma.Web.MastodonAPI.StatusView @@ -37,6 +38,7 @@ defmodule Pleroma.Web.PleromaAPI.Chat.MessageReferenceView do Pleroma.Web.RichMedia.Helpers.fetch_data_for_object(object) ) } + |> put_idempotency_key() end def render("index.json", opts) do @@ -47,4 +49,13 @@ defmodule Pleroma.Web.PleromaAPI.Chat.MessageReferenceView do Map.put(opts, :as, :chat_message_reference) ) end + + defp put_idempotency_key(data) do + with {:ok, idempotency_key} <- Cachex.get(:chat_message_id_idempotency_key_cache, data.id) do + data + |> Maps.put_if_present(:idempotency_key, idempotency_key) + else + _ -> data + end + end end -- cgit v1.2.3 From 8f00d90f9199e384fb1befb677c1c0595a0c854c Mon Sep 17 00:00:00 2001 From: Ekaterina Vaartis Date: Sun, 1 Nov 2020 12:05:39 +0300 Subject: Use Pleroma.HTTP instead of Tesla Closes #2275 As discovered in the issue, captcha used Tesla.get instead of Pleroma.HTTP. I've also grep'ed the repo and changed the other place where this was used. --- lib/pleroma/captcha/kocaptcha.ex | 2 +- lib/pleroma/emoji/pack.ex | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/captcha/kocaptcha.ex b/lib/pleroma/captcha/kocaptcha.ex index 337506647..201b55ab4 100644 --- a/lib/pleroma/captcha/kocaptcha.ex +++ b/lib/pleroma/captcha/kocaptcha.ex @@ -10,7 +10,7 @@ defmodule Pleroma.Captcha.Kocaptcha do def new do endpoint = Pleroma.Config.get!([__MODULE__, :endpoint]) - case Tesla.get(endpoint <> "/new") do + case Pleroma.HTTP.get(endpoint <> "/new") do {:error, _} -> %{error: :kocaptcha_service_unavailable} diff --git a/lib/pleroma/emoji/pack.ex b/lib/pleroma/emoji/pack.ex index 0670f29f1..ca58e5432 100644 --- a/lib/pleroma/emoji/pack.ex +++ b/lib/pleroma/emoji/pack.ex @@ -594,7 +594,7 @@ defmodule Pleroma.Emoji.Pack do end defp download_archive(url, sha) do - with {:ok, %{body: archive}} <- Tesla.get(url) do + with {:ok, %{body: archive}} <- Pleroma.HTTP.get(url) do if Base.decode16!(sha) == :crypto.hash(:sha256, archive) do {:ok, archive} else @@ -617,7 +617,7 @@ defmodule Pleroma.Emoji.Pack do end defp update_sha_and_save_metadata(pack, data) do - with {:ok, %{body: zip}} <- Tesla.get(data[:"fallback-src"]), + with {:ok, %{body: zip}} <- Pleroma.HTTP.get(data[:"fallback-src"]), :ok <- validate_has_all_files(pack, zip) do fallback_sha = :sha256 |> :crypto.hash(zip) |> Base.encode16() -- cgit v1.2.3 From 4caad4e9101c34debfa90d2e89850d4125a471b3 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Mon, 2 Nov 2020 05:43:06 +0100 Subject: =?UTF-8?q?side=5Feffects:=20Don=E2=80=99t=20increase=5Freplies=5F?= =?UTF-8?q?count=20when=20it=E2=80=99s=20an=20Answer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pleroma/web/activity_pub/side_effects.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/web/activity_pub/side_effects.ex b/lib/pleroma/web/activity_pub/side_effects.ex index 0fff5faf2..9b1171d07 100644 --- a/lib/pleroma/web/activity_pub/side_effects.ex +++ b/lib/pleroma/web/activity_pub/side_effects.ex @@ -187,7 +187,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"] do + if in_reply_to = object.data["inReplyTo"] && object.data["type"] != "Answer" do Object.increase_replies_count(in_reply_to) end -- cgit v1.2.3 From be52819a112abb66032a56d613eed0233995eef4 Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Mon, 2 Nov 2020 17:51:54 +0400 Subject: Hide chats from muted users --- .../web/pleroma_api/controllers/chat_controller.ex | 27 +++++++++------------- 1 file changed, 11 insertions(+), 16 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/pleroma_api/controllers/chat_controller.ex b/lib/pleroma/web/pleroma_api/controllers/chat_controller.ex index 2c4d3f135..8fc70c15a 100644 --- a/lib/pleroma/web/pleroma_api/controllers/chat_controller.ex +++ b/lib/pleroma/web/pleroma_api/controllers/chat_controller.ex @@ -15,7 +15,6 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do alias Pleroma.User alias Pleroma.Web.CommonAPI alias Pleroma.Web.PleromaAPI.Chat.MessageReferenceView - alias Pleroma.Web.PleromaAPI.ChatView alias Pleroma.Web.Plugs.OAuthScopesPlug import Ecto.Query @@ -121,9 +120,7 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do ) do with {:ok, chat} <- Chat.get_by_user_and_id(user, id), {_n, _} <- MessageReference.set_all_seen_for_chat(chat, last_read_id) do - conn - |> put_view(ChatView) - |> render("show.json", chat: chat) + render(conn, "show.json", chat: chat) end end @@ -142,32 +139,30 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do end def index(%{assigns: %{user: %{id: user_id} = user}} = conn, _params) do - blocked_ap_ids = User.blocked_users_ap_ids(user) + exclude_users = + user + |> User.blocked_users_ap_ids() + |> Enum.concat(User.muted_users_ap_ids(user)) chats = - Chat.for_user_query(user_id) - |> where([c], c.recipient not in ^blocked_ap_ids) + user_id + |> Chat.for_user_query() + |> where([c], c.recipient not in ^exclude_users) |> Repo.all() - conn - |> put_view(ChatView) - |> render("index.json", chats: chats) + render(conn, "index.json", chats: chats) end def create(%{assigns: %{user: user}} = conn, %{id: id}) do with %User{ap_id: recipient} <- User.get_cached_by_id(id), {:ok, %Chat{} = chat} <- Chat.get_or_create(user.id, recipient) do - conn - |> put_view(ChatView) - |> render("show.json", chat: chat) + render(conn, "show.json", chat: chat) end end def show(%{assigns: %{user: user}} = conn, %{id: id}) do with {:ok, chat} <- Chat.get_by_user_and_id(user, id) do - conn - |> put_view(ChatView) - |> render("show.json", chat: chat) + render(conn, "show.json", chat: chat) end end -- cgit v1.2.3 From 7efc074eadae9b3d6d351e769ead0661f1f4c89c Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Mon, 2 Nov 2020 12:19:44 -0600 Subject: Permit fetching individual reports with notes preloaded --- lib/pleroma/activity.ex | 13 +++++++++++++ lib/pleroma/web/admin_api/controllers/report_controller.ex | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/activity.ex b/lib/pleroma/activity.ex index 17af04257..553834da0 100644 --- a/lib/pleroma/activity.ex +++ b/lib/pleroma/activity.ex @@ -14,6 +14,7 @@ defmodule Pleroma.Activity do alias Pleroma.ReportNote alias Pleroma.ThreadMute alias Pleroma.User + alias Pleroma.Web.ActivityPub.ActivityPub import Ecto.Changeset import Ecto.Query @@ -153,6 +154,18 @@ defmodule Pleroma.Activity do def get_bookmark(_, _), do: nil + def get_report(activity_id) do + opts = %{ + type: "Flag", + skip_preload: true, + preload_report_notes: true + } + + ActivityPub.fetch_activities_query([], opts) + |> where(id: ^activity_id) + |> Repo.one() + end + def change(struct, params \\ %{}) do struct |> cast(params, [:data, :recipients]) diff --git a/lib/pleroma/web/admin_api/controllers/report_controller.ex b/lib/pleroma/web/admin_api/controllers/report_controller.ex index 86da93893..6a0e56f5f 100644 --- a/lib/pleroma/web/admin_api/controllers/report_controller.ex +++ b/lib/pleroma/web/admin_api/controllers/report_controller.ex @@ -38,7 +38,7 @@ defmodule Pleroma.Web.AdminAPI.ReportController do end def show(conn, %{id: id}) do - with %Activity{} = report <- Activity.get_by_id(id) do + with %Activity{} = report <- Activity.get_report(id) do render(conn, "show.json", Report.extract_report_info(report)) else _ -> {:error, :not_found} -- cgit v1.2.3 From c37118e6f26f0305d540047e4ccb8d594d2c0e6b Mon Sep 17 00:00:00 2001 From: lain Date: Tue, 3 Nov 2020 13:56:12 +0100 Subject: Conversations: A few refactors --- lib/pleroma/web/mastodon_api/views/conversation_view.ex | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/web/mastodon_api/views/conversation_view.ex b/lib/pleroma/web/mastodon_api/views/conversation_view.ex index 545778165..82fcff062 100644 --- a/lib/pleroma/web/mastodon_api/views/conversation_view.ex +++ b/lib/pleroma/web/mastodon_api/views/conversation_view.ex @@ -34,7 +34,8 @@ defmodule Pleroma.Web.MastodonAPI.ConversationView do activity = Activity.get_by_id_with_object(last_activity_id) - # Conversations return all users except current user when current user is not only participant + # Conversations return all users except the current user, + # except when the current user is the only participant users = if length(participation.recipients) > 1 do Enum.reject(participation.recipients, &(&1.id == user.id)) -- cgit v1.2.3 From ca95cbe0b48b6c64e6e33addf79e4d212d5f9872 Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Wed, 4 Nov 2020 16:40:12 +0400 Subject: Add `with_muted` param to ChatController.index/2 --- lib/pleroma/web/api_spec/operations/chat_operation.ex | 6 +++++- lib/pleroma/web/api_spec/operations/timeline_operation.ex | 2 +- lib/pleroma/web/pleroma_api/controllers/chat_controller.ex | 7 +++---- 3 files changed, 9 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/web/api_spec/operations/chat_operation.ex b/lib/pleroma/web/api_spec/operations/chat_operation.ex index 0dcfdb354..560b81f17 100644 --- a/lib/pleroma/web/api_spec/operations/chat_operation.ex +++ b/lib/pleroma/web/api_spec/operations/chat_operation.ex @@ -6,6 +6,7 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do alias OpenApiSpex.Operation alias OpenApiSpex.Schema alias Pleroma.Web.ApiSpec.Schemas.ApiError + alias Pleroma.Web.ApiSpec.Schemas.BooleanLike alias Pleroma.Web.ApiSpec.Schemas.Chat alias Pleroma.Web.ApiSpec.Schemas.ChatMessage @@ -132,7 +133,10 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do tags: ["chat"], summary: "Get a list of chats that you participated in", operationId: "ChatController.index", - parameters: pagination_params(), + parameters: [ + Operation.parameter(:with_muted, :query, BooleanLike, "Include chats from muted users") + | pagination_params() + ], responses: %{ 200 => Operation.response("The chats of the user", "application/json", chats_response()) }, diff --git a/lib/pleroma/web/api_spec/operations/timeline_operation.ex b/lib/pleroma/web/api_spec/operations/timeline_operation.ex index 8e19bace7..1b5ad796f 100644 --- a/lib/pleroma/web/api_spec/operations/timeline_operation.ex +++ b/lib/pleroma/web/api_spec/operations/timeline_operation.ex @@ -159,7 +159,7 @@ defmodule Pleroma.Web.ApiSpec.TimelineOperation do end defp with_muted_param do - Operation.parameter(:with_muted, :query, BooleanLike, "Includeactivities by muted users") + Operation.parameter(:with_muted, :query, BooleanLike, "Include activities by muted users") end defp exclude_visibilities_param do diff --git a/lib/pleroma/web/pleroma_api/controllers/chat_controller.ex b/lib/pleroma/web/pleroma_api/controllers/chat_controller.ex index 8fc70c15a..77564b342 100644 --- a/lib/pleroma/web/pleroma_api/controllers/chat_controller.ex +++ b/lib/pleroma/web/pleroma_api/controllers/chat_controller.ex @@ -138,11 +138,10 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do end end - def index(%{assigns: %{user: %{id: user_id} = user}} = conn, _params) do + def index(%{assigns: %{user: %{id: user_id} = user}} = conn, params) do exclude_users = - user - |> User.blocked_users_ap_ids() - |> Enum.concat(User.muted_users_ap_ids(user)) + User.blocked_users_ap_ids(user) ++ + if params[:with_muted], do: [], else: User.muted_users_ap_ids(user) chats = user_id -- cgit v1.2.3