Merge pull request 'Add YunoHost to installation guides' (#518) from ilja/akkoma...
authorfloatingghost <hannah@coffee-and-dreams.uk>
Tue, 11 Apr 2023 09:26:38 +0000 (09:26 +0000)
committerfloatingghost <hannah@coffee-and-dreams.uk>
Tue, 11 Apr 2023 09:26:38 +0000 (09:26 +0000)
Reviewed-on: https://akkoma.dev/AkkomaGang/akkoma/pulls/518

27 files changed:
CHANGELOG.md
config/config.exs
config/custom_emoji.txt
config/description.exs
lib/mix/tasks/pleroma/diagnostics.ex
lib/pleroma/activity.ex
lib/pleroma/instances/instance.ex
lib/pleroma/user.ex
lib/pleroma/web/activity_pub/activity_pub.ex
lib/pleroma/web/api_spec/operations/timeline_operation.ex
lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex
lib/pleroma/web/mastodon_api/views/instance_view.ex
lib/pleroma/web/mastodon_api/views/status_view.ex
lib/pleroma/web/nodeinfo/nodeinfo.ex
lib/pleroma/web/nodeinfo/nodeinfo_controller.ex
lib/pleroma/web/o_status/o_status_controller.ex
lib/pleroma/web/router.ex
mix.lock
priv/static/emoji/hehe.png [new file with mode: 0644]
priv/static/emoji/nothehe.png [new file with mode: 0644]
test/pleroma/user_test.exs
test/pleroma/web/activity_pub/activity_pub_test.exs
test/pleroma/web/mastodon_api/controllers/media_controller_test.exs
test/pleroma/web/mastodon_api/controllers/timeline_controller_test.exs
test/pleroma/web/mastodon_api/update_credentials_test.exs
test/pleroma/web/mastodon_api/views/account_view_test.exs
test/pleroma/web/node_info_test.exs

index d620c4f3ba3b5db8c09a95e5e3e7378fd2c631ee..1bf6253af55e7b5e21baa971c620120a9fd41401 100644 (file)
@@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file.
 
 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 
+## Unreleased
+
+## Added
+- Nodeinfo keys for unauthenticated timeline visibility
+- Option to disable federated timeline
+- Option to make the bubble timeline publicly accessible
+
 ## 2023.03
 
 ## Fixed
index 5eaa8ce760dc1ef696ea7fac0e3aa3f11e6c09ad..e216caf9d2c9913aa2c20be6785d594117971c01 100644 (file)
@@ -261,7 +261,8 @@ config :pleroma, :instance,
   privileged_staff: false,
   local_bubble: [],
   max_frontend_settings_json_chars: 100_000,
-  export_prometheus_metrics: true
+  export_prometheus_metrics: true,
+  federated_timeline_available: true
 
 config :pleroma, :welcome,
   direct_message: [
@@ -810,7 +811,7 @@ config :pleroma, :majic_pool, size: 2
 private_instance? = :if_instance_is_private
 
 config :pleroma, :restrict_unauthenticated,
-  timelines: %{local: private_instance?, federated: private_instance?},
+  timelines: %{local: private_instance?, federated: private_instance?, bubble: true},
   profiles: %{local: private_instance?, remote: private_instance?},
   activities: %{local: private_instance?, remote: private_instance?}
 
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..7b2e51265f538ddfabf8ad9c9e90a1b4c3e9c354 100644 (file)
@@ -0,0 +1,2 @@
+hehe, /emoji/hehe.png, Akkoma
+nothehe, /emoji/nothehe.png, Akkoma
index 2a2d70a7b4a327a26fc92ac970db8d7cd9cf2c56..6520bc29aa7678656a0cbcf0a93a3033ad2121e0 100644 (file)
@@ -969,6 +969,12 @@ config :pleroma, :config_description, [
         key: :export_prometheus_metrics,
         type: :boolean,
         description: "Enable prometheus metrics (at /api/v1/akkoma/metrics)"
+      },
+      %{
+        key: :federated_timeline_available,
+        type: :boolean,
+        description:
+          "Let people view the 'firehose' feed of all public statuses from all instances."
       }
     ]
   },
@@ -2993,6 +2999,11 @@ config :pleroma, :config_description, [
             key: :federated,
             type: :boolean,
             description: "Disallow viewing the whole known network timeline."
+          },
+          %{
+            key: :bubble,
+            type: :boolean,
+            description: "Disallow viewing the bubble timeline."
           }
         ]
       },
index 3914540ca9597d1a1fe9d37534d43992298f0391..3b6063723713435a3c4373f4b8bc79f22d9269e1 100644 (file)
@@ -82,4 +82,46 @@ defmodule Mix.Tasks.Pleroma.Diagnostics do
     Ecto.Adapters.SQL.explain(Repo, :all, query, analyze: true, timeout: :infinity)
     |> IO.puts()
   end
+
+  def run(["notifications", nickname]) do
+    start_pleroma()
+    user = Repo.get_by!(User, nickname: nickname)
+    account_ap_id = user.ap_id
+    options = %{account_ap_id: user.ap_id}
+
+    query =
+      user
+      |> Pleroma.Notification.for_user_query(options)
+      |> where([n, a], a.actor == ^account_ap_id)
+      |> limit(20)
+
+    Ecto.Adapters.SQL.explain(Repo, :all, query, analyze: true, timeout: :infinity)
+    |> IO.puts()
+  end
+
+  def run(["known_network", nickname]) do
+    start_pleroma()
+    user = Repo.get_by!(User, nickname: nickname)
+
+    params =
+      %{}
+      |> Map.put(:type, ["Create"])
+      |> Map.put(:local_only, false)
+      |> Map.put(:blocking_user, user)
+      |> Map.put(:muting_user, user)
+      |> Map.put(:reply_filtering_user, user)
+      # Restricts unfederated content to authenticated users
+      |> Map.put(:includes_local_public, not is_nil(user))
+      |> Map.put(:restrict_unlisted, true)
+
+    query =
+      Pleroma.Web.ActivityPub.ActivityPub.fetch_activities_query(
+        [Pleroma.Constants.as_public()],
+        params
+      )
+      |> limit(20)
+    
+    Ecto.Adapters.SQL.explain(Repo, :all, query, analyze: true, timeout: :infinity)
+    |> IO.puts()    
+  end
 end
index c5b51474269fb7afd76494cdf003c512db472752..c94667fb9f177be171898c9b6b4d42766a9bb1a0 100644 (file)
@@ -277,6 +277,13 @@ defmodule Pleroma.Activity do
 
   def get_create_by_object_ap_id_with_object(_), do: nil
 
