diff options
66 files changed, 861 insertions, 421 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e65cae9d8..fd0c5c8d4 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -198,7 +198,7 @@ amd64:    variables: &release-variables      MIX_ENV: prod    before_script: &before-release -  - apt-get update && apt-get install -y cmake +  - apt-get update && apt-get install -y cmake libmagic-dev    - echo "import Mix.Config" > config/prod.secret.exs    - mix local.hex --force    - mix local.rebar --force @@ -217,7 +217,7 @@ amd64-musl:    cache: *release-cache    variables: *release-variables    before_script: &before-release-musl -  - apk add git gcc g++ musl-dev make cmake +  - apk add git gcc g++ musl-dev make cmake file-dev    - echo "import Mix.Config" > config/prod.secret.exs    - mix local.hex --force    - mix local.rebar --force diff --git a/CHANGELOG.md b/CHANGELOG.md index 41f0a4402..5f6e1fe8d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,12 +13,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).  - Pleroma API: Importing the mutes users from CSV files.  - Experimental websocket-based federation between Pleroma instances.  - Support pagination of blocks and mutes +- App metrics: ability to restrict access to specified IP whitelist. +- Configuration: Add `:instance, autofollowing_nicknames` setting to provide a way to make accounts automatically follow new users that register on the local Pleroma instance.  ### Changed  - **Breaking** Requires `libmagic` (or `file`) to guess file types.  - **Breaking:** Pleroma Admin API: emoji packs and files routes changed.  - **Breaking:** Sensitive/NSFW statuses no longer disable link previews. +- **Breaking:** App metrics endpoint (`/api/pleroma/app_metrics`) is disabled by default, check `docs/API/prometheus.md` on enabling and configuring.   - Search: Users are now findable by their urls.  - Renamed `:await_up_timeout` in `:connections_pool` namespace to `:connect_timeout`, old name is deprecated.  - Renamed `:timeout` in `pools` namespace to `:recv_timeout`, old name is deprecated. @@ -48,6 +51,9 @@ switched to a new configuration mechanism, however it was not officially removed  - Add documented-but-missing chat pagination.  - Allow sending out emails again. +- Allow sending chat messages to yourself. +- Fix remote users with a whitespace name. +- OStatus / static FE endpoints: fixed inaccessibility for anonymous users on non-federating instances, switched to handling per `:restrict_unauthenticated` setting.  ## Unreleased (Patch) diff --git a/config/config.exs b/config/config.exs index 2c6142360..c52ee8f82 100644 --- a/config/config.exs +++ b/config/config.exs @@ -123,7 +123,6 @@ websocket_config = [  # Configures the endpoint  config :pleroma, Pleroma.Web.Endpoint, -  instrumenters: [Pleroma.Web.Endpoint.Instrumenter],    url: [host: "localhost"],    http: [      ip: {127, 0, 0, 1}, @@ -143,7 +142,7 @@ config :pleroma, Pleroma.Web.Endpoint,    secret_key_base: "aK4Abxf29xU9TTDKre9coZPUgevcVCFQJe/5xP/7Lt4BEif6idBIbjupVbOrbKxl",    signing_salt: "CqaoopA2",    render_errors: [view: Pleroma.Web.ErrorView, accepts: ~w(json)], -  pubsub: [name: Pleroma.PubSub, adapter: Phoenix.PubSub.PG2], +  pubsub_server: Pleroma.PubSub,    secure_cookie_flag: true,    extra_cookie_attrs: [      "SameSite=Lax" @@ -235,6 +234,7 @@ config :pleroma, :instance,      "text/bbcode"    ],    autofollowed_nicknames: [], +  autofollowing_nicknames: [],    max_pinned_statuses: 1,    attachment_links: false,    max_report_comment_size: 1000, @@ -636,7 +636,12 @@ config :pleroma, Pleroma.Emails.UserEmail,  config :pleroma, Pleroma.Emails.NewUsersDigestEmail, enabled: false -config :prometheus, Pleroma.Web.Endpoint.MetricsExporter, path: "/api/pleroma/app_metrics" +config :prometheus, Pleroma.Web.Endpoint.MetricsExporter, +  enabled: false, +  auth: false, +  ip_whitelist: [], +  path: "/api/pleroma/app_metrics", +  format: :text  config :pleroma, Pleroma.ScheduledActivity,    daily_user_limit: 25, diff --git a/config/description.exs b/config/description.exs index 2a1898922..0bfa9979f 100644 --- a/config/description.exs +++ b/config/description.exs @@ -829,13 +829,13 @@ config :pleroma, :config_description, [          key: :autofollowed_nicknames,          type: {:list, :string},          description: -          "Set to nicknames of (local) users that every new user should automatically follow", -        suggestions: [ -          "lain", -          "kaniini", -          "lanodan", -          "rinpatch" -        ] +          "Set to nicknames of (local) users that every new user should automatically follow" +      }, +      %{ +        key: :autofollowing_nicknames, +        type: {:list, :string}, +        description: +          "Set to nicknames of (local) users that automatically follows every newly registered user"        },        %{          key: :attachment_links, @@ -3722,5 +3722,42 @@ config :pleroma, :config_description, [          suggestions: [2]        }      ] +  }, +  %{ +    group: :prometheus, +    key: Pleroma.Web.Endpoint.MetricsExporter, +    type: :group, +    description: "Prometheus app metrics endpoint configuration", +    children: [ +      %{ +        key: :enabled, +        type: :boolean, +        description: "[Pleroma extension] Enables app metrics endpoint." +      }, +      %{ +        key: :ip_whitelist, +        type: [{:list, :string}, {:list, :charlist}, {:list, :tuple}], +        description: +          "[Pleroma extension] If non-empty, restricts access to app metrics endpoint to specified IP addresses." +      }, +      %{ +        key: :auth, +        type: [:boolean, :tuple], +        description: "Enables HTTP Basic Auth for app metrics endpoint.", +        suggestion: [false, {:basic, "myusername", "mypassword"}] +      }, +      %{ +        key: :path, +        type: :string, +        description: "App metrics endpoint URI path.", +        suggestions: ["/api/pleroma/app_metrics"] +      }, +      %{ +        key: :format, +        type: :atom, +        description: "App metrics endpoint output format.", +        suggestions: [:text, :protobuf] +      } +    ]    }  ] diff --git a/docs/API/prometheus.md b/docs/API/prometheus.md index 19c564e3c..a5158d905 100644 --- a/docs/API/prometheus.md +++ b/docs/API/prometheus.md @@ -2,15 +2,37 @@  Pleroma includes support for exporting metrics via the [prometheus_ex](https://github.com/deadtrickster/prometheus.ex) library. +Config example: + +``` +config :prometheus, Pleroma.Web.Endpoint.MetricsExporter, +  enabled: true, +  auth: {:basic, "myusername", "mypassword"}, +  ip_whitelist: ["127.0.0.1"], +  path: "/api/pleroma/app_metrics", +  format: :text +``` + +* `enabled` (Pleroma extension) enables the endpoint +* `ip_whitelist` (Pleroma extension) could be used to restrict access only to specified IPs +* `auth` sets the authentication (`false` for no auth; configurable to HTTP Basic Auth, see [prometheus-plugs](https://github.com/deadtrickster/prometheus-plugs#exporting) documentation) +* `format` sets the output format (`:text` or `:protobuf`) +* `path` sets the path to app metrics page  + +  ## `/api/pleroma/app_metrics` +  ### Exports Prometheus application metrics +  * Method: `GET` -* Authentication: not required +* Authentication: not required by default (see configuration options above)  * Params: none -* Response: JSON +* Response: text  ## Grafana +  ### Config example +  The following is a config example to use with [Grafana](https://grafana.com)  ``` diff --git a/docs/ap_extensions.md b/docs/ap_extensions.md index c4550a1ac..3d1caeb3e 100644 --- a/docs/ap_extensions.md +++ b/docs/ap_extensions.md @@ -1,11 +1,41 @@ -# ChatMessages +# AP Extensions +## Actor endpoints -ChatMessages are the messages sent in 1-on-1 chats. They are similar to +The following endpoints are additionally present into our actors. + +- `oauthRegistrationEndpoint` (`http://litepub.social/ns#oauthRegistrationEndpoint`) +- `uploadMedia` (`https://www.w3.org/ns/activitystreams#uploadMedia`) + +### oauthRegistrationEndpoint + +Points to MastodonAPI `/api/v1/apps` for now. + +See <https://docs.joinmastodon.org/methods/apps/> + +### uploadMedia + +Inspired by <https://www.w3.org/wiki/SocialCG/ActivityPub/MediaUpload>, it is part of the ActivityStreams namespace because it used to be part of the ActivityPub specification and got removed from it. + +Content-Type: multipart/form-data + +Parameters: +- (required) `file`: The file being uploaded +- (optionnal) `description`: A plain-text description of the media, for accessibility purposes. + +Response: HTTP 201 Created with the object into the body, no `Location` header provided as it doesn't have an `id` + +The object given in the reponse should then be inserted into an Object's `attachment` field. + +## ChatMessages + +`ChatMessage`s are the messages sent in 1-on-1 chats. They are similar to  `Note`s, but the addresing is done by having a single AP actor in the `to`  field. Addressing multiple actors is not allowed. These messages are always  private, there is no public version of them. They are created with a `Create`  activity. +They are part of the `litepub` namespace as `http://litepub.social/ns#ChatMessage`. +  Example:  ```json diff --git a/docs/clients.md b/docs/clients.md index 1e2c14f1b..3d81763e1 100644 --- a/docs/clients.md +++ b/docs/clients.md @@ -7,97 +7,105 @@ Feel free to contact us to be added to this list!  - Homepage: <https://www.pleroma.com/#desktopApp>  - Source Code: <https://github.com/roma-apps/roma-desktop>  - Platforms: Windows, Mac, Linux -- Features: Streaming Ready +- Features: MastoAPI, Streaming Ready  ### Social  - Source Code: <https://gitlab.gnome.org/World/Social>  - Contact: [@brainblasted@social.libre.fi](https://social.libre.fi/users/brainblasted)  - Platforms: Linux (GNOME)  - Note(2019-01-28): Not at a pre-alpha stage yet +- Features: MastoAPI  ### Whalebird  - Homepage: <https://whalebird.org/>  - Source Code: <https://github.com/h3poteto/whalebird-desktop>  - Contact: [@h3poteto@pleroma.io](https://pleroma.io/users/h3poteto)  - Platforms: Windows, Mac, Linux -- Features: Streaming Ready +- Features: MastoAPI, Streaming Ready  ## Handheld +### AndStatus +- Homepage: <http://andstatus.org/> +- Source Code: <https://github.com/andstatus/andstatus/> +- Platforms: Android +- Features: MastoAPI, ActivityPub (Client-to-Server) +  ### Amaroq  - Homepage: <https://itunes.apple.com/us/app/amaroq-for-mastodon/id1214116200>  - Source Code: <https://github.com/ReticentJohn/Amaroq>  - Contact: [@eurasierboy@mastodon.social](https://mastodon.social/users/eurasierboy)  - Platforms: iOS -- Features: No Streaming +- Features: MastoAPI, No Streaming  ### Fedilab  - Homepage: <https://fedilab.app/>  - Source Code: <https://framagit.org/tom79/fedilab/>  - Contact: [@fedilab@framapiaf.org](https://framapiaf.org/users/fedilab)  - Platforms: Android -- Features: Streaming Ready, Moderation, Text Formatting +- Features: MastoAPI, Streaming Ready, Moderation, Text Formatting  ### Kyclos  - Source Code: <https://git.pleroma.social/pleroma/harbour-kyclos>  - Platforms: SailfishOS -- Features: No Streaming +- Features: MastoAPI, No Streaming  ### Husky  - Source code: <https://git.mentality.rip/FWGS/Husky>  - Contact: [@Husky@enigmatic.observer](https://enigmatic.observer/users/Husky)  - Platforms: Android -- Features: No Streaming, Emoji Reactions, Text Formatting, FE Stickers +- Features: MastoAPI, No Streaming, Emoji Reactions, Text Formatting, FE Stickers  ### Fedi  - Homepage: <https://www.fediapp.com/>  - Source Code: Proprietary, but gratis  - Platforms: iOS, Android -- Features: Pleroma-specific features like Reactions +- Features: MastoAPI, Pleroma-specific features like Reactions  ### Tusky  - Homepage: <https://tuskyapp.github.io/>  - Source Code: <https://github.com/tuskyapp/Tusky>  - Contact: [@ConnyDuck@mastodon.social](https://mastodon.social/users/ConnyDuck)  - Platforms: Android -- Features: No Streaming +- Features: MastoAPI, No Streaming  ### Twidere  - Homepage: <https://twidere.mariotaku.org/>  - Source Code: <https://github.com/TwidereProject/Twidere-Android/>  - Contact: <me@mariotaku.org>  - Platform: Android -- Features: No Streaming +- Features: MastoAPI, No Streaming  ### Indigenous  - Homepage: <https://indigenous.realize.be/>  - Source Code: <https://github.com/swentel/indigenous-android/>  - Contact: [@swentel@realize.be](https://realize.be)  - Platforms: Android -- Features: No Streaming +- Features: MastoAPI, No Streaming  ## Alternative Web Interfaces  ### Brutaldon  - Homepage: <https://jfm.carcosa.net/projects/software/brutaldon/>  - Source Code: <https://git.carcosa.net/jmcbray/brutaldon>  - Contact: [@gcupc@glitch.social](https://glitch.social/users/gcupc) -- Features: No Streaming +- Features: MastoAPI, No Streaming  ### Halcyon  - Source Code: <https://notabug.org/halcyon-suite/halcyon>  - Contact: [@halcyon@social.csswg.org](https://social.csswg.org/users/halcyon) -- Features: Streaming Ready +- Features: MastoAPI, Streaming Ready  ### Pinafore  - Homepage: <https://pinafore.social/>  - Source Code: <https://github.com/nolanlawson/pinafore>  - Contact: [@pinafore@mastodon.technology](https://mastodon.technology/users/pinafore)  - Note: Pleroma support is a secondary goal -- Features: No Streaming +- Features: MastoAPI, No Streaming  ### Sengi  - Homepage: <https://nicolasconstant.github.io/sengi/>  - Source Code: <https://github.com/NicolasConstant/sengi>  - Contact: [@sengi_app@mastodon.social](https://mastodon.social/users/sengi_app) +- Features: MastoAPI  ### DashFE  - Source Code: <https://notabug.org/daisuke/DashboardFE> @@ -107,3 +115,4 @@ Feel free to contact us to be added to this list!  - Source Code: <https://git.freesoftwareextremist.com/bloat/>  - Contact: [@r@freesoftwareextremist.com](https://freesoftwareextremist.com/users/r)  - Features: Does not requires JavaScript +- Features: MastoAPI diff --git a/docs/configuration/cheatsheet.md b/docs/configuration/cheatsheet.md index 0b13d7e88..f4b4b6c3c 100644 --- a/docs/configuration/cheatsheet.md +++ b/docs/configuration/cheatsheet.md @@ -45,6 +45,7 @@ To add configuration to your config file, you can copy it from the base config.      older software for theses nicknames.  * `max_pinned_statuses`: The maximum number of pinned statuses. `0` will disable the feature.  * `autofollowed_nicknames`: Set to nicknames of (local) users that every new user should automatically follow. +* `autofollowing_nicknames`: Set to nicknames of (local) users that automatically follows every newly registered user.  * `attachment_links`: Set to true to enable automatically adding attachment link text to statuses.  * `max_report_comment_size`: The maximum size of the report comment (Default: `1000`).  * `safe_dm_mentions`: If set to true, only mentions at the beginning of a post will be used to address people in direct messages. This is to prevent accidental mentioning of people when talking about them (e.g. "@friend hey i really don't like @enemy"). Default: `false`. diff --git a/docs/installation/otp_en.md b/docs/installation/otp_en.md index 676b10699..98360bcf7 100644 --- a/docs/installation/otp_en.md +++ b/docs/installation/otp_en.md @@ -43,7 +43,7 @@ Other than things bundled in the OTP release Pleroma depends on:  ### Installing optional packages -Per [`docs/installation/optional/media_graphics_packages.md`](docs/installation/optional/media_graphics_packages.md): +Per [`docs/installation/optional/media_graphics_packages.md`](optional/media_graphics_packages.md):    * ImageMagick    * ffmpeg    * exiftool diff --git a/installation/pleroma.service b/installation/pleroma.service index ee00a3b7a..63e83ed6e 100644 --- a/installation/pleroma.service +++ b/installation/pleroma.service @@ -31,8 +31,6 @@ ProtectHome=true  ProtectSystem=full  ; Sets up a new /dev mount for the process and only adds API pseudo devices like /dev/null, /dev/zero or /dev/random but not physical devices. Disabled by default because it may not work on devices like the Raspberry Pi.  PrivateDevices=false -; Ensures that the service process and all its children can never gain new privileges through execve(). -NoNewPrivileges=true  ; Drops the sysadmin capability from the daemon.  CapabilityBoundingSet=~CAP_SYS_ADMIN diff --git a/lib/phoenix/transports/web_socket/raw.ex b/lib/phoenix/transports/web_socket/raw.ex index aab7fad99..c3665bebe 100644 --- a/lib/phoenix/transports/web_socket/raw.ex +++ b/lib/phoenix/transports/web_socket/raw.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 handler.connect(%{ +               endpoint: endpoint, +               transport: transport, +               options: [serializer: nil], +               params: conn.params +             }) do            {:ok, socket} ->              {:ok, conn, {__MODULE__, {socket, opts}}} diff --git a/lib/pleroma/application.ex b/lib/pleroma/application.ex index 301b4e273..51e9dda3b 100644 --- a/lib/pleroma/application.ex +++ b/lib/pleroma/application.ex @@ -100,7 +100,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 @@ -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 @@ -202,11 +205,14 @@ defmodule Pleroma.Application do      ]    end -  defp chat_child(_env, true) do -    [Pleroma.Web.ChatChannel.ChatChannelState] +  defp chat_child(true) do +    [ +      Pleroma.Web.ChatChannel.ChatChannelState, +      {Phoenix.PubSub, [name: Pleroma.PubSub, adapter: Phoenix.PubSub.PG2]} +    ]    end -  defp chat_child(_, _), do: [] +  defp chat_child(_), do: []    defp task_children(:test) do      [ 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 <https://pleroma.social/> +# 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/user.ex b/lib/pleroma/user.ex index dc41d0001..a1e546b2d 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) @@ -765,6 +766,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 +785,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), diff --git a/lib/pleroma/web.ex b/lib/pleroma/web.ex index 7779826e3..6ed19d3dd 100644 --- a/lib/pleroma/web.ex +++ b/lib/pleroma/web.ex @@ -172,7 +172,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 diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index d17c892a7..13869f897 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -1378,6 +1378,7 @@ 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} diff --git a/lib/pleroma/web/activity_pub/activity_pub_controller.ex b/lib/pleroma/web/activity_pub/activity_pub_controller.ex index 570bcc7e7..31df80adb 100644 --- a/lib/pleroma/web/activity_pub/activity_pub_controller.ex +++ b/lib/pleroma/web/activity_pub/activity_pub_controller.ex @@ -414,7 +414,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(%{ @@ -458,7 +458,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 @@ -525,19 +525,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do      {new_user, for_user}    end -  @doc """ -  Endpoint based on <https://www.w3.org/wiki/SocialCG/ActivityPub/MediaUpload> - -  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( 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/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) diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index d7dd9fe6b..39c8f7e39 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,19 +314,21 @@ 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 -  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. @@ -927,7 +930,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 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/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(%{ 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: [] diff --git a/lib/pleroma/web/common_api/utils.ex b/lib/pleroma/web/common_api/utils.ex index 21f4d43e9..3b71adf0e 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/endpoint.ex b/lib/pleroma/web/endpoint.ex index 56562c12f..f26542e88 100644 --- a/lib/pleroma/web/endpoint.ex +++ b/lib/pleroma/web/endpoint.ex @@ -7,8 +7,12 @@ defmodule Pleroma.Web.Endpoint do    require Pleroma.Constants +  alias Pleroma.Config +    socket("/socket", Pleroma.Web.UserSocket) +  plug(Plug.Telemetry, event_prefix: [:phoenix, :endpoint]) +    plug(Pleroma.Web.Plugs.SetLocalePlug)    plug(CORSPlug)    plug(Pleroma.Web.Plugs.HTTPSecurityPlug) @@ -86,19 +90,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 +110,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 +120,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 +140,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) diff --git a/lib/pleroma/web/feed/tag_controller.ex b/lib/pleroma/web/feed/tag_controller.ex index 93a8294b7..218cdbdf3 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 +    if Config.get!([:instance, :public]) 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 = @@ -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 752983c3b..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 @@ -22,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.Web.Plugs.EnsureAuthenticatedPlug.call(conn, -             unless_func: &Pleroma.Web.Plugs.FederatingPlug.federating?/1 -           ) do -      ActivityPubController.call(conn, :user) -    end +    ActivityPubController.call(conn, :user)    end    def feed_redirect(conn, %{"nickname" => nickname}) do @@ -36,25 +32,18 @@ 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 - -  def render_feed(conn, %{"nickname" => nickname} = params) do +  def 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"        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"], @@ -69,7 +58,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 @@ -81,6 +70,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/mastodon_api/controllers/auth_controller.ex b/lib/pleroma/web/mastodon_api/controllers/auth_controller.ex index 75b809aab..9cc3984d0 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 08d6c1c22..6848adace 100644 --- a/lib/pleroma/web/mastodon_api/controllers/status_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/status_controller.ex @@ -127,9 +127,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}, @@ -160,11 +159,7 @@ 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]) diff --git a/lib/pleroma/web/media_proxy/invalidation/http.ex b/lib/pleroma/web/media_proxy/invalidation/http.ex index bb81d8888..0b0cde68c 100644 --- a/lib/pleroma/web/media_proxy/invalidation/http.ex +++ b/lib/pleroma/web/media_proxy/invalidation/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        _ -> diff --git a/lib/pleroma/web/o_status/o_status_controller.ex b/lib/pleroma/web/o_status/o_status_controller.ex index b044260b3..668ae0ea4 100644 --- a/lib/pleroma/web/o_status/o_status_controller.ex +++ b/lib/pleroma/web/o_status/o_status_controller.ex @@ -16,10 +16,6 @@ defmodule Pleroma.Web.OStatus.OStatusController do    alias Pleroma.Web.Plugs.RateLimiter    alias Pleroma.Web.Router -  plug(Pleroma.Web.Plugs.EnsureAuthenticatedPlug, -    unless_func: &Pleroma.Web.Plugs.FederatingPlug.federating?/1 -  ) -    plug(      RateLimiter,      [name: :ap_routes, params: ["uuid"]] when action in [:object, :activity] @@ -37,14 +33,12 @@ 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 +      redirect(conn, to: "/notice/#{activity.id}")      else        reason when reason in [{:public?, false}, {:activity, nil}] ->          {:error, :not_found} @@ -59,13 +53,11 @@ 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 +      redirect(conn, to: "/notice/#{activity.id}")      else        reason when reason in [{:public?, false}, {:activity, nil}] ->          {:error, :not_found} @@ -119,6 +111,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/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 diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index d2d939989..07a574f35 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -5,6 +5,26 @@  defmodule Pleroma.Web.Router do    use Pleroma.Web, :router +  pipeline :accepts_html 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 +    pipeline :browser do      plug(:accepts, ["html"])      plug(:fetch_session) @@ -566,30 +586,43 @@ defmodule Pleroma.Web.Router do      )    end -  pipeline :ostatus do -    plug(:accepts, ["html", "xml", "rss", "atom", "activity+json", "json"]) -    plug(Pleroma.Web.Plugs.StaticFEPlug) -  end - -  pipeline :oembed do -    plug(:accepts, ["json", "xml"]) -  end -    scope "/", Pleroma.Web do -    pipe_through([:ostatus, :http_signature]) +    # Note: html format is supported only if static FE is enabled +    # Note: http signature is only considered for json requests (no auth for non-json requests) +    pipe_through([:accepts_html_json, :http_signature, Pleroma.Web.Plugs.StaticFEPlug])      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 +    # Note: http signature is only considered for json requests (no auth for non-json requests) +    pipe_through([:accepts_html_xml_json, :http_signature, Pleroma.Web.Plugs.StaticFEPlug]) + +    # 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([:accepts_html_xml, Pleroma.Web.Plugs.StaticFEPlug]) +    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 687b17df6..bdec0897a 100644 --- a/lib/pleroma/web/static_fe/static_fe_controller.ex +++ b/lib/pleroma/web/static_fe/static_fe_controller.ex @@ -17,74 +17,14 @@ defmodule Pleroma.Web.StaticFE.StaticFEController do    plug(:put_view, Pleroma.Web.StaticFE.StaticFEView)    plug(:assign_id) -  plug(Pleroma.Web.Plugs.EnsureAuthenticatedPlug, -    unless_func: &Pleroma.Web.Plugs.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 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),           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}) @@ -107,34 +47,35 @@ defmodule Pleroma.Web.StaticFE.StaticFEController do    end    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(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 @@ -166,6 +107,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) 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 @@    <body>      <div class="container">        <h1><%= Pleroma.Config.get([:instance, :name]) %></h1> -      <%= render @view_module, @view_template, assigns %> +      <%= @inner_content %>      </div>    </body>  </html> 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 @@  							</div>  						</div>  					<% end %> -					<%= render @view_module, @view_template, assigns %> +					<%= @inner_content %>  				</td>  			</tr> 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 {  }  </style> -<%= render @view_module, @view_template, assigns %> +<%= @inner_content %>  </body>  </html> 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 @@    </head>    <body>      <div class="container"> -      <%= render @view_module, @view_template, assigns %> +      <%= @inner_content %>      </div>    </body>  </html> @@ -114,10 +114,10 @@ defmodule Pleroma.Mixfile do    # Type `mix help deps` for examples and options.    defp deps do      [ -      {:phoenix, "~> 1.4.17"}, +      {:phoenix, "~> 1.5.5"},        {:tzdata, "~> 1.0.3"},        {:plug_cowboy, "~> 2.3"}, -      {:phoenix_pubsub, "~> 1.1"}, +      {:phoenix_pubsub, "~> 2.0"},        {:phoenix_ecto, "~> 4.0"},        {:ecto_enum, "~> 1.4"},        {:ecto_sql, "~> 3.4.4"}, @@ -165,9 +165,16 @@ defmodule Pleroma.Mixfile do        {:telemetry, "~> 0.3"},        {:poolboy, "~> 1.5"},        {:prometheus, "~> 4.6"}, -      {:prometheus_ex, "~> 3.0"}, +      {:prometheus_ex, +       git: "https://git.pleroma.social/pleroma/elixir-libraries/prometheus.ex.git", +       ref: "a4e9beb3c1c479d14b352fd9d6dd7b1f6d7deee5", +       override: true},        {:prometheus_plugs, "~> 1.1"},        {:prometheus_phoenix, "~> 1.3"}, +      # Note: once `prometheus_phx` is integrated into `prometheus_phoenix`, remove the former: +      {:prometheus_phx, +       git: "https://git.pleroma.social/pleroma/elixir-libraries/prometheus-phx.git", +       branch: "no-logging"},        {:prometheus_ecto, "~> 1.4"},        {:recon, "~> 2.5"},        {:quack, "~> 0.1.1"}, @@ -18,8 +18,9 @@    "connection": {:hex, :connection, "1.0.4", "a1cae72211f0eef17705aaededacac3eb30e6625b04a6117c1b2db6ace7d5976", [:mix], [], "hexpm", "4a0850c9be22a43af9920a71ab17c051f5f7d45c209e40269a1938832510e4d9"},    "cors_plug": {:hex, :cors_plug, "2.0.2", "2b46083af45e4bc79632bd951550509395935d3e7973275b2b743bd63cc942ce", [:mix], [{:plug, "~> 1.8", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "f0d0e13f71c51fd4ef8b2c7e051388e4dfb267522a83a22392c856de7e46465f"},    "cowboy": {:hex, :cowboy, "2.8.0", "f3dc62e35797ecd9ac1b50db74611193c29815401e53bac9a5c0577bd7bc667d", [:rebar3], [{:cowlib, "~> 2.9.1", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.7.1", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "4643e4fba74ac96d4d152c75803de6fad0b3fa5df354c71afdd6cbeeb15fac8a"}, +  "cowboy_telemetry": {:hex, :cowboy_telemetry, "0.3.0", "69fdb5cf92df6373e15675eb4018cf629f5d8e35e74841bb637d6596cb797bbc", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "42868c229d9a2900a1501c5d0355bfd46e24c862c322b0b4f5a6f14fe0216753"},    "cowlib": {:hex, :cowlib, "2.9.1", "61a6c7c50cf07fdd24b2f45b89500bb93b6686579b069a89f88cb211e1125c78", [:rebar3], [], "hexpm", "e4175dc240a70d996156160891e1c62238ede1729e45740bdd38064dad476170"}, -  "credo": {:hex, :credo, "1.4.0", "92339d4cbadd1e88b5ee43d427b639b68a11071b6f73854e33638e30a0ea11f5", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "1fd3b70dce216574ce3c18bdf510b57e7c4c85c2ec9cad4bff854abaf7e58658"}, +  "credo": {:hex, :credo, "1.4.1", "16392f1edd2cdb1de9fe4004f5ab0ae612c92e230433968eab00aafd976282fc", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "155f8a2989ad77504de5d8291fa0d41320fdcaa6a1030472e9967f285f8c7692"},    "crontab": {:hex, :crontab, "1.1.8", "2ce0e74777dfcadb28a1debbea707e58b879e6aa0ffbf9c9bb540887bce43617", [:mix], [{:ecto, "~> 1.0 or ~> 2.0 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}], "hexpm"},    "crypt": {:git, "https://github.com/msantos/crypt.git", "f63a705f92c26955977ee62a313012e309a4d77a", [ref: "f63a705f92c26955977ee62a313012e309a4d77a"]},    "custom_base": {:hex, :custom_base, "0.2.1", "4a832a42ea0552299d81652aa0b1f775d462175293e99dfbe4d7dbaab785a706", [:mix], [], "hexpm", "8df019facc5ec9603e94f7270f1ac73ddf339f56ade76a721eaa57c1493ba463"}, @@ -85,14 +86,14 @@    "p1_utils": {:hex, :p1_utils, "1.0.18", "3fe224de5b2e190d730a3c5da9d6e8540c96484cf4b4692921d1e28f0c32b01c", [:rebar3], [], "hexpm", "1fc8773a71a15553b179c986b22fbeead19b28fe486c332d4929700ffeb71f88"},    "parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm", "17ef63abde837ad30680ea7f857dd9e7ced9476cdd7b0394432af4bfc241b960"},    "pbkdf2_elixir": {:hex, :pbkdf2_elixir, "1.2.1", "9cbe354b58121075bd20eb83076900a3832324b7dd171a6895fab57b6bb2752c", [:mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}], "hexpm", "d3b40a4a4630f0b442f19eca891fcfeeee4c40871936fed2f68e1c4faa30481f"}, -  "phoenix": {:hex, :phoenix, "1.4.17", "1b1bd4cff7cfc87c94deaa7d60dd8c22e04368ab95499483c50640ef3bd838d8", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 1.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.8.1 or ~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3a8e5d7a3d76d452bb5fb86e8b7bd115f737e4f8efe202a463d4aeb4a5809611"}, -  "phoenix_ecto": {:hex, :phoenix_ecto, "4.1.0", "a044d0756d0464c5a541b4a0bf4bcaf89bffcaf92468862408290682c73ae50d", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.9", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "c5e666a341ff104d0399d8f0e4ff094559b2fde13a5985d4cb5023b2c2ac558b"}, +  "phoenix": {:hex, :phoenix, "1.5.6", "8298cdb4e0f943242ba8410780a6a69cbbe972fef199b341a36898dd751bdd66", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_html, "~> 2.13", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.10", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.2", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.1.2 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "0dc4d39af1306b6aa5122729b0a95ca779e42c708c6fe7abbb3d336d5379e956"}, +  "phoenix_ecto": {:hex, :phoenix_ecto, "4.2.1", "13f124cf0a3ce0f1948cf24654c7b9f2347169ff75c1123f44674afee6af3b03", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 2.15", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "478a1bae899cac0a6e02be1deec7e2944b7754c04e7d4107fc5a517f877743c0"},    "phoenix_html": {:hex, :phoenix_html, "2.14.2", "b8a3899a72050f3f48a36430da507dd99caf0ac2d06c77529b1646964f3d563e", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "58061c8dfd25da5df1ea0ca47c972f161beb6c875cd293917045b92ffe1bf617"}, -  "phoenix_pubsub": {:hex, :phoenix_pubsub, "1.1.2", "496c303bdf1b2e98a9d26e89af5bba3ab487ba3a3735f74bf1f4064d2a845a3e", [:mix], [], "hexpm", "1f13f9f0f3e769a667a6b6828d29dec37497a082d195cc52dbef401a9b69bf38"}, -  "phoenix_swoosh": {:hex, :phoenix_swoosh, "0.3.0", "2acfa0db038a7649e0a4614eee970e6ed9a39d191ccd79a03583b51d0da98165", [:mix], [{:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:swoosh, "~> 1.0", [hex: :swoosh, repo: "hexpm", optional: false]}], "hexpm", "b8bbae4b59a676de6b8bd8675eda37bc8b4424812ae429d6fdcb2b039e00003b"}, +  "phoenix_pubsub": {:hex, :phoenix_pubsub, "2.0.0", "a1ae76717bb168cdeb10ec9d92d1480fec99e3080f011402c0a2d68d47395ffb", [:mix], [], "hexpm", "c52d948c4f261577b9c6fa804be91884b381a7f8f18450c5045975435350f771"}, +  "phoenix_swoosh": {:hex, :phoenix_swoosh, "0.3.2", "43d3518349a22b8b1910ea28b4dd5119926d5017b3187db3fbd1a1e05769a851", [:mix], [{:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:swoosh, "~> 1.0", [hex: :swoosh, repo: "hexpm", optional: false]}], "hexpm", "3e2ac4e883db7af0702d75ba00c19901760e8342b91f8f66e13941de552e777f"},    "plug": {:hex, :plug, "1.10.4", "41eba7d1a2d671faaf531fa867645bd5a3dce0957d8e2a3f398ccff7d2ef017f", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ad1e233fe73d2eec56616568d260777b67f53148a999dc2d048f4eb9778fe4a0"}, -  "plug_cowboy": {:hex, :plug_cowboy, "2.3.0", "149a50e05cb73c12aad6506a371cd75750c0b19a32f81866e1a323dda9e0e99d", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "bc595a1870cef13f9c1e03df56d96804db7f702175e4ccacdb8fc75c02a7b97e"}, -  "plug_crypto": {:hex, :plug_crypto, "1.1.2", "bdd187572cc26dbd95b87136290425f2b580a116d3fb1f564216918c9730d227", [:mix], [], "hexpm", "6b8b608f895b6ffcfad49c37c7883e8df98ae19c6a28113b02aa1e9c5b22d6b5"}, +  "plug_cowboy": {:hex, :plug_cowboy, "2.4.0", "e936ef151751f386804c51f87f7300f5aaae6893cdad726559c3930c6c032948", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "e25ddcfc06b1b76e55af79d078b03cbc86bbcb99ce4e5e0a5e4a8114ee039be6"}, +  "plug_crypto": {:hex, :plug_crypto, "1.2.0", "1cb20793aa63a6c619dd18bb33d7a3aa94818e5fd39ad357051a67f26dfa2df6", [:mix], [], "hexpm", "a48b538ae8bf381ffac344520755f3007cc10bd8e90b240af98ea29b69683fc2"},    "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, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], [], "hexpm", "fec8660eb7733ee4117b85f55799fd3833eb769a6df71ccf8903e8dc5447cfce"},    "poolboy": {:hex, :poolboy, "1.5.2", "392b007a1693a64540cead79830443abf5762f5d30cf50bc95cb2c1aaafa006b", [:rebar3], [], "hexpm", "dad79704ce5440f3d5a3681c8590b9dc25d1a561e8f5a9c995281012860901e3"}, @@ -100,8 +101,9 @@    "pot": {:hex, :pot, "0.11.0", "61bad869a94534739dd4614a25a619bc5c47b9970e9a0ea5bef4628036fc7a16", [:rebar3], [], "hexpm", "57ee6ee6bdeb639661ffafb9acefe3c8f966e45394de6a766813bb9e1be4e54b"},    "prometheus": {:hex, :prometheus, "4.6.0", "20510f381db1ccab818b4cf2fac5fa6ab5cc91bc364a154399901c001465f46f", [:mix, :rebar3], [], "hexpm", "4905fd2992f8038eccd7aa0cd22f40637ed618c0bed1f75c05aacec15b7545de"},    "prometheus_ecto": {:hex, :prometheus_ecto, "1.4.3", "3dd4da1812b8e0dbee81ea58bb3b62ed7588f2eae0c9e97e434c46807ff82311", [:mix], [{:ecto, "~> 2.0 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:prometheus_ex, "~> 1.1 or ~> 2.0 or ~> 3.0", [hex: :prometheus_ex, repo: "hexpm", optional: false]}], "hexpm", "8d66289f77f913b37eda81fd287340c17e61a447549deb28efc254532b2bed82"}, -  "prometheus_ex": {:hex, :prometheus_ex, "3.0.5", "fa58cfd983487fc5ead331e9a3e0aa622c67232b3ec71710ced122c4c453a02f", [:mix], [{:prometheus, "~> 4.0", [hex: :prometheus, repo: "hexpm", optional: false]}], "hexpm", "9fd13404a48437e044b288b41f76e64acd9735fb8b0e3809f494811dfa66d0fb"}, +  "prometheus_ex": {:git, "https://git.pleroma.social/pleroma/elixir-libraries/prometheus.ex.git", "a4e9beb3c1c479d14b352fd9d6dd7b1f6d7deee5", [ref: "a4e9beb3c1c479d14b352fd9d6dd7b1f6d7deee5"]},    "prometheus_phoenix": {:hex, :prometheus_phoenix, "1.3.0", "c4b527e0b3a9ef1af26bdcfbfad3998f37795b9185d475ca610fe4388fdd3bb5", [:mix], [{:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}, {:prometheus_ex, "~> 1.3 or ~> 2.0 or ~> 3.0", [hex: :prometheus_ex, repo: "hexpm", optional: false]}], "hexpm", "c4d1404ac4e9d3d963da601db2a7d8ea31194f0017057fabf0cfb9bf5a6c8c75"}, +  "prometheus_phx": {:git, "https://git.pleroma.social/pleroma/elixir-libraries/prometheus-phx.git", "9cd8f248c9381ffedc799905050abce194a97514", [branch: "no-logging"]},    "prometheus_plugs": {:hex, :prometheus_plugs, "1.1.5", "25933d48f8af3a5941dd7b621c889749894d8a1082a6ff7c67cc99dec26377c5", [:mix], [{:accept, "~> 0.1", [hex: :accept, repo: "hexpm", optional: false]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}, {:prometheus_ex, "~> 1.1 or ~> 2.0 or ~> 3.0", [hex: :prometheus_ex, repo: "hexpm", optional: false]}, {:prometheus_process_collector, "~> 1.1", [hex: :prometheus_process_collector, repo: "hexpm", optional: true]}], "hexpm", "0273a6483ccb936d79ca19b0ab629aef0dba958697c94782bb728b920dfc6a79"},    "quack": {:hex, :quack, "0.1.1", "cca7b4da1a233757fdb44b3334fce80c94785b3ad5a602053b7a002b5a8967bf", [:mix], [{:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: false]}, {:tesla, "~> 1.2.0", [hex: :tesla, repo: "hexpm", optional: false]}], "hexpm", "d736bfa7444112eb840027bb887832a0e403a4a3437f48028c3b29a2dbbd2543"},    "ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm", "451d8527787df716d99dc36162fca05934915db0b6141bbdac2ea8d3c7afc7d7"}, @@ -110,13 +112,13 @@    "sleeplocks": {:hex, :sleeplocks, "1.1.1", "3d462a0639a6ef36cc75d6038b7393ae537ab394641beb59830a1b8271faeed3", [:rebar3], [], "hexpm", "84ee37aeff4d0d92b290fff986d6a95ac5eedf9b383fadfd1d88e9b84a1c02e1"},    "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.5", "6eaf7ad16cb568bb01753dbbd7a95ff8b91c7979482b95f38443fe2c8852a79b", [:make, :mix, :rebar3], [], "hexpm", "13104d7897e38ed7f044c4de953a6c28597d1c952075eb2e328bc6d6f2bfc496"},    "sweet_xml": {:hex, :sweet_xml, "0.6.6", "fc3e91ec5dd7c787b6195757fbcf0abc670cee1e4172687b45183032221b66b8", [:mix], [], "hexpm", "2e1ec458f892ffa81f9f8386e3f35a1af6db7a7a37748a64478f13163a1f3573"}, -  "swoosh": {:hex, :swoosh, "1.0.0", "c547cfc83f30e12d5d1fdcb623d7de2c2e29a5becfc68bf8f42ba4d23d2c2756", [:mix], [{:cowboy, "~> 1.0.1 or ~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.13", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mail, "~> 0.2", [hex: :mail, repo: "hexpm", optional: true]}, {:mime, "~> 1.1", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}], "hexpm", "b3b08e463f876cb6167f7168e9ad99a069a724e124bcee61847e0e1ed13f4a0d"}, +  "swoosh": {:hex, :swoosh, "1.0.6", "6765e334c67dacabe721f0d701c7e5a6f06e4595c90df6f91e73ebd54d555833", [:mix], [{:cowboy, "~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.13 or ~> 1.0", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mail, "~> 0.2", [hex: :mail, repo: "hexpm", optional: true]}, {:mime, "~> 1.1", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}], "hexpm", "7c50ef78e4acfd1cbd4907dc1fa87b5540675a6be9dc979d04890f49d7ec1830"},    "syslog": {:hex, :syslog, "1.1.0", "6419a232bea84f07b56dc575225007ffe34d9fdc91abe6f1b2f254fd71d8efc2", [:rebar3], [], "hexpm", "4c6a41373c7e20587be33ef841d3de6f3beba08519809329ecc4d27b15b659e1"},    "telemetry": {:hex, :telemetry, "0.4.2", "2808c992455e08d6177322f14d3bdb6b625fbcfd233a73505870d8738a2f4599", [:rebar3], [], "hexpm", "2d1419bd9dda6a206d7b5852179511722e2b18812310d304620c7bd92a13fcef"},    "tesla": {:git, "https://github.com/teamon/tesla/", "9f7261ca49f9f901ceb73b60219ad6f8a9f6aa30", [ref: "9f7261ca49f9f901ceb73b60219ad6f8a9f6aa30"]},    "timex": {:hex, :timex, "3.6.2", "845cdeb6119e2fef10751c0b247b6c59d86d78554c83f78db612e3290f819bc2", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.10", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 0.1.8 or ~> 0.5 or ~> 1.0.0", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "26030b46199d02a590be61c2394b37ea25a3664c02fafbeca0b24c972025d47a"},    "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.0.3", "73470ad29dde46e350c60a66e6b360d3b99d2d18b74c4c349dbebbc27a09a3eb", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "a6e1ee7003c4d04ecbd21dd3ec690d4c6662db5d3bbdd7262d53cdf5e7c746c1"}, +  "tzdata": {:hex, :tzdata, "1.0.4", "a3baa4709ea8dba552dca165af6ae97c624a2d6ac14bd265165eaa8e8af94af6", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "b02637db3df1fd66dd2d3c4f194a81633d0e4b44308d36c1b2fdfd1e4e6f169b"},    "ueberauth": {:hex, :ueberauth, "0.6.3", "d42ace28b870e8072cf30e32e385579c57b9cc96ec74fa1f30f30da9c14f3cc0", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "afc293d8a1140d6591b53e3eaf415ca92842cb1d32fad3c450c6f045f7f91b60"},    "unicode_util_compat": {:hex, :unicode_util_compat, "0.4.1", "d869e4c68901dd9531385bb0c8c40444ebf624e60b6962d95952775cac5e90cd", [:rebar3], [], "hexpm", "1d1848c40487cdb0b30e8ed975e34e025860c02e419cb615d255849f3427439d"},    "unsafe": {:hex, :unsafe, "1.0.1", "a27e1874f72ee49312e0a9ec2e0b27924214a05e3ddac90e91727bc76f8613d8", [:mix], [], "hexpm", "6c7729a2d214806450d29766abc2afaa7a2cbecf415be64f36a6691afebb50e5"}, diff --git a/priv/gettext/zh_Hans/LC_MESSAGES/errors.po b/priv/gettext/zh_Hans/LC_MESSAGES/errors.po index 4f029d558..8b24d4a86 100644 --- a/priv/gettext/zh_Hans/LC_MESSAGES/errors.po +++ b/priv/gettext/zh_Hans/LC_MESSAGES/errors.po @@ -3,8 +3,8 @@ msgstr ""  "Project-Id-Version: PACKAGE VERSION\n"  "Report-Msgid-Bugs-To: \n"  "POT-Creation-Date: 2020-09-20 13:18+0000\n" -"PO-Revision-Date: 2020-09-20 14:48+0000\n" -"Last-Translator: Kana <gudzpoz@live.com>\n" +"PO-Revision-Date: 2020-10-22 18:25+0000\n" +"Last-Translator: shironeko <shironeko@tesaguri.club>\n"  "Language-Team: Chinese (Simplified) <https://translate.pleroma.social/"  "projects/pleroma/pleroma/zh_Hans/>\n"  "Language: zh_Hans\n" @@ -49,7 +49,7 @@ msgstr "是被保留的"  ## From Ecto.Changeset.validate_confirmation/3  msgid "does not match confirmation" -msgstr "" +msgstr "与验证不符"  ## From Ecto.Changeset.no_assoc_constraint/3  msgid "is still associated with this entry" @@ -138,12 +138,12 @@ msgstr "不能获取收藏"  #: lib/pleroma/web/activity_pub/activity_pub_controller.ex:438  #, elixir-format  msgid "Can't like object" -msgstr "" +msgstr "不能喜欢对象"  #: lib/pleroma/web/common_api/utils.ex:563  #, elixir-format  msgid "Cannot post an empty status without attachments" -msgstr "" +msgstr "无法发送空白且不包含附件的状态"  #: lib/pleroma/web/common_api/utils.ex:511  #, elixir-format @@ -153,100 +153,100 @@ msgstr ""  #: lib/pleroma/config/config_db.ex:191  #, elixir-format  msgid "Config with params %{params} not found" -msgstr "" +msgstr "无法找到包含参数 %{params} 的配置"  #: lib/pleroma/web/common_api/common_api.ex:181  #: lib/pleroma/web/common_api/common_api.ex:185  #, elixir-format  msgid "Could not delete" -msgstr "" +msgstr "无法删除"  #: lib/pleroma/web/common_api/common_api.ex:231  #, elixir-format  msgid "Could not favorite" -msgstr "" +msgstr "无法收藏"  #: lib/pleroma/web/common_api/common_api.ex:453  #, elixir-format  msgid "Could not pin" -msgstr "" +msgstr "无法置顶"  #: lib/pleroma/web/common_api/common_api.ex:278  #, elixir-format  msgid "Could not unfavorite" -msgstr "" +msgstr "无法取消收藏"  #: lib/pleroma/web/common_api/common_api.ex:463  #, elixir-format  msgid "Could not unpin" -msgstr "" +msgstr "无法取消置顶"  #: lib/pleroma/web/common_api/common_api.ex:216  #, elixir-format  msgid "Could not unrepeat" -msgstr "" +msgstr "无法取消转发"  #: lib/pleroma/web/common_api/common_api.ex:512  #: lib/pleroma/web/common_api/common_api.ex:521  #, elixir-format  msgid "Could not update state" -msgstr "" +msgstr "无法更新状态"  #: lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:207  #, elixir-format  msgid "Error." -msgstr "" +msgstr "错误。"  #: lib/pleroma/web/twitter_api/twitter_api.ex:106  #, elixir-format  msgid "Invalid CAPTCHA" -msgstr "" +msgstr "无效的验证码"  #: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:116  #: lib/pleroma/web/oauth/oauth_controller.ex:568  #, elixir-format  msgid "Invalid credentials" -msgstr "" +msgstr "无效的凭据"  #: lib/pleroma/plugs/ensure_authenticated_plug.ex:38  #, elixir-format  msgid "Invalid credentials." -msgstr "" +msgstr "无效的凭据。"  #: lib/pleroma/web/common_api/common_api.ex:355  #, elixir-format  msgid "Invalid indices" -msgstr "" +msgstr "无效的索引"  #: lib/pleroma/web/admin_api/controllers/fallback_controller.ex:29  #, elixir-format  msgid "Invalid parameters" -msgstr "" +msgstr "无效的参数"  #: lib/pleroma/web/common_api/utils.ex:414  #, elixir-format  msgid "Invalid password." -msgstr "" +msgstr "无效的密码。"  #: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:220  #, elixir-format  msgid "Invalid request" -msgstr "" +msgstr "无效的请求"  #: lib/pleroma/web/twitter_api/twitter_api.ex:109  #, elixir-format  msgid "Kocaptcha service unavailable" -msgstr "" +msgstr "Kocaptcha 服务不可用"  #: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:112  #, elixir-format  msgid "Missing parameters" -msgstr "" +msgstr "缺少参数"  #: lib/pleroma/web/common_api/utils.ex:547  #, elixir-format  msgid "No such conversation" -msgstr "" +msgstr "没有该对话"  #: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:388  #: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:414 lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:456 diff --git a/test/fixtures/mastodon-post-activity-nsfw.json b/test/fixtures/mastodon-post-activity-nsfw.json new file mode 100644 index 000000000..70729a1bd --- /dev/null +++ b/test/fixtures/mastodon-post-activity-nsfw.json @@ -0,0 +1,68 @@ +{ +    "@context": [ +        "https://www.w3.org/ns/activitystreams", +        "https://w3id.org/security/v1", +        { +            "Emoji": "toot:Emoji", +            "Hashtag": "as:Hashtag", +            "atomUri": "ostatus:atomUri", +            "conversation": "ostatus:conversation", +            "inReplyToAtomUri": "ostatus:inReplyToAtomUri", +            "manuallyApprovesFollowers": "as:manuallyApprovesFollowers", +            "movedTo": "as:movedTo", +            "ostatus": "http://ostatus.org#", +            "toot": "http://joinmastodon.org/ns#" +        } +    ], +    "actor": "http://mastodon.example.org/users/admin", +    "cc": [ +        "http://mastodon.example.org/users/admin/followers", +        "http://localtesting.pleroma.lol/users/lain" +    ], +    "id": "http://mastodon.example.org/users/admin/statuses/99512778738411822/activity", +    "nickname": "lain", +    "object": { +        "atomUri": "http://mastodon.example.org/users/admin/statuses/99512778738411822", +        "attachment": [], +        "attributedTo": "http://mastodon.example.org/users/admin", +        "cc": [ +            "http://mastodon.example.org/users/admin/followers", +            "http://localtesting.pleroma.lol/users/lain" +        ], +        "content": "<p><span class=\"h-card\"><a href=\"http://localtesting.pleroma.lol/users/lain\" class=\"u-url mention\">@<span>lain</span></a></span> #moo</p>", +        "conversation": "tag:mastodon.example.org,2018-02-12:objectId=20:objectType=Conversation", +        "id": "http://mastodon.example.org/users/admin/statuses/99512778738411822", +        "inReplyTo": null, +        "inReplyToAtomUri": null, +        "published": "2018-02-12T14:08:20Z", +        "summary": "cw", +        "tag": [ +            { +                "href": "http://localtesting.pleroma.lol/users/lain", +                "name": "@lain@localtesting.pleroma.lol", +                "type": "Mention" +            }, +            { +                "href": "http://mastodon.example.org/tags/nsfw", +                "name": "#NSFW", +                "type": "Hashtag" +            } +        ], +        "to": [ +            "https://www.w3.org/ns/activitystreams#Public" +        ], +        "type": "Note", +        "url": "http://mastodon.example.org/@admin/99512778738411822" +    }, +    "published": "2018-02-12T14:08:20Z", +    "signature": { +        "created": "2018-02-12T14:08:20Z", +        "creator": "http://mastodon.example.org/users/admin#main-key", +        "signatureValue": "rnNfcopkc6+Ju73P806popcfwrK9wGYHaJVG1/ZvrlEbWVDzaHjkXqj9Q3/xju5l8CSn9tvSgCCtPFqZsFQwn/pFIFUcw7ZWB2xi4bDm3NZ3S4XQ8JRaaX7og5hFxAhWkGhJhAkfxVnOg2hG+w2d/7d7vRVSC1vo5ip4erUaA/PkWusZvPIpxnRWoXaxJsFmVx0gJgjpJkYDyjaXUlp+jmaoseeZ4EPQUWqHLKJ59PRG0mg8j2xAjYH9nQaN14qMRmTGPxY8gfv/CUFcatA+8VJU9KEsJkDAwLVvglydNTLGrxpAJU78a2eaht0foV43XUIZGe3DKiJPgE+UOKGCJw==", +        "type": "RsaSignature2017" +    }, +    "to": [ +        "https://www.w3.org/ns/activitystreams#Public" +    ], +    "type": "Create" +} diff --git a/test/fixtures/mewmew_no_name.json b/test/fixtures/mewmew_no_name.json new file mode 100644 index 000000000..532d4cf70 --- /dev/null +++ b/test/fixtures/mewmew_no_name.json @@ -0,0 +1,46 @@ +{ +   "@context" : [ +      "https://www.w3.org/ns/activitystreams", +      "https://princess.cat/schemas/litepub-0.1.jsonld", +      { +         "@language" : "und" +      } +   ], +   "attachment" : [], +   "capabilities" : { +      "acceptsChatMessages" : true +   }, +   "discoverable" : false, +   "endpoints" : { +      "oauthAuthorizationEndpoint" : "https://princess.cat/oauth/authorize", +      "oauthRegistrationEndpoint" : "https://princess.cat/api/v1/apps", +      "oauthTokenEndpoint" : "https://princess.cat/oauth/token", +      "sharedInbox" : "https://princess.cat/inbox", +      "uploadMedia" : "https://princess.cat/api/ap/upload_media" +   }, +   "followers" : "https://princess.cat/users/mewmew/followers", +   "following" : "https://princess.cat/users/mewmew/following", +   "icon" : { +      "type" : "Image", +      "url" : "https://princess.cat/media/12794fb50e86911e65be97f69196814049dcb398a2f8b58b99bb6591576e648c.png?name=blobcatpresentpink.png" +   }, +   "id" : "https://princess.cat/users/mewmew", +   "image" : { +      "type" : "Image", +      "url" : "https://princess.cat/media/05d8bf3953ab6028fc920494ffc643fbee9dcef40d7bdd06f107e19acbfbd7f9.png" +   }, +   "inbox" : "https://princess.cat/users/mewmew/inbox", +   "manuallyApprovesFollowers" : true, +   "name" : " ", +   "outbox" : "https://princess.cat/users/mewmew/outbox", +   "preferredUsername" : "mewmew", +   "publicKey" : { +      "id" : "https://princess.cat/users/mewmew#main-key", +      "owner" : "https://princess.cat/users/mewmew", +      "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAru7VpygVef4zrFwnj0Mh\nrbO/2z2EdKN3rERtNrT8zWsLXNLQ50lfpRPnGDrd+xq7Rva4EIu0d5KJJ9n4vtY0\nuxK3On9vA2oyjLlR9O0lI3XTrHJborG3P7IPXrmNUMFpHiFHNqHp5tugUrs1gUFq\n7tmOmM92IP4Wjk8qNHFcsfnUbaPTX7sNIhteQKdi5HrTb/6lrEIe4G/FlMKRqxo3\nRNHuv6SNFQuiUKvFzjzazvjkjvBSm+aFROgdHa2tKl88StpLr7xmuY8qNFCRT6W0\nLacRp6c8ah5f03Kd+xCBVhCKvKaF1K0ERnQTBiitUh85md+Mtx/CoDoLnmpnngR3\nvQIDAQAB\n-----END PUBLIC KEY-----\n\n" +   }, +   "summary" : "please reply to my posts as direct messages if you have many followers", +   "tag" : [], +   "type" : "Person", +   "url" : "https://princess.cat/users/mewmew" +} diff --git a/test/pleroma/notification_test.exs b/test/pleroma/notification_test.exs index 0e9630f28..a74fb7bc2 100644 --- a/test/pleroma/notification_test.exs +++ b/test/pleroma/notification_test.exs @@ -400,7 +400,7 @@ defmodule Pleroma.NotificationTest do        user = insert(:user, is_locked: true)        follower = insert(:user)        {:ok, _, _, _follow_activity} = CommonAPI.follow(follower, user) -      assert [notification] = Notification.for_user(user) +      assert [_notification] = Notification.for_user(user)        {:ok, _follower} = CommonAPI.reject_follow_request(follower, user)        assert [] = Notification.for_user(user)      end diff --git a/test/pleroma/user_test.exs b/test/pleroma/user_test.exs index 7220ce846..9ae52d594 100644 --- a/test/pleroma/user_test.exs +++ b/test/pleroma/user_test.exs @@ -388,6 +388,7 @@ defmodule Pleroma.UserTest do      }      setup do: clear_config([:instance, :autofollowed_nicknames]) +    setup do: clear_config([:instance, :autofollowing_nicknames])      setup do: clear_config([:welcome])      setup do: clear_config([:instance, :account_activation_required]) @@ -408,6 +409,23 @@ defmodule Pleroma.UserTest do        refute User.following?(registered_user, remote_user)      end +    test "it adds automatic followers for new registered accounts" do +      user1 = insert(:user) +      user2 = insert(:user) + +      Pleroma.Config.put([:instance, :autofollowing_nicknames], [ +        user1.nickname, +        user2.nickname +      ]) + +      cng = User.register_changeset(%User{}, @full_user_data) + +      {:ok, registered_user} = User.register(cng) + +      assert User.following?(user1, registered_user) +      assert User.following?(user2, registered_user) +    end +      test "it sends a welcome message if it is set" do        welcome_user = insert(:user)        Pleroma.Config.put([:welcome, :direct_message, :enabled], true) diff --git a/test/pleroma/web/activity_pub/activity_pub_controller_test.exs b/test/pleroma/web/activity_pub/activity_pub_controller_test.exs index b11e2f961..b696a24f4 100644 --- a/test/pleroma/web/activity_pub/activity_pub_controller_test.exs +++ b/test/pleroma/web/activity_pub/activity_pub_controller_test.exs @@ -156,21 +156,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do        assert response == "Not found"      end - -    test "it requires authentication if instance is NOT federating", %{ -      conn: conn -    } do -      user = insert(:user) - -      conn = -        put_req_header( -          conn, -          "accept", -          "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"" -        ) - -      ensure_federating_or_authenticated(conn, "/users/#{user.nickname}.json", user) -    end    end    describe "mastodon compatibility routes" do @@ -338,18 +323,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do        assert "Not found" == json_response(conn2, :not_found)      end - -    test "it requires authentication if instance is NOT federating", %{ -      conn: conn -    } do -      user = insert(:user) -      note = insert(:note) -      uuid = String.split(note.data["id"], "/") |> List.last() - -      conn = put_req_header(conn, "accept", "application/activity+json") - -      ensure_federating_or_authenticated(conn, "/objects/#{uuid}", user) -    end    end    describe "/activities/:uuid" do @@ -421,18 +394,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do        assert "Not found" == json_response(conn2, :not_found)      end - -    test "it requires authentication if instance is NOT federating", %{ -      conn: conn -    } do -      user = insert(:user) -      activity = insert(:note_activity) -      uuid = String.split(activity.data["id"], "/") |> List.last() - -      conn = put_req_header(conn, "accept", "application/activity+json") - -      ensure_federating_or_authenticated(conn, "/activities/#{uuid}", user) -    end    end    describe "/inbox" do @@ -893,15 +854,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do        assert response(conn, 200) =~ announce_activity.data["object"]      end - -    test "it requires authentication if instance is NOT federating", %{ -      conn: conn -    } do -      user = insert(:user) -      conn = put_req_header(conn, "accept", "application/activity+json") - -      ensure_federating_or_authenticated(conn, "/users/#{user.nickname}/outbox", user) -    end    end    describe "POST /users/:nickname/outbox (C2S)" do diff --git a/test/pleroma/web/activity_pub/activity_pub_test.exs b/test/pleroma/web/activity_pub/activity_pub_test.exs index e6b6086e6..43bd14ee6 100644 --- a/test/pleroma/web/activity_pub/activity_pub_test.exs +++ b/test/pleroma/web/activity_pub/activity_pub_test.exs @@ -505,22 +505,22 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do        # public        {:ok, _} = CommonAPI.post(user2, Map.put(reply_data, :visibility, "public")) -      assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id) +      assert %{data: _data, object: object} = Activity.get_by_ap_id_with_object(ap_id)        assert object.data["repliesCount"] == 1        # unlisted        {:ok, _} = CommonAPI.post(user2, Map.put(reply_data, :visibility, "unlisted")) -      assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id) +      assert %{data: _data, object: object} = Activity.get_by_ap_id_with_object(ap_id)        assert object.data["repliesCount"] == 2        # private        {:ok, _} = CommonAPI.post(user2, Map.put(reply_data, :visibility, "private")) -      assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id) +      assert %{data: _data, object: object} = Activity.get_by_ap_id_with_object(ap_id)        assert object.data["repliesCount"] == 2        # direct        {:ok, _} = CommonAPI.post(user2, Map.put(reply_data, :visibility, "direct")) -      assert %{data: data, object: object} = Activity.get_by_ap_id_with_object(ap_id) +      assert %{data: _data, object: object} = Activity.get_by_ap_id_with_object(ap_id)        assert object.data["repliesCount"] == 2      end    end @@ -2273,4 +2273,15 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do        assert length(activities) == 2      end    end + +  test "allow fetching of accounts with an empty string name field" do +    Tesla.Mock.mock(fn +      %{method: :get, url: "https://princess.cat/users/mewmew"} -> +        file = File.read!("test/fixtures/mewmew_no_name.json") +        %Tesla.Env{status: 200, body: file} +    end) + +    {:ok, user} = ActivityPub.make_user_from_ap_id("https://princess.cat/users/mewmew") +    assert user.name == " " +  end  end diff --git a/test/pleroma/web/activity_pub/mrf/reject_non_public_test.exs b/test/pleroma/web/activity_pub/mrf/reject_non_public_test.exs index 58b46b9a2..e08eb3ba6 100644 --- a/test/pleroma/web/activity_pub/mrf/reject_non_public_test.exs +++ b/test/pleroma/web/activity_pub/mrf/reject_non_public_test.exs @@ -21,7 +21,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.RejectNonPublicTest do          "type" => "Create"        } -      assert {:ok, message} = RejectNonPublic.filter(message) +      assert {:ok, _message} = RejectNonPublic.filter(message)      end      test "it's allowed when cc address contain public address" do @@ -34,7 +34,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.RejectNonPublicTest do          "type" => "Create"        } -      assert {:ok, message} = RejectNonPublic.filter(message) +      assert {:ok, _message} = RejectNonPublic.filter(message)      end    end @@ -50,7 +50,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.RejectNonPublicTest do        }        Pleroma.Config.put([:mrf_rejectnonpublic, :allow_followersonly], true) -      assert {:ok, message} = RejectNonPublic.filter(message) +      assert {:ok, _message} = RejectNonPublic.filter(message)      end      test "it's rejected when addrer of message in the follower addresses of user and it disabled in config" do @@ -80,7 +80,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.RejectNonPublicTest do        }        Pleroma.Config.put([:mrf_rejectnonpublic, :allow_direct], true) -      assert {:ok, message} = RejectNonPublic.filter(message) +      assert {:ok, _message} = RejectNonPublic.filter(message)      end      test "it's reject when direct messages aren't allow" do diff --git a/test/pleroma/web/activity_pub/mrf/tag_policy_test.exs b/test/pleroma/web/activity_pub/mrf/tag_policy_test.exs index 6ff71d640..ffc30ba62 100644 --- a/test/pleroma/web/activity_pub/mrf/tag_policy_test.exs +++ b/test/pleroma/web/activity_pub/mrf/tag_policy_test.exs @@ -29,7 +29,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.TagPolicyTest do        actor = insert(:user, tags: ["mrf_tag:disable-remote-subscription"])        follower = insert(:user, tags: ["mrf_tag:disable-remote-subscription"], local: true)        message = %{"object" => actor.ap_id, "type" => "Follow", "actor" => follower.ap_id} -      assert {:ok, message} = TagPolicy.filter(message) +      assert {:ok, _message} = TagPolicy.filter(message)      end    end diff --git a/test/pleroma/web/activity_pub/transmogrifier/announce_handling_test.exs b/test/pleroma/web/activity_pub/transmogrifier/announce_handling_test.exs index e895636b5..54335acdb 100644 --- a/test/pleroma/web/activity_pub/transmogrifier/announce_handling_test.exs +++ b/test/pleroma/web/activity_pub/transmogrifier/announce_handling_test.exs @@ -144,7 +144,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.AnnounceHandlingTest do      _user = insert(:user, local: false, ap_id: data["actor"]) -    assert {:error, e} = Transmogrifier.handle_incoming(data) +    assert {:error, _e} = Transmogrifier.handle_incoming(data)    end    test "it does not clobber the addressing on announce activities" do diff --git a/test/pleroma/web/activity_pub/transmogrifier_test.exs b/test/pleroma/web/activity_pub/transmogrifier_test.exs index 561674f01..e39af1dfc 100644 --- a/test/pleroma/web/activity_pub/transmogrifier_test.exs +++ b/test/pleroma/web/activity_pub/transmogrifier_test.exs @@ -101,7 +101,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do        {:ok, returned_activity} = Transmogrifier.handle_incoming(data)        returned_object = Object.normalize(returned_activity, false) -      assert activity = +      assert %Activity{} =                 Activity.get_create_by_object_ap_id(                   "https://mstdn.io/users/mayuutann/statuses/99568293732299394"                 ) @@ -206,6 +206,16 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do        assert user.note_count == 1      end +    test "it works for incoming notices without the sensitive property but an nsfw hashtag" do +      data = File.read!("test/fixtures/mastodon-post-activity-nsfw.json") |> Poison.decode!() + +      {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) + +      object_data = Object.normalize(data["object"], false).data + +      assert object_data["sensitive"] == true +    end +      test "it works for incoming notices with hashtags" do        data = File.read!("test/fixtures/mastodon-post-activity-hashtag.json") |> Poison.decode!() diff --git a/test/pleroma/web/common_api_test.exs b/test/pleroma/web/common_api_test.exs index f5d09f396..c5b90ad84 100644 --- a/test/pleroma/web/common_api_test.exs +++ b/test/pleroma/web/common_api_test.exs @@ -95,6 +95,20 @@ defmodule Pleroma.Web.CommonAPITest do    describe "posting chat messages" do      setup do: clear_config([:instance, :chat_limit]) +    test "it posts a self-chat" do +      author = insert(:user) +      recipient = author + +      {:ok, activity} = +        CommonAPI.post_chat_message( +          author, +          recipient, +          "remember to buy milk when milk truk arive" +        ) + +      assert activity.data["type"] == "Create" +    end +      test "it posts a chat message without content but with an attachment" do        author = insert(:user)        recipient = insert(:user) @@ -622,7 +636,7 @@ defmodule Pleroma.Web.CommonAPITest do        assert {:error, "The status is over the character limit"} =                 CommonAPI.post(user, %{status: "foobar"}) -      assert {:ok, activity} = CommonAPI.post(user, %{status: "12345"}) +      assert {:ok, _activity} = CommonAPI.post(user, %{status: "12345"})      end      test "it can handle activities that expire" do diff --git a/test/pleroma/web/endpoint/metrics_exporter_test.exs b/test/pleroma/web/endpoint/metrics_exporter_test.exs new file mode 100644 index 000000000..875addc96 --- /dev/null +++ b/test/pleroma/web/endpoint/metrics_exporter_test.exs @@ -0,0 +1,68 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.Endpoint.MetricsExporterTest do +  use Pleroma.Web.ConnCase + +  alias Pleroma.Web.Endpoint.MetricsExporter + +  defp config do +    Application.get_env(:prometheus, MetricsExporter) +  end + +  describe "with default config" do +    test "does NOT expose app metrics", %{conn: conn} do +      conn +      |> get(config()[:path]) +      |> json_response(404) +    end +  end + +  describe "when enabled" do +    setup do +      initial_config = config() +      on_exit(fn -> Application.put_env(:prometheus, MetricsExporter, initial_config) end) + +      Application.put_env( +        :prometheus, +        MetricsExporter, +        Keyword.put(initial_config, :enabled, true) +      ) +    end + +    test "serves app metrics", %{conn: conn} do +      conn = get(conn, config()[:path]) +      assert response = response(conn, 200) + +      for metric <- [ +            "http_requests_total", +            "http_request_duration_microseconds", +            "phoenix_controller_call_duration", +            "telemetry_scrape_duration", +            "erlang_vm_memory_atom_bytes_total" +          ] do +        assert response =~ ~r/#{metric}/ +      end +    end + +    test "when IP whitelist configured, " <> +           "serves app metrics only if client IP is whitelisted", +         %{conn: conn} do +      Application.put_env( +        :prometheus, +        MetricsExporter, +        Keyword.put(config(), :ip_whitelist, ["127.127.127.127", {1, 1, 1, 1}, '255.255.255.255']) +      ) + +      conn +      |> get(config()[:path]) +      |> json_response(404) + +      conn +      |> Map.put(:remote_ip, {127, 127, 127, 127}) +      |> get(config()[:path]) +      |> response(200) +    end +  end +end diff --git a/test/pleroma/web/fed_sockets/fed_registry_test.exs b/test/pleroma/web/fed_sockets/fed_registry_test.exs index 19ac874d6..73aaced46 100644 --- a/test/pleroma/web/fed_sockets/fed_registry_test.exs +++ b/test/pleroma/web/fed_sockets/fed_registry_test.exs @@ -52,7 +52,7 @@ defmodule Pleroma.Web.FedSockets.FedRegistryTest do      end      test "will be ignored" do -      assert {:ok, %SocketInfo{origin: origin, pid: pid_one}} = +      assert {:ok, %SocketInfo{origin: origin, pid: _pid_one}} =                 FedRegistry.get_fed_socket(@good_domain_origin)        assert origin == "good.domain:80" @@ -63,7 +63,7 @@ defmodule Pleroma.Web.FedSockets.FedRegistryTest do      test "the newer process will be closed" do        pid_two = build_test_socket(@good_domain) -      assert {:ok, %SocketInfo{origin: origin, pid: pid_one}} = +      assert {:ok, %SocketInfo{origin: origin, pid: _pid_one}} =                 FedRegistry.get_fed_socket(@good_domain_origin)        assert origin == "good.domain:80" diff --git a/test/pleroma/web/feed/tag_controller_test.exs b/test/pleroma/web/feed/tag_controller_test.exs index 868e40965..e4084b0e5 100644 --- a/test/pleroma/web/feed/tag_controller_test.exs +++ b/test/pleroma/web/feed/tag_controller_test.exs @@ -8,6 +8,7 @@ defmodule Pleroma.Web.Feed.TagControllerTest do    import Pleroma.Factory    import SweetXml +  alias Pleroma.Config    alias Pleroma.Object    alias Pleroma.Web.CommonAPI    alias Pleroma.Web.Feed.FeedView @@ -15,7 +16,7 @@ defmodule Pleroma.Web.Feed.TagControllerTest do    setup do: clear_config([:feed])    test "gets a feed (ATOM)", %{conn: conn} do -    Pleroma.Config.put( +    Config.put(        [:feed, :post_title],        %{max_length: 25, omission: "..."}      ) @@ -82,7 +83,7 @@ defmodule Pleroma.Web.Feed.TagControllerTest do    end    test "gets a feed (RSS)", %{conn: conn} do -    Pleroma.Config.put( +    Config.put(        [:feed, :post_title],        %{max_length: 25, omission: "..."}      ) @@ -157,7 +158,7 @@ defmodule Pleroma.Web.Feed.TagControllerTest do      response =        conn        |> put_req_header("accept", "application/rss+xml") -      |> get(tag_feed_path(conn, :feed, "pleromaart")) +      |> get(tag_feed_path(conn, :feed, "pleromaart.rss"))        |> response(200)      xml = parse(response) @@ -183,14 +184,12 @@ defmodule Pleroma.Web.Feed.TagControllerTest do    end    describe "private instance" do -    setup do: clear_config([:instance, :public]) +    setup do: clear_config([:instance, :public], false)      test "returns 404 for tags feed", %{conn: conn} do -      Config.put([:instance, :public], false) -        conn        |> put_req_header("accept", "application/rss+xml") -      |> get(tag_feed_path(conn, :feed, "pleromaart")) +      |> get(tag_feed_path(conn, :feed, "pleromaart.rss"))        |> response(404)      end    end diff --git a/test/pleroma/web/feed/user_controller_test.exs b/test/pleroma/web/feed/user_controller_test.exs index a5dc0894b..eabfe3a63 100644 --- a/test/pleroma/web/feed/user_controller_test.exs +++ b/test/pleroma/web/feed/user_controller_test.exs @@ -13,7 +13,7 @@ defmodule Pleroma.Web.Feed.UserControllerTest do    alias Pleroma.User    alias Pleroma.Web.CommonAPI -  setup do: clear_config([:instance, :federating], true) +  setup do: clear_config([:static_fe, :enabled], false)    describe "feed" do      setup do: clear_config([:feed]) @@ -192,6 +192,16 @@ defmodule Pleroma.Web.Feed.UserControllerTest do               |> get(user_feed_path(conn, :feed, user.nickname))               |> response(404)      end + +    test "does not require authentication on non-federating instances", %{conn: conn} do +      clear_config([:instance, :federating], false) +      user = insert(:user) + +      conn +      |> put_req_header("accept", "application/rss+xml") +      |> get("/users/#{user.nickname}/feed.rss") +      |> response(200) +    end    end    # Note: see ActivityPubControllerTest for JSON format tests diff --git a/test/pleroma/web/mastodon_api/controllers/account_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/account_controller_test.exs index c86223b26..58ce76ab8 100644 --- a/test/pleroma/web/mastodon_api/controllers/account_controller_test.exs +++ b/test/pleroma/web/mastodon_api/controllers/account_controller_test.exs @@ -32,7 +32,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do      test "works by nickname" do        user = insert(:user) -      assert %{"id" => user_id} = +      assert %{"id" => _user_id} =                 build_conn()                 |> get("/api/v1/accounts/#{user.nickname}")                 |> json_response_and_validate_schema(200) @@ -43,7 +43,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do        user = insert(:user, nickname: "user@example.com", local: false) -      assert %{"id" => user_id} = +      assert %{"id" => _user_id} =                 build_conn()                 |> get("/api/v1/accounts/#{user.nickname}")                 |> json_response_and_validate_schema(200) @@ -1429,10 +1429,10 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do      test "returns lists to which the account belongs" do        %{user: user, conn: conn} = oauth_access(["read:lists"])        other_user = insert(:user) -      assert {:ok, %Pleroma.List{id: list_id} = list} = Pleroma.List.create("Test List", user) +      assert {:ok, %Pleroma.List{id: _list_id} = list} = Pleroma.List.create("Test List", user)        {:ok, %{following: _following}} = Pleroma.List.follow(list, other_user) -      assert [%{"id" => list_id, "title" => "Test List"}] = +      assert [%{"id" => _list_id, "title" => "Test List"}] =                 conn                 |> get("/api/v1/accounts/#{other_user.id}/lists")                 |> json_response_and_validate_schema(200) diff --git a/test/pleroma/web/mastodon_api/controllers/status_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/status_controller_test.exs index 61359214a..436608e51 100644 --- a/test/pleroma/web/mastodon_api/controllers/status_controller_test.exs +++ b/test/pleroma/web/mastodon_api/controllers/status_controller_test.exs @@ -937,7 +937,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do          |> get("/api/v1/statuses/#{reblog_activity1.id}")        assert %{ -               "reblog" => %{"id" => id, "reblogged" => false, "reblogs_count" => 2}, +               "reblog" => %{"id" => _id, "reblogged" => false, "reblogs_count" => 2},                 "reblogged" => false,                 "favourited" => false,                 "bookmarked" => false diff --git a/test/pleroma/web/o_auth/o_auth_controller_test.exs b/test/pleroma/web/o_auth/o_auth_controller_test.exs index 1200126b8..a00df8cc7 100644 --- a/test/pleroma/web/o_auth/o_auth_controller_test.exs +++ b/test/pleroma/web/o_auth/o_auth_controller_test.exs @@ -77,7 +77,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do            }          ) -      assert response = html_response(conn, 302) +      assert html_response(conn, 302)        redirect_query = URI.parse(redirected_to(conn)).query        assert %{"state" => state_param} = URI.decode_query(redirect_query) @@ -119,7 +119,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do            }          ) -      assert response = html_response(conn, 302) +      assert html_response(conn, 302)        assert redirected_to(conn) =~ ~r/#{redirect_uri}\?code=.+/      end @@ -182,7 +182,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do            }          ) -      assert response = html_response(conn, 302) +      assert html_response(conn, 302)        assert redirected_to(conn) == app.redirect_uris        assert get_flash(conn, :error) == "Failed to authenticate: (error description)."      end @@ -238,7 +238,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do            }          ) -      assert response = html_response(conn, 302) +      assert html_response(conn, 302)        assert redirected_to(conn) =~ ~r/#{redirect_uri}\?code=.+/      end @@ -268,7 +268,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do            }          ) -      assert response = html_response(conn, 401) +      assert html_response(conn, 401)      end      test "with invalid params, POST /oauth/register?op=register renders registration_details page", @@ -336,7 +336,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do            }          ) -      assert response = html_response(conn, 302) +      assert html_response(conn, 302)        assert redirected_to(conn) =~ ~r/#{redirect_uri}\?code=.+/      end @@ -367,7 +367,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do            }          ) -      assert response = html_response(conn, 401) +      assert html_response(conn, 401)      end      test "with invalid params, POST /oauth/register?op=connect renders registration_details page", diff --git a/test/pleroma/web/o_status/o_status_controller_test.exs b/test/pleroma/web/o_status/o_status_controller_test.exs index ee498f4b5..65b2c22db 100644 --- a/test/pleroma/web/o_status/o_status_controller_test.exs +++ b/test/pleroma/web/o_status/o_status_controller_test.exs @@ -7,7 +7,6 @@ defmodule Pleroma.Web.OStatus.OStatusControllerTest do    import Pleroma.Factory -  alias Pleroma.Config    alias Pleroma.Object    alias Pleroma.User    alias Pleroma.Web.ActivityPub.ActivityPub @@ -21,7 +20,7 @@ defmodule Pleroma.Web.OStatus.OStatusControllerTest do      :ok    end -  setup do: clear_config([:instance, :federating], true) +  setup do: clear_config([:static_fe, :enabled], false)    describe "Mastodon compatibility routes" do      setup %{conn: conn} do @@ -215,15 +214,16 @@ defmodule Pleroma.Web.OStatus.OStatusControllerTest do        assert response(conn, 404)      end -    test "it requires authentication if instance is NOT federating", %{ +    test "does not require authentication on non-federating instances", %{        conn: conn      } do -      user = insert(:user) +      clear_config([:instance, :federating], false)        note_activity = insert(:note_activity) -      conn = put_req_header(conn, "accept", "text/html") - -      ensure_federating_or_authenticated(conn, "/notice/#{note_activity.id}", user) +      conn +      |> put_req_header("accept", "text/html") +      |> get("/notice/#{note_activity.id}") +      |> response(200)      end    end @@ -325,14 +325,16 @@ defmodule Pleroma.Web.OStatus.OStatusControllerTest do        |> response(404)      end -    test "it requires authentication if instance is NOT federating", %{ +    test "does not require authentication on non-federating instances", %{        conn: conn,        note_activity: note_activity      } do -      user = insert(:user) -      conn = put_req_header(conn, "accept", "text/html") +      clear_config([:instance, :federating], false) -      ensure_federating_or_authenticated(conn, "/notice/#{note_activity.id}/embed_player", user) +      conn +      |> put_req_header("accept", "text/html") +      |> get("/notice/#{note_activity.id}/embed_player") +      |> response(200)      end    end  end diff --git a/test/pleroma/web/pleroma_api/controllers/emoji_pack_controller_test.exs b/test/pleroma/web/pleroma_api/controllers/emoji_pack_controller_test.exs index 386ad8634..3445f0ca0 100644 --- a/test/pleroma/web/pleroma_api/controllers/emoji_pack_controller_test.exs +++ b/test/pleroma/web/pleroma_api/controllers/emoji_pack_controller_test.exs @@ -569,7 +569,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do      test "for pack name with special chars", %{conn: conn} do        assert %{ -               "files" => files, +               "files" => _files,                 "files_count" => 1,                 "pack" => %{                   "can-download" => true, diff --git a/test/pleroma/web/pleroma_api/controllers/mascot_controller_test.exs b/test/pleroma/web/pleroma_api/controllers/mascot_controller_test.exs index d6be92869..289119d45 100644 --- a/test/pleroma/web/pleroma_api/controllers/mascot_controller_test.exs +++ b/test/pleroma/web/pleroma_api/controllers/mascot_controller_test.exs @@ -34,7 +34,7 @@ defmodule Pleroma.Web.PleromaAPI.MascotControllerTest do        |> put_req_header("content-type", "multipart/form-data")        |> put("/api/v1/pleroma/mascot", %{"file" => file}) -    assert %{"id" => _, "type" => image} = json_response_and_validate_schema(conn, 200) +    assert %{"id" => _, "type" => _image} = json_response_and_validate_schema(conn, 200)    end    test "mascot retrieving" do diff --git a/test/pleroma/web/plugs/frontend_static_plug_test.exs b/test/pleroma/web/plugs/frontend_static_plug_test.exs index f6f7d7bdb..8b7b022fc 100644 --- a/test/pleroma/web/plugs/frontend_static_plug_test.exs +++ b/test/pleroma/web/plugs/frontend_static_plug_test.exs @@ -4,6 +4,7 @@  defmodule Pleroma.Web.Plugs.FrontendStaticPlugTest do    use Pleroma.Web.ConnCase +  import Mock    @dir "test/tmp/instance_static" @@ -53,4 +54,24 @@ defmodule Pleroma.Web.Plugs.FrontendStaticPlugTest do      index = get(conn, "/pleroma/admin/")      assert html_response(index, 200) == "from frontend plug"    end + +  test "exclude invalid path", %{conn: conn} do +    name = "pleroma-fe" +    ref = "dist" +    clear_config([:media_proxy, :enabled], true) +    clear_config([Pleroma.Web.Endpoint, :secret_key_base], "00000000000") +    clear_config([:frontends, :primary], %{"name" => name, "ref" => ref}) +    path = "#{@dir}/frontends/#{name}/#{ref}" + +    File.mkdir_p!("#{path}/proxy/rr/ss") +    File.write!("#{path}/proxy/rr/ss/Ek7w8WPVcAApOvN.jpg:large", "FB image") + +    url = +      Pleroma.Web.MediaProxy.encode_url("https://pbs.twimg.com/media/Ek7w8WPVcAApOvN.jpg:large") + +    with_mock Pleroma.ReverseProxy, +      call: fn _conn, _url, _opts -> %Plug.Conn{status: :success} end do +      assert %Plug.Conn{status: :success} = get(conn, url) +    end +  end  end diff --git a/test/pleroma/web/static_fe/static_fe_controller_test.exs b/test/pleroma/web/static_fe/static_fe_controller_test.exs index f819a1e52..19506f1d8 100644 --- a/test/pleroma/web/static_fe/static_fe_controller_test.exs +++ b/test/pleroma/web/static_fe/static_fe_controller_test.exs @@ -6,14 +6,12 @@ defmodule Pleroma.Web.StaticFE.StaticFEControllerTest do    use Pleroma.Web.ConnCase    alias Pleroma.Activity -  alias Pleroma.Config    alias Pleroma.Web.ActivityPub.Transmogrifier    alias Pleroma.Web.CommonAPI    import Pleroma.Factory    setup_all do: clear_config([:static_fe, :enabled], true) -  setup do: clear_config([:instance, :federating], true)    setup %{conn: conn} do      conn = put_req_header(conn, "accept", "text/html") @@ -74,8 +72,27 @@ defmodule Pleroma.Web.StaticFE.StaticFEControllerTest do        refute html =~ ">test29<"      end -    test "it requires authentication if instance is NOT federating", %{conn: conn, user: user} do -      ensure_federating_or_authenticated(conn, "/users/#{user.nickname}", user) +    test "does not require authentication on non-federating instances", %{ +      conn: conn, +      user: user +    } do +      clear_config([:instance, :federating], false) + +      conn = get(conn, "/users/#{user.nickname}") + +      assert html_response(conn, 200) =~ user.nickname +    end + +    test "returns 404 for local user with `restrict_unauthenticated/profiles/local` setting", %{ +      conn: conn +    } do +      clear_config([:restrict_unauthenticated, :profiles, :local], true) + +      local_user = insert(:user, local: true) + +      conn +      |> get("/users/#{local_user.nickname}") +      |> html_response(404)      end    end @@ -187,10 +204,28 @@ defmodule Pleroma.Web.StaticFE.StaticFEControllerTest do        assert html_response(conn, 302) =~ "redirected"      end -    test "it requires authentication if instance is NOT federating", %{conn: conn, user: user} do +    test "does not require authentication on non-federating instances", %{ +      conn: conn, +      user: user +    } do +      clear_config([:instance, :federating], false) + +      {:ok, activity} = CommonAPI.post(user, %{status: "testing a thing!"}) + +      conn = get(conn, "/notice/#{activity.id}") + +      assert html_response(conn, 200) =~ "testing a thing!" +    end + +    test "returns 404 for local public activity with `restrict_unauthenticated/activities/local` setting", +         %{conn: conn, user: user} do +      clear_config([:restrict_unauthenticated, :activities, :local], true) +        {:ok, activity} = CommonAPI.post(user, %{status: "testing a thing!"}) -      ensure_federating_or_authenticated(conn, "/notice/#{activity.id}", user) +      conn +      |> get("/notice/#{activity.id}") +      |> html_response(404)      end    end  end diff --git a/test/support/channel_case.ex b/test/support/channel_case.ex index d63a0f06b..114184a9f 100644 --- a/test/support/channel_case.ex +++ b/test/support/channel_case.ex @@ -22,7 +22,7 @@ defmodule Pleroma.Web.ChannelCase do    using do      quote do        # Import conveniences for testing with channels -      use Phoenix.ChannelTest +      import Phoenix.ChannelTest        use Pleroma.Tests.Helpers        # The default endpoint for testing diff --git a/test/support/conn_case.ex b/test/support/conn_case.ex index 7ef681258..47cb65a80 100644 --- a/test/support/conn_case.ex +++ b/test/support/conn_case.ex @@ -22,7 +22,8 @@ defmodule Pleroma.Web.ConnCase do    using do      quote do        # Import conveniences for testing with connections -      use Phoenix.ConnTest +      import Plug.Conn +      import Phoenix.ConnTest        use Pleroma.Tests.Helpers        import Pleroma.Web.Router.Helpers @@ -111,28 +112,6 @@ defmodule Pleroma.Web.ConnCase do        defp json_response_and_validate_schema(conn, _status) do          flunk("Response schema not found for #{conn.method} #{conn.request_path} #{conn.status}")        end - -      defp ensure_federating_or_authenticated(conn, url, user) do -        initial_setting = Config.get([:instance, :federating]) -        on_exit(fn -> Config.put([:instance, :federating], initial_setting) end) - -        Config.put([:instance, :federating], false) - -        conn -        |> get(url) -        |> response(403) - -        conn -        |> assign(:user, user) -        |> get(url) -        |> response(200) - -        Config.put([:instance, :federating], true) - -        conn -        |> get(url) -        |> response(200) -      end      end    end  | 