+  def get_local_create_by_object_ap_id(ap_id) when is_binary(ap_id) do
+    ap_id
+    |> create_by_object_ap_id()
+    |> where(local: true)
+    |> Repo.one()
+  end
+
   @spec create_by_id_with_object(String.t()) :: t() | nil
   def create_by_id_with_object(id) do
     get_by_id_with_opts(id, preload: [:object], filter: [type: "Create"])
index 6ddfa5042ae386fa642d47fdf67a99c2d8bfe466..5c70748b6da2d5060951bffc685a9dd3f5e3f007 100644 (file)
@@ -162,7 +162,7 @@ defmodule Pleroma.Instances.Instance do
     %Instance{
       host: Pleroma.Web.Endpoint.host(),
       favicon: Pleroma.Web.Endpoint.url() <> "/favicon.png",
-      nodeinfo: Pleroma.Web.Nodeinfo.NodeinfoController.raw_nodeinfo()
+      nodeinfo: Pleroma.Web.Nodeinfo.Nodeinfo.get_nodeinfo("2.1")
     }
   end
 
index f94202af5df22510d19f30fb73a5133ae923e9c7..ead37ccca00a03f070f99cef5357fc186acc2362 100644 (file)
@@ -366,21 +366,21 @@ defmodule Pleroma.User do
   def invisible?(_), do: false
 
   def avatar_url(user, options \\ []) do
-    case user.avatar do
-      %{"url" => [%{"href" => href} | _]} ->
-        href
-
-      _ ->
-        unless options[:no_default] do
-          Config.get([:assets, :default_user_avatar], "#{Endpoint.url()}/images/avi.png")
-        end
-    end
+    default = Config.get([:assets, :default_user_avatar], "#{Endpoint.url()}/images/avi.png")
+    do_optional_url(user.avatar, default, options)
   end
 
   def banner_url(user, options \\ []) do
-    case user.banner do
-      %{"url" => [%{"href" => href} | _]} -> href
-      _ -> !options[:no_default] && "#{Endpoint.url()}/images/banner.png"
+    do_optional_url(user.banner, "#{Endpoint.url()}/images/banner.png", options)
+  end
+
+  defp do_optional_url(field, default, options) do
+    case field do
+      %{"url" => [%{"href" => href} | _]} when is_binary(href) ->
+        href
+
+      _ ->
+        unless options[:no_default], do: default
     end
   end
 
index 8e55df0d8cac2fc955b2394e197be133167ffe89..649bf909544d3f07f484c2bf966623bc29ec4e7b 100644 (file)
@@ -1502,13 +1502,22 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
 
   @spec upload(Upload.source(), keyword()) :: {:ok, Object.t()} | {:error, any()}
   def upload(file, opts \\ []) do
-    with {:ok, data} <- Upload.store(file, opts) do
+    with {:ok, data} <- Upload.store(sanitize_upload_file(file), opts) do
       obj_data = Maps.put_if_present(data, "actor", opts[:actor])
 
       Repo.insert(%Object{data: obj_data})
     end
   end
 
+  defp sanitize_upload_file(%Plug.Upload{filename: filename} = upload) when is_binary(filename) do
+    %Plug.Upload{
+      upload
+      | filename: Path.basename(filename)
+    }
+  end
+
+  defp sanitize_upload_file(upload), do: upload
+
   @spec get_actor_url(any()) :: binary() | nil
   defp get_actor_url(url) when is_binary(url), do: url
   defp get_actor_url(%{"href" => href}) when is_binary(href), do: href
index 3eb6f700b7f959986d9f58c5a6a93b502d4cfd62..45c97cab6d39d56ca744cc09a2dfbd9eaa21d1c1 100644 (file)
@@ -70,7 +70,8 @@ defmodule Pleroma.Web.ApiSpec.TimelineOperation do
       operationId: "TimelineController.public",
       responses: %{
         200 => Operation.response("Array of Status", "application/json", array_of_statuses()),
-        401 => Operation.response("Error", "application/json", ApiError)
+        401 => Operation.response("Error", "application/json", ApiError),
+        404 => Operation.response("Error", "application/json", ApiError)
       }
     }
   end
index 2d0e36420f7a90c6007acd255e73fb467ddedda8..1d4e734a40d811f18ddd52bc542835173b490773 100644 (file)
@@ -16,7 +16,7 @@ defmodule Pleroma.Web.MastodonAPI.TimelineController do
   alias Pleroma.Web.Plugs.RateLimiter
 
   plug(Pleroma.Web.ApiSpec.CastAndValidate)
-  plug(:skip_public_check when action in [:public, :hashtag])
+  plug(:skip_public_check when action in [:public, :hashtag, :bubble])
 
   # TODO: Replace with a macro when there is a Phoenix release with the following commit in it:
   # https://github.com/phoenixframework/phoenix/commit/2e8c63c01fec4dde5467dbbbf9705ff9e780735e
@@ -28,19 +28,25 @@ defmodule Pleroma.Web.MastodonAPI.TimelineController do
   plug(RateLimiter, [name: :timeline, bucket_name: :list_timeline] when action == :list)
   plug(RateLimiter, [name: :timeline, bucket_name: :bubble_timeline] when action == :bubble)
 
-  plug(OAuthScopesPlug, %{scopes: ["read:statuses"]} when action in [:home, :direct, :bubble])
+  plug(OAuthScopesPlug, %{scopes: ["read:statuses"]} when action in [:home, :direct])
   plug(OAuthScopesPlug, %{scopes: ["read:lists"]} when action == :list)
 
   plug(
     OAuthScopesPlug,
     %{scopes: ["read:statuses"], fallback: :proceed_unauthenticated}
-    when action in [:public, :hashtag]
+    when action in [:public, :hashtag, :bubble]
   )
 
+  require Logger
+
   defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.TimelineOperation
 
   # GET /api/v1/timelines/home
   def home(%{assigns: %{user: user}} = conn, params) do
+    %{nickname: nickname} = user
+
+    Logger.debug("TimelineController.home: #{nickname}")
+
     followed_hashtags =
       user
       |> User.followed_hashtags()
@@ -58,11 +64,15 @@ defmodule Pleroma.Web.MastodonAPI.TimelineController do
       |> Map.put(:followed_hashtags, followed_hashtags)
       |> Map.delete(:local)
 
+    Logger.debug("TimelineController.home: #{nickname} - fetching activities")
+
     activities =
       [user.ap_id | User.following(user)]
       |> ActivityPub.fetch_activities(params)
       |> Enum.reverse()
 
+    Logger.debug("TimelineController.home: #{nickname} - rendering")
+
     conn
     |> add_link_headers(activities)
     |> render("index.json",
@@ -75,6 +85,8 @@ defmodule Pleroma.Web.MastodonAPI.TimelineController do
 
   # GET /api/v1/timelines/direct
   def direct(%{assigns: %{user: user}} = conn, params) do
+    Logger.debug("TimelineController.direct: #{user.nickname}")
+
     params =
       params
       |> Map.put(:type, "Create")
@@ -82,11 +94,15 @@ defmodule Pleroma.Web.MastodonAPI.TimelineController do
       |> Map.put(:user, user)
       |> Map.put(:visibility, "direct")
 
+    Logger.debug("TimelineController.direct: #{user.nickname} - fetching activities")
+
     activities =
       [user.ap_id]
       |> ActivityPub.fetch_activities_query(params)
       |> Pagination.fetch_paginated(params)
 
+    Logger.debug("TimelineController.direct: #{user.nickname} - rendering")
+
     conn
     |> add_link_headers(activities)
     |> render("index.json",
@@ -96,21 +112,22 @@ defmodule Pleroma.Web.MastodonAPI.TimelineController do
     )
   end
 
-  defp restrict_unauthenticated?(true = _local_only) do
-    Config.restrict_unauthenticated_access?(:timelines, :local)
-  end
-
-  defp restrict_unauthenticated?(_) do
-    Config.restrict_unauthenticated_access?(:timelines, :federated)
+  defp restrict_unauthenticated?(type) do
+    Config.restrict_unauthenticated_access?(:timelines, type)
   end
 
   # GET /api/v1/timelines/public
   def public(%{assigns: %{user: user}} = conn, params) do
+    Logger.debug("TimelineController.public")
     local_only = params[:local]
+    timeline_type = if local_only, do: :local, else: :federated
+
+    with {:enabled, true} <-
+           {:enabled, local_only || Config.get([:instance, :federated_timeline_available], true)},
+         {:authenticated, true} <-
+           {:authenticated, !(is_nil(user) and restrict_unauthenticated?(timeline_type))} do
+      Logger.debug("TimelineController.public: fetching activities")
 
-    if is_nil(user) and restrict_unauthenticated?(local_only) do
-      fail_on_bad_auth(conn)
-    else
       activities =
         params
         |> Map.put(:type, ["Create"])
@@ -123,6 +140,8 @@ defmodule Pleroma.Web.MastodonAPI.TimelineController do
         |> Map.put(:includes_local_public, not is_nil(user))
         |> ActivityPub.fetch_public_activities()
 
+      Logger.debug("TimelineController.public: rendering")
+
       conn
       |> add_link_headers(activities, %{"local" => local_only})
       |> render("index.json",
@@ -131,20 +150,32 @@ defmodule Pleroma.Web.MastodonAPI.TimelineController do
         as: :activity,
         with_muted: Map.get(params, :with_muted, false)
       )
+    else
+      {:enabled, false} ->
+        conn
+        |> put_status(404)
+        |> json(%{error: "Federated timeline is disabled"})
+
+      {:authenticated, false} ->
+        fail_on_bad_auth(conn)
     end
   end
 
   # GET /api/v1/timelines/bubble
   def bubble(%{assigns: %{user: user}} = conn, params) do
-    bubble_instances =
-      Enum.uniq(
-        Config.get([:instance, :local_bubble], []) ++
-          [Pleroma.Web.Endpoint.host()]
-      )
+    Logger.debug("TimelineController.bubble")
 
-    if is_nil(user) do
+    if is_nil(user) and restrict_unauthenticated?(:bubble) do
       fail_on_bad_auth(conn)
     else
+      bubble_instances =
+        Enum.uniq(
+          Config.get([:instance, :local_bubble], []) ++
+            [Pleroma.Web.Endpoint.host()]
+        )
+
+      Logger.debug("TimelineController.bubble: fetching activities")
+
       activities =
         params
         |> Map.put(:type, ["Create"])
@@ -154,6 +185,8 @@ defmodule Pleroma.Web.MastodonAPI.TimelineController do
         |> Map.put(:instance, bubble_instances)
         |> ActivityPub.fetch_public_activities()
 
+      Logger.debug("TimelineController.bubble: rendering")
+
       conn
       |> add_link_headers(activities)
       |> render("index.json",
@@ -195,7 +228,7 @@ defmodule Pleroma.Web.MastodonAPI.TimelineController do
   def hashtag(%{assigns: %{user: user}} = conn, params) do
     local_only = params[:local]
 
-    if is_nil(user) and restrict_unauthenticated?(local_only) do
+    if is_nil(user) and restrict_unauthenticated?(if local_only, do: :local, else: :federated) do
       fail_on_bad_auth(conn)
     else
       activities = hashtag_fetching(params, user, local_only)
index 2717da99d950b3c441ee3c7263c30b4ba61959ae..2b535487377dd2a591fb9d3c1c5eb6faeb411ffa 100644 (file)
@@ -67,6 +67,9 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do
       "pleroma:api/v1/notifications:include_types_filter",
       "quote_posting",
       "editing",
+      if !Enum.empty?(Config.get([:instance, :local_bubble], [])) do
+        "bubble_timeline"
+      end,
       if Config.get([:media_proxy, :enabled]) do
         "media_proxy"
       end,
index 3868da8d9310c96ec33fcf65230e5eea2552e423..47d1616c47b36794be2e830f8a33e45ea3f3255b 100644 (file)
@@ -21,6 +21,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
   alias Pleroma.Web.MastodonAPI.StatusView
   alias Pleroma.Web.MediaProxy
   alias Pleroma.Web.PleromaAPI.EmojiReactionController
+  require Logger
 
   import Pleroma.Web.ActivityPub.Visibility, only: [get_visibility: 1, visible_for_user?: 2]
 
@@ -87,6 +88,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
   defp reblogged?(_activity, _user), do: false
 
   def render("index.json", opts) do
+    Logger.debug("Rendering index")
     reading_user = opts[:for]
     # To do: check AdminAPIControllerTest on the reasons behind nil activities in the list
     activities = Enum.filter(opts.activities, & &1)
@@ -136,8 +138,10 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
 
   def render(
         "show.json",
-        %{activity: %{data: %{"type" => "Announce", "object" => _object}} = activity} = opts
+        %{activity: %{id: id, data: %{"type" => "Announce", "object" => _object}} = activity} =
+          opts
       ) do
+    Logger.debug("Rendering reblog #{id}")
     user = CommonAPI.get_user(activity.data["actor"])
     created_at = Utils.to_masto_date(activity.data["published"])
     object = Object.normalize(activity, fetch: false)
@@ -209,7 +213,9 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
     }
   end
 
-  def render("show.json", %{activity: %{data: %{"object" => _object}} = activity} = opts) do
+  def render("show.json", %{activity: %{id: id, data: %{"object" => _object}} = activity} = opts) do
+    Logger.debug("Rendering status #{id}")
+
     with %Object{} = object <- Object.normalize(activity, fetch: false) do
       user = CommonAPI.get_user(activity.data["actor"])
       user_follower_address = user.follower_address
@@ -428,6 +434,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
   end
 
   def render("history.json", %{activity: %{data: %{"object" => _object}} = activity} = opts) do
+    Logger.debug("Rendering history for #{activity.id}")
     object = Object.normalize(activity, fetch: false)
 
     hashtags = Object.hashtags(object)
@@ -614,6 +621,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
   def render("attachment_meta.json", _), do: nil
 
   def render("context.json", %{activity: activity, activities: activities, user: user}) do
+    Logger.debug("Rendering context for #{activity.id}")
+
     %{ancestors: ancestors, descendants: descendants} =
       activities
       |> Enum.reverse()
index bf0d65f4522ae1b72aa6267b47263d2e15b08a6a..532ae53a721d3a4eaaa19a9e70ba213360b67462 100644 (file)
@@ -71,7 +71,15 @@ defmodule Pleroma.Web.Nodeinfo.Nodeinfo do
         restrictedNicknames: Config.get([Pleroma.User, :restricted_nicknames]),
         skipThreadContainment: Config.get([:instance, :skip_thread_containment], false),
         privilegedStaff: Config.get([:instance, :privileged_staff]),
-        localBubbleInstances: Config.get([:instance, :local_bubble], [])
+        localBubbleInstances: Config.get([:instance, :local_bubble], []),
+        publicTimelineVisibility: %{
+          federated:
+            !Config.restrict_unauthenticated_access?(:timelines, :federated) &&
+              Config.get([:instance, :federated_timeline_available], true),
+          local: !Config.restrict_unauthenticated_access?(:timelines, :local),
+          bubble: !Config.restrict_unauthenticated_access?(:timelines, :bubble)
+        },
+        federatedTimelineAvailable: Config.get([:instance, :federated_timeline_available], true)
       }
     }
   end
index a0dee7c6bc283d370e667a051bb61ad530adcdf4..4c5a36895ceac1a09f025b3e9daae04450f9ba48 100644 (file)
@@ -11,6 +11,7 @@ defmodule Pleroma.Web.Nodeinfo.NodeinfoController do
   alias Pleroma.Web.Federator.Publisher
   alias Pleroma.Web.MastodonAPI.InstanceView
   alias Pleroma.Web.Endpoint
+  alias Pleroma.Web.Nodeinfo.Nodeinfo
 
   def schemas(conn, _params) do
     response = %{
@@ -29,101 +30,15 @@ defmodule Pleroma.Web.Nodeinfo.NodeinfoController do
     json(conn, response)
   end
 
-  # returns a nodeinfo 2.0 map, since 2.1 just adds a repository field
-  # under software.
-  def raw_nodeinfo do
-    stats = Stats.get_stats()
-
-    staff_accounts =
-      User.all_superusers()
-      |> Enum.map(fn u -> u.ap_id end)
-      |> Enum.filter(fn u -> not Enum.member?(Config.get([:instance, :staff_transparency]), u) end)
-
-    features = InstanceView.features()
-    federation = InstanceView.federation()
-
-    %{
-      version: "2.0",
-      software: %{
-        name: Pleroma.Application.name() |> String.downcase(),
-        version: Pleroma.Application.version()
-      },
-      protocols: Publisher.gather_nodeinfo_protocol_names(),
-      services: %{
-        inbound: [],
-        outbound: []
-      },
-      openRegistrations: Config.get([:instance, :registrations_open]),
-      usage: %{
-        users: %{
-          total: Map.get(stats, :user_count, 0)
-        },
-        localPosts: Map.get(stats, :status_count, 0)
-      },
-      metadata: %{
-        nodeName: Config.get([:instance, :name]),
-        nodeDescription: Config.get([:instance, :description]),
-        private: !Config.get([:instance, :public], true),
-        suggestions: %{
-          enabled: false
-        },
-        staffAccounts: staff_accounts,
-        federation: federation,
-        pollLimits: Config.get([:instance, :poll_limits]),
-        postFormats: Config.get([:instance, :allowed_post_formats]),
-        uploadLimits: %{
-          general: Config.get([:instance, :upload_limit]),
-          avatar: Config.get([:instance, :avatar_upload_limit]),
-          banner: Config.get([:instance, :banner_upload_limit]),
-          background: Config.get([:instance, :background_upload_limit])
-        },
-        fieldsLimits: %{
-          maxFields: Config.get([:instance, :max_account_fields]),
-          maxRemoteFields: Config.get([:instance, :max_remote_account_fields]),
-          nameLength: Config.get([:instance, :account_field_name_length]),
-          valueLength: Config.get([:instance, :account_field_value_length])
-        },
-        accountActivationRequired: Config.get([:instance, :account_activation_required], false),
-        invitesEnabled: Config.get([:instance, :invites_enabled], false),
-        mailerEnabled: Config.get([Pleroma.Emails.Mailer, :enabled], false),
-        features: features,
-        restrictedNicknames: Config.get([Pleroma.User, :restricted_nicknames]),
-        skipThreadContainment: Config.get([:instance, :skip_thread_containment], false),
-        localBubbleInstances: Config.get([:instance, :local_bubble], [])
-      }
-    }
-  end
-
   # Schema definition: https://github.com/jhass/nodeinfo/blob/master/schemas/2.0/schema.json
   # and https://github.com/jhass/nodeinfo/blob/master/schemas/2.1/schema.json
-  def nodeinfo(conn, %{"version" => "2.0"}) do
+  def nodeinfo(conn, %{"version" => version}) when version in ["2.0", "2.1"] do
     conn
     |> put_resp_header(
       "content-type",
       "application/json; profile=http://nodeinfo.diaspora.software/ns/schema/2.0#; charset=utf-8"
     )
-    |> json(raw_nodeinfo())
-  end
-
-  def nodeinfo(conn, %{"version" => "2.1"}) do
-    raw_response = raw_nodeinfo()
-
-    updated_software =
-      raw_response
-      |> Map.get(:software)
-      |> Map.put(:repository, Pleroma.Application.repository())
-
-    response =
-      raw_response
-      |> Map.put(:software, updated_software)
-      |> Map.put(:version, "2.1")
-
-    conn
-    |> put_resp_header(
-      "content-type",
-      "application/json; profile=http://nodeinfo.diaspora.software/ns/schema/2.1#; charset=utf-8"
-    )
-    |> json(response)
+    |> json(Nodeinfo.get_nodeinfo(version))
   end
 
   def nodeinfo(conn, _) do
index 7731d847f6e0a3f9570266d574dd69e57debcfa9..95a22895e547a1aca24c39759c91955c249b4826 100644 (file)
@@ -36,7 +36,7 @@ defmodule Pleroma.Web.OStatus.OStatusController 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)},
+           {:activity, Activity.get_local_create_by_object_ap_id(id)},
          {_, true} <- {:public?, Visibility.is_public?(activity)},
          {_, false} <- {:local_public?, Visibility.is_local_public?(activity)} do
       redirect(conn, to: "/notice/#{activity.id}")
index faaf3d67979b409c2224d85a99c6b62588bb6cbc..24ca5c37bffde89f9f81f9fd893ebb12ceb5fae1 100644 (file)
@@ -598,7 +598,6 @@ defmodule Pleroma.Web.Router do
     get("/timelines/home", TimelineController, :home)
     get("/timelines/direct", TimelineController, :direct)
     get("/timelines/list/:list_id", TimelineController, :list)
-    get("/timelines/bubble", TimelineController, :bubble)
 
     get("/announcements", AnnouncementController, :index)
     post("/announcements/:id/dismiss", AnnouncementController, :mark_read)
@@ -653,6 +652,7 @@ defmodule Pleroma.Web.Router do
 
     get("/timelines/public", TimelineController, :public)
     get("/timelines/tag/:tag", TimelineController, :hashtag)
+    get("/timelines/bubble", TimelineController, :bubble)
 
     get("/polls/:id", PollController, :show)
 
index 369d1ed252d16a1e42b6f1abfa54b32ba68be972..bee2c15857260796be5f54b0bef0e9d2ae0bf0ad 100644 (file)
--- a/mix.lock
+++ b/mix.lock
@@ -27,7 +27,7 @@
   "earmark": {:hex, :earmark, "1.4.37", "56ce845c543393aa3f9b294c818c3d783452a4a67e4ab18c4303a954a8b59363", [:mix], [{:earmark_parser, "~> 1.4.31", [hex: :earmark_parser, repo: "hexpm", optional: false]}], "hexpm", "d86d5e12868db86d5321b00e62a4bbcb4150346e4acc9a90a041fb188a5cb106"},
   "earmark_parser": {:hex, :earmark_parser, "1.4.31", "a93921cdc6b9b869f519213d5bc79d9e218ba768d7270d46fdcf1c01bacff9e2", [:mix], [], "hexpm", "317d367ee0335ef037a87e46c91a2269fef6306413f731e8ec11fc45a7efd059"},
   "eblurhash": {:hex, :eblurhash, "1.2.2", "7da4255aaea984b31bb71155f673257353b0e0554d0d30dcf859547e74602582", [:rebar3], [], "hexpm", "8c20ca00904de023a835a9dcb7b7762fed32264c85a80c3cafa85288e405044c"},
-  "ecto": {:hex, :ecto, "3.9.4", "3ee68e25dbe0c36f980f1ba5dd41ee0d3eb0873bccae8aeaf1a2647242bffa35", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "de5f988c142a3aa4ec18b85a4ec34a2390b65b24f02385c1144252ff6ff8ee75"},
+  "ecto": {:hex, :ecto, "3.9.5", "9f0aa7ae44a1577b651c98791c6988cd1b69b21bc724e3fd67090b97f7604263", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d4f3115d8cbacdc0bfa4b742865459fb1371d0715515842a1fb17fe31920b74c"},
   "ecto_enum": {:hex, :ecto_enum, "1.4.0", "d14b00e04b974afc69c251632d1e49594d899067ee2b376277efd8233027aec8", [:mix], [{:ecto, ">= 3.0.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:ecto_sql, "> 3.0.0", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:mariaex, ">= 0.0.0", [hex: :mariaex, repo: "hexpm", optional: true]}, {:postgrex, ">= 0.0.0", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm", "8fb55c087181c2b15eee406519dc22578fa60dd82c088be376d0010172764ee4"},
   "ecto_psql_extras": {:hex, :ecto_psql_extras, "0.7.10", "e14d400930f401ca9f541b3349212634e44027d7f919bbb71224d7ac0d0e8acd", [:mix], [{:ecto_sql, "~> 3.4", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.15.7 or ~> 0.16.0", [hex: :postgrex, repo: "hexpm", optional: false]}, {:table_rex, "~> 3.1.1", [hex: :table_rex, repo: "hexpm", optional: false]}], "hexpm", "505e8cd81e4f17c090be0f99e92b1b3f0fd915f98e76965130b8ccfb891e7088"},
   "ecto_sql": {:hex, :ecto_sql, "3.9.2", "34227501abe92dba10d9c3495ab6770e75e79b836d114c41108a4bf2ce200ad5", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.9.2", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.6.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.16.0 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "1eb5eeb4358fdbcd42eac11c1fbd87e3affd7904e639d77903c1358b2abd3f70"},
@@ -38,7 +38,7 @@
   "ex_aws": {:hex, :ex_aws, "2.1.9", "dc4865ecc20a05190a34a0ac5213e3e5e2b0a75a0c2835e923ae7bfeac5e3c31", [:mix], [{:configparser_ex, "~> 4.0", [hex: :configparser_ex, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:jsx, "~> 3.0", [hex: :jsx, repo: "hexpm", optional: true]}, {:sweet_xml, "~> 0.6", [hex: :sweet_xml, repo: "hexpm", optional: true]}], "hexpm", "3e6c776703c9076001fbe1f7c049535f042cb2afa0d2cbd3b47cbc4e92ac0d10"},
   "ex_aws_s3": {:hex, :ex_aws_s3, "2.4.0", "ce8decb6b523381812798396bc0e3aaa62282e1b40520125d1f4eff4abdff0f4", [:mix], [{:ex_aws, "~> 2.0", [hex: :ex_aws, repo: "hexpm", optional: false]}, {:sweet_xml, ">= 0.0.0", [hex: :sweet_xml, repo: "hexpm", optional: true]}], "hexpm", "85dda6e27754d94582869d39cba3241d9ea60b6aa4167f9c88e309dc687e56bb"},
   "ex_const": {:hex, :ex_const, "0.2.4", "d06e540c9d834865b012a17407761455efa71d0ce91e5831e86881b9c9d82448", [:mix], [], "hexpm", "96fd346610cc992b8f896ed26a98be82ac4efb065a0578f334a32d60a3ba9767"},
-  "ex_doc": {:hex, :ex_doc, "0.29.2", "dfa97532ba66910b2a3016a4bbd796f41a86fc71dd5227e96f4c8581fdf0fdf0", [:mix], [{:earmark_parser, "~> 1.4.19", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "6b5d7139eda18a753e3250e27e4a929f8d2c880dd0d460cb9986305dea3e03af"},
+  "ex_doc": {:hex, :ex_doc, "0.29.3", "f07444bcafb302db86e4f02d8bbcd82f2e881a0dcf4f3e4740e4b8128b9353f7", [:mix], [{:earmark_parser, "~> 1.4.31", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "3dc6787d7b08801ec3b51e9bd26be5e8826fbf1a17e92d1ebc252e1a1c75bfe1"},
   "ex_machina": {:hex, :ex_machina, "2.7.0", "b792cc3127fd0680fecdb6299235b4727a4944a09ff0fa904cc639272cd92dc7", [:mix], [{:ecto, "~> 2.2 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_sql, "~> 3.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}], "hexpm", "419aa7a39bde11894c87a615c4ecaa52d8f107bbdd81d810465186f783245bf8"},
   "ex_syslogger": {:hex, :ex_syslogger, "1.5.2", "72b6aa2d47a236e999171f2e1ec18698740f40af0bd02c8c650bf5f1fd1bac79", [:mix], [{:poison, ">= 1.5.0", [hex: :poison, repo: "hexpm", optional: true]}, {:syslog, "~> 1.1.0", [hex: :syslog, repo: "hexpm", optional: false]}], "hexpm", "ab9fab4136dbc62651ec6f16fa4842f10cf02ab4433fa3d0976c01be99398399"},
   "excoveralls": {:hex, :excoveralls, "0.15.1", "83c8cf7973dd9d1d853dce37a2fb98aaf29b564bf7d01866e409abf59dac2c0e", [:mix], [{:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "f8416bd90c0082d56a2178cf46c837595a06575f70a5624f164a1ffe37de07e7"},
   "phoenix_ecto": {:hex, :phoenix_ecto, "4.4.0", "0672ed4e4808b3fbed494dded89958e22fb882de47a97634c0b13e7b0b5f7720", [:mix], [{:ecto, "~> 3.3", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "09864e558ed31ee00bd48fcc1d4fc58ae9678c9e81649075431e69dbabb43cc1"},
   "phoenix_html": {:hex, :phoenix_html, "3.3.1", "4788757e804a30baac6b3fc9695bf5562465dd3f1da8eb8460ad5b404d9a2178", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "bed1906edd4906a15fd7b412b85b05e521e1f67c9a85418c55999277e553d0d3"},
   "phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.7.2", "97cc4ff2dba1ebe504db72cb45098cb8e91f11160528b980bd282cc45c73b29c", [:mix], [{:ecto, "~> 3.6.2 or ~> 3.7", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_mysql_extras, "~> 0.5", [hex: :ecto_mysql_extras, repo: "hexpm", optional: true]}, {:ecto_psql_extras, "~> 0.7", [hex: :ecto_psql_extras, repo: "hexpm", optional: true]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.18.3", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6 or ~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "0e5fdf063c7a3b620c566a30fcf68b7ee02e5e46fe48ee46a6ec3ba382dc05b7"},
-  "phoenix_live_view": {:hex, :phoenix_live_view, "0.18.17", "74938b02f3c531bed3f87fe1ea39af6b5b2d26ab1405e77e76b8ef5df9ffa8a1", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.15 or ~> 1.7.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.3", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "f4b5710e19a29b8dc93b7af4bab4739c067a3cb759af01ffc3057165453dce38"},
+  "phoenix_live_view": {:hex, :phoenix_live_view, "0.18.18", "1f38fbd7c363723f19aad1a04b5490ff3a178e37daaf6999594d5f34796c47fc", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.15 or ~> 1.7.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.3", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a5810d0472f3189ede6d2a95bda7f31c6113156b91784a3426cb0ab6a6d85214"},
   "phoenix_pubsub": {:hex, :phoenix_pubsub, "2.1.1", "ba04e489ef03763bf28a17eb2eaddc2c20c6d217e2150a61e3298b0f4c2012b5", [:mix], [], "hexpm", "81367c6d1eea5878ad726be80808eb5a787a23dee699f96e72b1109c57cdd8d9"},
   "phoenix_swoosh": {:hex, :phoenix_swoosh, "0.3.4", "615f8f393135de7e0cbb4bd00ba238b1e0cd324b0d90efbaee613c2f02ca5e5c", [:mix], [{:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:swoosh, "~> 1.0", [hex: :swoosh, repo: "hexpm", optional: false]}], "hexpm", "3971221846232021ab5e3c7489fd62ec5bfd6a2e01cae10a317ccf6fb350571c"},
   "phoenix_template": {:hex, :phoenix_template, "1.0.1", "85f79e3ad1b0180abb43f9725973e3b8c2c3354a87245f91431eec60553ed3ef", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "157dc078f6226334c91cb32c1865bf3911686f8bcd6bcff86736f6253e6993ee"},
   "phoenix_view": {:hex, :phoenix_view, "2.0.2", "6bd4d2fd595ef80d33b439ede6a19326b78f0f1d8d62b9a318e3d9c1af351098", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}], "hexpm", "a929e7230ea5c7ee0e149ffcf44ce7cf7f4b6d2bfe1752dd7c084cdff152d36f"},
-  "plug": {:hex, :plug, "1.14.0", "ba4f558468f69cbd9f6b356d25443d0b796fbdc887e03fa89001384a9cac638f", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "bf020432c7d4feb7b3af16a0c2701455cbbbb95e5b6866132cb09eb0c29adc14"},
-  "plug_cowboy": {:hex, :plug_cowboy, "2.6.0", "d1cf12ff96a1ca4f52207c5271a6c351a4733f413803488d75b70ccf44aebec2", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "073cf20b753ce6682ed72905cd62a2d4bd9bad1bf9f7feb02a1b8e525bd94fa6"},
-  "plug_crypto": {:hex, :plug_crypto, "1.2.4", "34c380ef387cc7e8d537854ddd4b7096c79a4397d53587cb80419c782b03fdbc", [:mix], [], "hexpm", "4de415f03faec94d9da9be8c12cb51e9c98cbf66d732b6df669d4562d8e91acc"},
+  "plug": {:hex, :plug, "1.14.2", "cff7d4ec45b4ae176a227acd94a7ab536d9b37b942c8e8fa6dfc0fff98ff4d80", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "842fc50187e13cf4ac3b253d47d9474ed6c296a8732752835ce4a86acdf68d13"},
+  "plug_cowboy": {:hex, :plug_cowboy, "2.6.1", "9a3bbfceeb65eff5f39dab529e5cd79137ac36e913c02067dba3963a26efe9b2", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "de36e1a21f451a18b790f37765db198075c25875c64834bcc82d90b309eb6613"},
+  "plug_crypto": {:hex, :plug_crypto, "1.2.5", "918772575e48e81e455818229bf719d4ab4181fcbf7f85b68a35620f78d89ced", [:mix], [], "hexpm", "26549a1d6345e2172eb1c233866756ae44a9609bd33ee6f99147ab3fd87fd842"},
   "plug_static_index_html": {:hex, :plug_static_index_html, "1.0.0", "840123d4d3975585133485ea86af73cb2600afd7f2a976f9f5fd8b3808e636a0", [:mix], [{:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "79fd4fcf34d110605c26560cbae8f23c603ec4158c08298bd4360fdea90bb5cf"},
   "poison": {:hex, :poison, "5.0.0", "d2b54589ab4157bbb82ec2050757779bfed724463a544b6e20d79855a9e43b24", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "11dc6117c501b80c62a7594f941d043982a1bd05a1184280c0d9166eb4d8d3fc"},
   "poolboy": {:hex, :poolboy, "1.5.2", "392b007a1693a64540cead79830443abf5762f5d30cf50bc95cb2c1aaafa006b", [:rebar3], [], "hexpm", "dad79704ce5440f3d5a3681c8590b9dc25d1a561e8f5a9c995281012860901e3"},
   "telemetry_poller": {:hex, :telemetry_poller, "0.5.1", "21071cc2e536810bac5628b935521ff3e28f0303e770951158c73eaaa01e962a", [:rebar3], [{:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "4cab72069210bc6e7a080cec9afffad1b33370149ed5d379b81c7c5f0c663fd4"},
   "temple": {:git, "https://akkoma.dev/AkkomaGang/temple.git", "066a699ade472d8fa42a9d730b29a61af9bc8b59", [ref: "066a699ade472d8fa42a9d730b29a61af9bc8b59"]},
   "tesla": {:hex, :tesla, "1.4.4", "bb89aa0c9745190930366f6a2ac612cdf2d0e4d7fff449861baa7875afd797b2", [:mix], [{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: true]}, {:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:finch, "~> 0.3", [hex: :finch, repo: "hexpm", optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]}, {:gun, "~> 1.3", [hex: :gun, repo: "hexpm", optional: true]}, {:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "4.4.0", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "d5503a49f9dec1b287567ea8712d085947e247cb11b06bc54adb05bfde466457"},
-  "timex": {:hex, :timex, "3.7.9", "790cdfc4acfce434e442f98c02ea6d84d0239073bfd668968f82ac63e9a6788d", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.10", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 1.1", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "64691582e5bb87130f721fc709acfb70f24405833998fabf35be968984860ce1"},
+  "timex": {:hex, :timex, "3.7.11", "bb95cb4eb1d06e27346325de506bcc6c30f9c6dea40d1ebe390b262fad1862d1", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.20", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 1.1", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "8b9024f7efbabaf9bd7aa04f65cf8dcd7c9818ca5737677c7b76acbc6a94d1aa"},
   "trailing_format_plug": {:hex, :trailing_format_plug, "0.0.7", "64b877f912cf7273bed03379936df39894149e35137ac9509117e59866e10e45", [:mix], [{:plug, "> 0.12.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "bd4fde4c15f3e993a999e019d64347489b91b7a9096af68b2bdadd192afa693f"},
   "tzdata": {:hex, :tzdata, "1.1.1", "20c8043476dfda8504952d00adac41c6eda23912278add38edc140ae0c5bcc46", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "a69cec8352eafcd2e198dea28a34113b60fdc6cb57eb5ad65c10292a6ba89787"},
   "ueberauth": {:hex, :ueberauth, "0.10.5", "806adb703df87e55b5615cf365e809f84c20c68aa8c08ff8a416a5a6644c4b02", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "3efd1f31d490a125c7ed453b926f7c31d78b97b8a854c755f5c40064bf3ac9e1"},
diff --git a/priv/static/emoji/hehe.png b/priv/static/emoji/hehe.png
new file mode 100644 (file)
index 0000000..c02592d
Binary files /dev/null and b/priv/static/emoji/hehe.png differ
diff --git a/priv/static/emoji/nothehe.png b/priv/static/emoji/nothehe.png
new file mode 100644 (file)
index 0000000..427bb6d
Binary files /dev/null and b/priv/static/emoji/nothehe.png differ
index a590946c215ea2d3781b75b76ec1028a50945923..12ccc6bf4aa3a2c207f1fa1703ceaa97f695551c 100644 (file)
@@ -2509,6 +2509,16 @@ defmodule Pleroma.UserTest do
     assert User.avatar_url(user, no_default: true) == nil
   end
 
+  test "avatar object with nil in href" do
+    user = insert(:user, avatar: %{"url" => [%{"href" => nil}]})
+    assert User.avatar_url(user) != nil
+  end
+
+  test "banner object with nil in href" do
+    user = insert(:user, banner: %{"url" => [%{"href" => nil}]})
+    assert User.banner_url(user) != nil
+  end
+
   test "get_host/1" do
     user = insert(:user, ap_id: "https://lain.com/users/lain", nickname: "lain")
     assert User.get_host(user) == "lain.com"
index 17c52fc912354a460665445a8860533c05cf8acc..e95e4490aa57da984517bcf744a1f8d2ef3d5e1e 100644 (file)
@@ -1303,6 +1303,14 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
       %{test_file: test_file}
     end
 
+    test "strips / from filename", %{test_file: file} do
+      file = %Plug.Upload{file | filename: "../../../../../nested/bad.jpg"}
+      {:ok, %Object{} = object} = ActivityPub.upload(file)
+      [%{"href" => href}] = object.data["url"]
+      assert Regex.match?(~r"/bad.jpg$", href)
+      refute Regex.match?(~r"/nested/", href)
+    end
+
     test "sets a description if given", %{test_file: file} do
       {:ok, %Object{} = object} = ActivityPub.upload(file, description: "a cool file")
       assert object.data["name"] == "a cool file"
index 50b9febead639757f117d1c925f6169beb8667c4..7ff8cff6bd0b9e67400986c5a3cc1fa5449745f7 100644 (file)
@@ -124,6 +124,23 @@ defmodule Pleroma.Web.MastodonAPI.MediaControllerTest do
 
       assert :ok == File.rm(Path.absname("test/tmp/large_binary.data"))
     end
+
+    test "Do not allow nested filename", %{conn: conn, image: image} do
+      image = %Plug.Upload{
+        image
+        | filename: "../../../../../nested/file.jpg"
+      }
+
+      desc = "Description of the image"
+
+      media =
+        conn
+        |> put_req_header("content-type", "multipart/form-data")
+        |> post("/api/v1/media", %{"file" => image, "description" => desc})
+        |> json_response_and_validate_schema(:ok)
+
+      refute Regex.match?(~r"/nested/", media["url"])
+    end
   end
 
   describe "Update media description" do
index aa9006681823441f93c963028078910c9a8701cd..fcc7a204eb58b429d7afd4246ded0a7d30cc59dc 100644 (file)
@@ -408,6 +408,26 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
 
       assert [] = result
     end
+
+    test "should return 404 if disabled" do
+      clear_config([:instance, :federated_timeline_available], false)
+
+      result =
+        build_conn()
+        |> get("/api/v1/timelines/public")
+        |> json_response_and_validate_schema(404)
+
+      assert %{"error" => "Federated timeline is disabled"} = result
+    end
+
+    test "should not return 404 if local is specified" do
+      clear_config([:instance, :federated_timeline_available], false)
+
+      result =
+        build_conn()
+        |> get("/api/v1/timelines/public?local=true")
+        |> json_response_and_validate_schema(200)
+    end
   end
 
   defp local_and_remote_activities do
@@ -1036,9 +1056,8 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
   end
 
   describe "bubble" do
-    setup do: oauth_access(["read:statuses"])
-
-    test "filtering", %{conn: conn, user: user} do
+    test "filtering" do
+      %{conn: conn, user: user} = oauth_access(["read:statuses"])
       clear_config([:instance, :local_bubble], [])
       # our endpoint host has a port in it so let's set the AP ID
       local_user = insert(:user, %{ap_id: "https://localhost/users/user"})
@@ -1060,7 +1079,7 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
 
       assert local_activity.id in one_instance
 
-      # If we have others, also include theirs 
+      # If we have others, also include theirs
       clear_config([:instance, :local_bubble], ["example.com"])
 
       two_instances =
@@ -1072,6 +1091,20 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
       assert local_activity.id in two_instances
       assert remote_activity.id in two_instances
     end
+
+    test "restrict_unauthenticated with bubble timeline", %{conn: conn} do
+      clear_config([:restrict_unauthenticated, :timelines, :bubble], true)
+
+      conn
+      |> get("/api/v1/timelines/bubble")
+      |> json_response_and_validate_schema(:unauthorized)
+
+      clear_config([:restrict_unauthenticated, :timelines, :bubble], false)
+
+      conn
+      |> get("/api/v1/timelines/bubble")
+      |> json_response_and_validate_schema(200)
+    end
   end
 
   defp create_remote_activity(user) do
index e9b8825bfb7801f7c5507175ecb2fb9b82dbbf31..4aec31eacd07088edde803686b2ea9c86c7c3a8a 100644 (file)
@@ -396,6 +396,34 @@ defmodule Pleroma.Web.MastodonAPI.UpdateCredentialsTest do
       assert :ok == File.rm(Path.absname("test/tmp/large_binary.data"))
     end
 
+    test "Strip / from upload files", %{user: user, conn: conn} do
+      new_image = %Plug.Upload{
+        content_type: "image/jpeg",
+        path: Path.absname("test/fixtures/image.jpg"),
+        filename: "../../../../nested/an_image.jpg"
+      }
+
+      assert user.avatar == %{}
+
+      res =
+        patch(conn, "/api/v1/accounts/update_credentials", %{
+          "avatar" => new_image,
+          "header" => new_image,
+          "pleroma_background_image" => new_image
+        })
+
+      assert user_response = json_response_and_validate_schema(res, 200)
+      assert user_response["avatar"]
+      assert user_response["header"]
+      assert user_response["pleroma"]["background_image"]
+      refute Regex.match?(~r"/nested/", user_response["avatar"])
+      refute Regex.match?(~r"/nested/", user_response["header"])
+      refute Regex.match?(~r"/nested/", user_response["pleroma"]["background_image"])
+
+      user = User.get_by_id(user.id)
+      refute user.avatar == %{}
+    end
+
     test "requires 'write:accounts' permission" do
       token1 = insert(:oauth_token, scopes: ["read"])
       token2 = insert(:oauth_token, scopes: ["write", "follow"])
index c9036d67d225165ddde7bc08572412c3be162b0d..6ef89f7998136e137b436f1a9e76ed6ef360b3d6 100644 (file)
@@ -269,8 +269,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
     }
 
     with_mock(
-      Pleroma.Web.Nodeinfo.NodeinfoController,
-      raw_nodeinfo: fn -> %{version: "2.0"} end
+      Pleroma.Web.Nodeinfo.Nodeinfo,
+      get_nodeinfo: fn _ -> %{version: "2.0"} end
     ) do
       assert expected ==
                AccountView.render("show.json", %{user: user, skip_visibility_check: true})
index 05a078266c1d41d950f09653a4e37a0fa10de9e1..ff14db4607f50bce7603024afbfd6a406d6f615a 100644 (file)
@@ -292,4 +292,38 @@ defmodule Pleroma.Web.NodeInfoTest do
       assert response["metadata"]["federation"]["mrf_simple_info"] == expected_config
     end
   end
+
+  describe "public timeline visibility" do
+    test "shows public timeline visibility", %{conn: conn} do
+      clear_config([:restrict_unauthenticated, :timelines], %{local: false, federated: false})
+
+      response =
+        conn
+        |> get("/nodeinfo/2.1.json")
+        |> json_response(:ok)
+
+      assert response["metadata"]["publicTimelineVisibility"]["local"] == true
+      assert response["metadata"]["publicTimelineVisibility"]["federated"] == true
+
+      clear_config([:restrict_unauthenticated, :timelines], %{local: true, federated: false})
+
+      response =
+        conn
+        |> get("/nodeinfo/2.1.json")
+        |> json_response(:ok)
+
+      assert response["metadata"]["publicTimelineVisibility"]["local"] == false
+      assert response["metadata"]["publicTimelineVisibility"]["federated"] == true
+
+      clear_config([:restrict_unauthenticated, :timelines], %{local: false, federated: true})
+
+      response =
+        conn
+        |> get("/nodeinfo/2.1.json")
+        |> json_response(:ok)
+
+      assert response["metadata"]["publicTimelineVisibility"]["local"] == true
+      assert response["metadata"]["publicTimelineVisibility"]["federated"] == false
+    end
+  end
 end