Merge branch 'develop' of git.pleroma.social:pleroma/pleroma into features/poll-valid...
authorlain <lain@soykaf.club>
Tue, 4 Aug 2020 13:28:41 +0000 (15:28 +0200)
committerlain <lain@soykaf.club>
Tue, 4 Aug 2020 13:28:41 +0000 (15:28 +0200)
39 files changed:
CHANGELOG.md
config/config.exs
config/description.exs
docs/API/pleroma_api.md
docs/clients.md
docs/configuration/cheatsheet.md
docs/configuration/howto_database_config.md
lib/pleroma/captcha/kocaptcha.ex
lib/pleroma/captcha/native.ex
lib/pleroma/following_relationship.ex
lib/pleroma/gun/connection_pool.ex
lib/pleroma/http/request_builder.ex
lib/pleroma/user.ex
lib/pleroma/user/welcome_chat_message.ex [new file with mode: 0644]
lib/pleroma/web/activity_pub/mrf/object_age_policy.ex
lib/pleroma/web/activity_pub/mrf/simple_policy.ex
lib/pleroma/web/api_spec/operations/account_operation.ex
lib/pleroma/web/api_spec/schemas/chat_message.ex
lib/pleroma/web/mastodon_api/controllers/account_controller.ex
lib/pleroma/web/mastodon_api/controllers/status_controller.ex
lib/pleroma/web/oauth/oauth_controller.ex
lib/pleroma/web/pleroma_api/controllers/emoji_reaction_controller.ex
lib/pleroma/web/pleroma_api/views/chat/message_reference_view.ex
lib/pleroma/web/rich_media/helpers.ex
mix.exs
mix.lock
test/captcha_test.exs
test/report_note_test.exs [new file with mode: 0644]
test/support/captcha_mock.ex
test/support/factory.ex
test/user/welcome_chat_massage_test.exs [new file with mode: 0644]
test/user_test.exs
test/web/activity_pub/mrf/object_age_policy_test.exs
test/web/activity_pub/mrf/simple_policy_test.exs
test/web/admin_api/controllers/report_controller_test.exs
test/web/mastodon_api/controllers/account_controller_test.exs
test/web/mastodon_api/controllers/status_controller_test.exs
test/web/pleroma_api/controllers/emoji_reaction_controller_test.exs
test/web/pleroma_api/views/chat/message_reference_view_test.exs

index 7d5256600df8986d5e5995d8667feddb28f0341b..de017e30aab54b6bf99a59117d97f3aba5c3c817 100644 (file)
@@ -33,6 +33,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
   contents has been renamed to `hide_notification_contents`
 - Mastodon API: Added `pleroma.metadata.post_formats` to /api/v1/instance
 - Mastodon API (legacy): Allow query parameters for `/api/v1/domain_blocks`, e.g. `/api/v1/domain_blocks?domain=badposters.zone`
+- Pleroma API: `/api/pleroma/captcha` responses now include `seconds_valid` with an integer value.
 </details>
 
 <details>
@@ -48,6 +49,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 
 ### Added
 
+- Configuration: Added a blacklist for email servers.
 - Chats: Added `accepts_chat_messages` field to user, exposed in APIs and federation.
 - Chats: Added support for federated chats. For details, see the docs.
 - ActivityPub: Added support for existing AP ids for instances migrated from Mastodon.
@@ -68,7 +70,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 - Support for viewing instances favicons next to posts and accounts
 - Added Pleroma.Upload.Filter.Exiftool as an alternate EXIF stripping mechanism targeting GPS/location metadata.
 - "By approval" registrations mode.
-- Configuration: Added `:welcome` settings for the welcome message to newly registered users.
+- Configuration: Added `:welcome` settings for the welcome message to newly registered users. You can send a welcome message as a direct message, chat or email.
+- Ability to hide favourites and emoji reactions in the API with `[:instance, :show_reactions]` config.
 
 <details>
   <summary>API Changes</summary>
index 4b91a58b746de9830726a80d8a8524e8a997852e..933a899ab77100b1c608d97f8b64ed64414df8eb 100644 (file)
@@ -172,7 +172,7 @@ config :mime, :types, %{
   "application/ld+json" => ["activity+json"]
 }
 
-config :tesla, adapter: Tesla.Adapter.Gun
+config :tesla, adapter: Tesla.Adapter.Hackney
 
 # Configures http settings, upstream proxy etc.
 config :pleroma, :http,
@@ -252,7 +252,8 @@ config :pleroma, :instance,
       number: 5,
       length: 16
     ]
-  ]
+  ],
+  show_reactions: true
 
 config :pleroma, :welcome,
   direct_message: [
@@ -260,6 +261,11 @@ config :pleroma, :welcome,
     sender_nickname: nil,
     message: nil
   ],
+  chat_message: [
+    enabled: false,
+    sender_nickname: nil,
+    message: nil
+  ],
   email: [
     enabled: false,
     sender: nil,
@@ -373,6 +379,7 @@ config :pleroma, :mrf_simple,
   federated_timeline_removal: [],
   report_removal: [],
   reject: [],
+  followers_only: [],
   accept: [],
   avatar_removal: [],
   banner_removal: [],
@@ -391,8 +398,9 @@ config :pleroma, :mrf_vocabulary,
   accept: [],
   reject: []
 
+# threshold of 7 days
 config :pleroma, :mrf_object_age,
-  threshold: 172_800,
+  threshold: 604_800,
   actions: [:delist, :strip_followers]
 
 config :pleroma, :rich_media,
@@ -508,7 +516,8 @@ config :pleroma, Pleroma.User,
     "user_exists",
     "users",
     "web"
-  ]
+  ],
+  email_blacklist: []
 
 config :pleroma, Oban,
   repo: Pleroma.Repo,
@@ -718,7 +727,7 @@ config :pleroma, :restrict_unauthenticated,
 config :pleroma, Pleroma.Web.ApiSpec.CastAndValidate, strict: false
 
 config :pleroma, :mrf,
-  policies: Pleroma.Web.ActivityPub.MRF.NoOpPolicy,
+  policies: Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy,
   transparency: true,
   transparency_exclusions: []
 
index 30a503696c2271a14738316d837e2f56a38610a6..d823812fbd33d4fba0f2e56662d3880606455e87 100644 (file)
@@ -955,6 +955,11 @@ config :pleroma, :config_description, [
         description:
           "The instance thumbnail can be any image that represents your instance and is used by some apps or services when they display information about your instance.",
         suggestions: ["/instance/thumbnail.jpeg"]
+      },
+      %{
+        key: :show_reactions,
+        type: :boolean,
+        description: "Let favourites and emoji reactions be viewed through the API."
       }
     ]
   },
@@ -992,6 +997,35 @@ config :pleroma, :config_description, [
           }
         ]
       },
+      %{
+        group: :chat_message,
+        type: :group,
+        descpiption: "Chat message settings",
+        children: [
+          %{
+            key: :enabled,
+            type: :boolean,
+            description: "Enables sends chat message for new user after registration"
+          },
+          %{
+            key: :message,
+            type: :string,
+            description:
+              "A message that will be sent to a newly registered users as a chat message",
+            suggestions: [
+              "Hello, welcome on board!"
+            ]
+          },
+          %{
+            key: :sender_nickname,
+            type: :string,
+            description: "The nickname of the local user that sends the welcome message",
+            suggestions: [
+              "lain"
+            ]
+          }
+        ]
+      },
       %{
         group: :email,
         type: :group,
@@ -1537,6 +1571,12 @@ config :pleroma, :config_description, [
         description: "List of instances to only accept activities from (except deletes)",
         suggestions: ["example.com", "*.example.com"]
       },
+      %{
+        key: :followers_only,
+        type: {:list, :string},
+        description: "Force posts from the given instances to be visible by followers only",
+        suggestions: ["example.com", "*.example.com"]
+      },
       %{
         key: :report_removal,
         type: {:list, :string},
@@ -3016,6 +3056,7 @@ config :pleroma, :config_description, [
       %{
         key: :restricted_nicknames,
         type: {:list, :string},
+        description: "List of nicknames users may not register with.",
         suggestions: [
           ".well-known",
           "~",
@@ -3048,6 +3089,12 @@ config :pleroma, :config_description, [
           "users",
           "web"
         ]
+      },
+      %{
+        key: :email_blacklist,
+        type: {:list, :string},
+        description: "List of email domains users may not register with.",
+        suggestions: ["mailinator.com", "maildrop.cc"]
       }
     ]
   },
index 5bd38ad364d9db7be00fbb0750a9de3ddbe1e1e8..4e97d26c052d0e0969cbe33f21db507139a9880e 100644 (file)
@@ -50,7 +50,7 @@ Request parameters can be passed via [query strings](https://en.wikipedia.org/wi
 * Authentication: not required
 * Params: none
 * Response: Provider specific JSON, the only guaranteed parameter is `type`
-* Example response: `{"type": "kocaptcha", "token": "whatever", "url": "https://captcha.kotobank.ch/endpoint"}`
+* Example response: `{"type": "kocaptcha", "token": "whatever", "url": "https://captcha.kotobank.ch/endpoint", "seconds_valid": 300}`
 
 ## `/api/pleroma/delete_account`
 ### Delete an account
index ea751637ec8051d097851f0ed1a85654ba75f0eb..2a42c659f7ce3e19e3c3f2565ed2c79ce608c82f 100644 (file)
@@ -75,6 +75,13 @@ Feel free to contact us to be added to this list!
 - Platform: Android, iOS
 - Features: No Streaming
 
+### Indigenous
+- Homepage: <https://indigenous.realize.be/>
+- Source Code: <https://github.com/swentel/indigenous-android/>
+- Contact: [@realize.be@realize.be](@realize.be@realize.be)
+- Platforms: Android
+- Features: No Streaming
+
 ## Alternative Web Interfaces
 ### Brutaldon
 - Homepage: <https://jfm.carcosa.net/projects/software/brutaldon/>
index d6a9276eeb6f7613b3c61f79c11da79ca3df156d..f23cf4fe4cb62e7366ee95a01c59d69bd7943cdf 100644 (file)
@@ -62,12 +62,17 @@ To add configuration to your config file, you can copy it from the base config.
 * `registration_reason_length`: Maximum registration reason length (default: `500`).
 * `external_user_synchronization`: Enabling following/followers counters synchronization for external users.
 * `cleanup_attachments`: Remove attachments along with statuses. Does not affect duplicate files and attachments without status. Enabling this will increase load to database when deleting statuses on larger instances.
+* `show_reactions`: Let favourites and emoji reactions be viewed through the API (default: `true`).
 
 ## Welcome
 * `direct_message`: - welcome message sent as a direct message.
   * `enabled`: Enables the send a direct message to a newly registered user. Defaults to `false`.
   * `sender_nickname`: The nickname of the local user that sends the welcome message.
   * `message`: A message that will be send to a newly registered users as a direct message.
+* `chat_message`: - welcome message sent as a chat message.
+  * `enabled`: Enables the send a chat message to a newly registered user. Defaults to `false`.
+  * `sender_nickname`: The nickname of the local user that sends the welcome message.
+  * `message`: A message that will be send to a newly registered users as a chat message.
 * `email`: - welcome message sent as a email.
   * `enabled`: Enables the send a welcome email to a newly registered user. Defaults to `false`.
   * `sender`: The email address or tuple with `{nickname, email}` that will use as sender to the welcome email.
@@ -124,6 +129,7 @@ To add configuration to your config file, you can copy it from the base config.
 * `federated_timeline_removal`: List of instances to remove from Federated (aka The Whole Known Network) Timeline.
 * `reject`: List of instances to reject any activities from.
 * `accept`: List of instances to accept any activities from.
+* `followers_only`: List of instances to decrease post visibility to only the followers, including for DM mentions.
 * `report_removal`: List of instances to reject reports from.
 * `avatar_removal`: List of instances to strip avatars from.
 * `banner_removal`: List of instances to strip banners from.
@@ -201,6 +207,11 @@ config :pleroma, :mrf_user_allowlist, %{
 * `sign_object_fetches`: Sign object fetches with HTTP signatures
 * `authorized_fetch_mode`: Require HTTP signatures for AP fetches
 
+## Pleroma.User
+
+* `restricted_nicknames`: List of nicknames users may not register with.
+* `email_blacklist`: List of email domains users may not register with.
+
 ## Pleroma.ScheduledActivity
 
 * `daily_user_limit`: the number of scheduled activities a user is allowed to create in a single day (Default: `25`)
index ded9a2eb3f3aeba7d5f228f355dfc112a828c446..9ed4d6cddd41d117339da3703dd24d5cbac07023 100644 (file)
@@ -5,13 +5,7 @@ The configuration of Pleroma has traditionally been managed with a config file,
 
 ## Migration to database config
 
-1. Stop your Pleroma instance and edit your Pleroma config to enable database configuration: 
-
-  ```
-  config :pleroma, configurable_from_database: true
-  ```
-
-2. Run the mix task to migrate to the database. You'll receive some debugging output and a few messages informing you of what happened.
+1. Run the mix task to migrate to the database. You'll receive some debugging output and a few messages informing you of what happened.
 
   **Source:**
   
@@ -23,76 +17,82 @@ The configuration of Pleroma has traditionally been managed with a config file,
   
   **OTP:**
   
+  *Note: OTP users need Pleroma to be running for `pleroma_ctl` commands to work*
+  
   ```
   $ ./bin/pleroma_ctl config migrate_to_db
   ```
 
-  ```  
-  10:04:34.155 [debug] QUERY OK source="config" db=1.6ms decode=2.0ms queue=33.5ms idle=0.0ms
-SELECT c0."id", c0."key", c0."group", c0."value", c0."inserted_at", c0."updated_at" FROM "config" AS c0 []
-Migrating settings from file: /home/pleroma/config/dev.secret.exs
-  
-  10:04:34.240 [debug] QUERY OK db=4.5ms queue=0.3ms idle=92.2ms
-TRUNCATE config; []
-  
-  10:04:34.244 [debug] QUERY OK db=2.8ms queue=0.3ms idle=97.2ms
-ALTER SEQUENCE config_id_seq RESTART; []
-  
-  10:04:34.256 [debug] QUERY OK source="config" db=0.8ms queue=1.4ms idle=109.8ms
-SELECT c0."id", c0."key", c0."group", c0."value", c0."inserted_at", c0."updated_at" FROM "config" AS c0 WHERE ((c0."group" = $1) AND (c0."key" = $2)) [":pleroma", ":instance"]
+  ```
+   10:04:34.155 [debug] QUERY OK source="config" db=1.6ms decode=2.0ms queue=33.5ms idle=0.0ms
+    SELECT c0."id", c0."key", c0."group", c0."value", c0."inserted_at", c0."updated_at" FROM "config" AS c0 []
+    Migrating settings from file: /home/pleroma/config/dev.secret.exs
+    
+   10:04:34.240 [debug] QUERY OK db=4.5ms queue=0.3ms idle=92.2ms
+    TRUNCATE config; []
   
-  10:04:34.292 [debug] QUERY OK db=2.6ms queue=1.7ms idle=137.7ms
-INSERT INTO "config" ("group","key","value","inserted_at","updated_at") VALUES ($1,$2,$3,$4,$5) RETURNING "id" [":pleroma", ":instance", <<131, 108, 0, 0, 0, 1, 104, 2, 100, 0, 4, 110, 97, 109, 101, 109, 0, 0, 0, 7, 66, 108, 101, 114, 111, 109, 97, 106>>, ~N[2020-07-12 15:04:34], ~N[2020-07-12 15:04:34]]
-  Settings for key instance migrated.
-  Settings for group :pleroma migrated.
+   10:04:34.244 [debug] QUERY OK db=2.8ms queue=0.3ms idle=97.2ms
+    ALTER SEQUENCE config_id_seq RESTART; []
+    
+   10:04:34.256 [debug] QUERY OK source="config" db=0.8ms queue=1.4ms idle=109.8ms
+   SELECT c0."id", c0."key", c0."group", c0."value", c0."inserted_at", c0."updated_at" FROM "config" AS c0 WHERE ((c0."group" = $1) AND (c0."key" = $2)) [":pleroma", ":instance"]
+    
+   10:04:34.292 [debug] QUERY OK db=2.6ms queue=1.7ms idle=137.7ms
+   INSERT INTO "config" ("group","key","value","inserted_at","updated_at") VALUES ($1,$2,$3,$4,$5) RETURNING "id" [":pleroma", ":instance", <<131, 108, 0, 0, 0, 1, 104, 2, 100, 0, 4, 110, 97, 109, 101, 109, 0, 0, 0, 7, 66, 108, 101, 114, 111, 109, 97, 106>>, ~N[2020-07-12 15:04:34], ~N[2020-07-12 15:04:34]]
+   Settings for key instance migrated.
+   Settings for group :pleroma migrated.
   ```
   
-3. It is recommended to backup your config file now.
+2. It is recommended to backup your config file now.
+
   ```
   cp config/dev.secret.exs config/dev.secret.exs.orig
   ```
   
-4. Now you can edit your config file and strip it down to the only settings which are not possible to control in the database. e.g., the Postgres and webserver (Endpoint) settings cannot be controlled in the database because the application needs the settings to start up and access the database.
+3. Edit your Pleroma config to enable database configuration:
 
- ⚠️ **THIS IS NOT REQUIRED**
- Any settings in the database will override those in the config file, but you may find it less confusing if the setting is only declared in one place.
-
- A non-exhaustive list of settings that are only possible in the config file include the following:
+  ```
+  config :pleroma, configurable_from_database: true
+  ```
 
-* config :pleroma, Pleroma.Web.Endpoint
-* config :pleroma, Pleroma.Repo
-* config :pleroma, configurable_from_database
-* config :pleroma, :database, rum_enabled
-* config :pleroma, :connections_pool
+4. ⚠️ **THIS IS NOT REQUIRED** ⚠️
 
-Here is an example of a server config stripped down after migration:
+  Now you can edit your config file and strip it down to the only settings which are not possible to control in the database. e.g., the Postgres (Repo) and webserver (Endpoint) settings cannot be controlled in the database because the application needs the settings to start up and access the database.
 
-```
-use Mix.Config
+  Any settings in the database will override those in the config file, but you may find it less confusing if the setting is only declared in one place.
 
-config :pleroma, Pleroma.Web.Endpoint,
-  url: [host: "cool.pleroma.site", scheme: "https", port: 443]
+  A non-exhaustive list of settings that are only possible in the config file include the following:
 
+  * config :pleroma, Pleroma.Web.Endpoint
+  * config :pleroma, Pleroma.Repo
+  * config :pleroma, configurable\_from\_database
+  * config :pleroma, :database, rum_enabled
+  * config :pleroma, :connections_pool
 
-config :pleroma, Pleroma.Repo,
-  adapter: Ecto.Adapters.Postgres,
-  username: "pleroma",
-  password: "MySecretPassword",
-  database: "pleroma_prod",
-  hostname: "localhost"
+  Here is an example of a server config stripped down after migration:
 
-config :pleroma, configurable_from_database: true
-```
+  ```
+  use Mix.Config
 
-5. Start your instance back up and you can now access the Settings tab in AdminFE.
+  config :pleroma, Pleroma.Web.Endpoint,
+    url: [host: "cool.pleroma.site", scheme: "https", port: 443]
+  
+  config :pleroma, Pleroma.Repo,
+    adapter: Ecto.Adapters.Postgres,
+    username: "pleroma",
+    password: "MySecretPassword",
+    database: "pleroma_prod",
+    hostname: "localhost"
+  
+  config :pleroma, configurable_from_database: true
+  ```
+5. Restart your instance and you can now access the Settings tab in AdminFE.
 
 
 ## Reverting back from database config
 
-1. Stop your Pleroma instance.
-
-2. Run the mix task to migrate back from the database. You'll receive some debugging output and a few messages informing you of what happened.
+1. Run the mix task to migrate back from the database. You'll receive some debugging output and a few messages informing you of what happened.
 
   **Source:**
   
@@ -110,14 +110,16 @@ config :pleroma, configurable_from_database: true
 
   ```
   10:26:30.593 [debug] QUERY OK source="config" db=9.8ms decode=1.2ms queue=26.0ms idle=0.0ms
-SELECT c0."id", c0."key", c0."group", c0."value", c0."inserted_at", c0."updated_at" FROM "config" AS c0 []
-
+  SELECT c0."id", c0."key", c0."group", c0."value", c0."inserted_at", c0."updated_at" FROM "config" AS c0 []
+  
   10:26:30.659 [debug] QUERY OK source="config" db=1.1ms idle=80.7ms
-SELECT c0."id", c0."key", c0."group", c0."value", c0."inserted_at", c0."updated_at" FROM "config" AS c0 []
-Database configuration settings have been saved to config/dev.exported_from_db.secret.exs
-```
+  SELECT c0."id", c0."key", c0."group", c0."value", c0."inserted_at", c0."updated_at" FROM "config" AS c0 []
+  Database configuration settings have been saved to config/dev.exported_from_db.secret.exs
+  ```
+
+2. Remove `config :pleroma, configurable_from_database: true` from your config. The in-database configuration still exists, but it will not be used. Future migrations will erase the database config before importing your config file again.
 
-3. The in-database configuration still exists, but it will not be used if you remove `config :pleroma, configurable_from_database: true` from your config.
+3. Restart your instance.
 
 ## Debugging
 
index 6bc2fa158a2045182b9641c2f04166e168eaded7..337506647b373c21b9532bb924464982eeceaefb 100644 (file)
@@ -21,7 +21,8 @@ defmodule Pleroma.Captcha.Kocaptcha do
           type: :kocaptcha,
           token: json_resp["token"],
           url: endpoint <> json_resp["url"],
-          answer_data: json_resp["md5"]
+          answer_data: json_resp["md5"],
+          seconds_valid: Pleroma.Config.get([Pleroma.Captcha, :seconds_valid])
         }
     end
   end
index a90631d61be6e66b78cfbf4b30886aa788849427..8d604d2b2c00dd5af16759c7e8130bdc791914ce 100644 (file)
@@ -17,7 +17,8 @@ defmodule Pleroma.Captcha.Native do
           type: :native,
           token: token(),
           url: "data:image/png;base64," <> Base.encode64(img_binary),
-          answer_data: answer_data
+          answer_data: answer_data,
+          seconds_valid: Pleroma.Config.get([Pleroma.Captcha, :seconds_valid])
         }
     end
   end
index c2020d30a876a9169682f8271861d9e808165bf2..83b366dd406fc1fe8b6af93190268ff6d4694c4f 100644 (file)
@@ -95,7 +95,11 @@ defmodule Pleroma.FollowingRelationship do
     |> where([r], r.state == ^:follow_accept)
   end
 
-  def followers_ap_ids(%User{} = user, from_ap_ids \\ nil) do
+  def followers_ap_ids(user, from_ap_ids \\ nil)
+
+  def followers_ap_ids(_, []), do: []
+
+  def followers_ap_ids(%User{} = user, from_ap_ids) do
     query =
       user
       |> followers_query()
index 49e9885bbac3b82d224c901c458a7c41d5225901..f34602b73cd513239c956ca62174534159e84194 100644 (file)
@@ -10,6 +10,7 @@ defmodule Pleroma.Gun.ConnectionPool do
     ]
   end
 
+  @spec get_conn(URI.t(), keyword()) :: {:ok, pid()} | {:error, term()}
   def get_conn(uri, opts) do
     key = "#{uri.scheme}:#{uri.host}:#{uri.port}"
 
@@ -54,12 +55,14 @@ defmodule Pleroma.Gun.ConnectionPool do
 
       {:DOWN, ^ref, :process, ^worker_pid, reason} ->
         case reason do
-          {:shutdown, error} -> error
+          {:shutdown, {:error, _} = error} -> error
+          {:shutdown, error} -> {:error, error}
           _ -> {:error, reason}
         end
     end
   end
 
+  @spec release_conn(pid()) :: :ok
   def release_conn(conn_pid) do
     # :ets.fun2ms(fn {_, {worker_pid, {gun_pid, _, _, _}}} when gun_pid == conn_pid ->
     #    worker_pid end)
index 2fc876d924017f9d55a8d5d9cf3dd108e22fff02..8a44a001dbabc87e41f4f17936d5879af343cda6 100644 (file)
@@ -34,10 +34,12 @@ defmodule Pleroma.HTTP.RequestBuilder do
   @spec headers(Request.t(), Request.headers()) :: Request.t()
   def headers(request, headers) do
     headers_list =
-      if Pleroma.Config.get([:http, :send_user_agent]) do
+      with true <- Pleroma.Config.get([:http, :send_user_agent]),
+           nil <- Enum.find(headers, fn {key, _val} -> String.downcase(key) == "user-agent" end) do
         [{"user-agent", Pleroma.Application.user_agent()} | headers]
       else
-        headers
+        _ ->
+          headers
       end
 
     %{request | headers: headers_list}
index dcf6ebee2e4a46d8c6f4150e03a8fd4c7d561fac..09e606b370392fdae75970f692d7adf9aca6c5db 100644 (file)
@@ -676,10 +676,19 @@ defmodule Pleroma.User do
     |> validate_required([:name, :nickname, :password, :password_confirmation])
     |> validate_confirmation(:password)
     |> unique_constraint(:email)
+    |> validate_format(:email, @email_regex)
+    |> validate_change(:email, fn :email, email ->
+      valid? =
+        Config.get([User, :email_blacklist])
+        |> Enum.all?(fn blacklisted_domain ->
+          !String.ends_with?(email, ["@" <> blacklisted_domain, "." <> blacklisted_domain])
+        end)
+
+      if valid?, do: [], else: [email: "Invalid email"]
+    end)
     |> unique_constraint(:nickname)
     |> validate_exclusion(:nickname, Config.get([User, :restricted_nicknames]))
     |> validate_format(:nickname, local_nickname_regex())
-    |> validate_format(:email, @email_regex)
     |> validate_length(:bio, max: bio_limit)
     |> validate_length(:name, min: 1, max: name_limit)
     |> validate_length(:registration_reason, max: reason_limit)
@@ -734,6 +743,7 @@ defmodule Pleroma.User do
          {:ok, user} <- set_cache(user),
          {:ok, _} <- send_welcome_email(user),
          {:ok, _} <- send_welcome_message(user),
+         {:ok, _} <- send_welcome_chat_message(user),
          {:ok, _} <- try_send_confirmation_email(user) do
       {:ok, user}
     end
@@ -748,6 +758,15 @@ defmodule Pleroma.User do
     end
   end
 
+  def send_welcome_chat_message(user) do
+    if User.WelcomeChatMessage.enabled?() do
+      User.WelcomeChatMessage.post_message(user)
+      {:ok, :enqueued}
+    else
+      {:ok, :noop}
+    end
+  end
+
   def send_welcome_email(%User{email: email} = user) when is_binary(email) do
     if User.WelcomeEmail.enabled?() do
       User.WelcomeEmail.send_email(user)
diff --git a/lib/pleroma/user/welcome_chat_message.ex b/lib/pleroma/user/welcome_chat_message.ex
new file mode 100644 (file)
index 0000000..3e7d1f4
--- /dev/null
@@ -0,0 +1,45 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.User.WelcomeChatMessage do
+  alias Pleroma.Config
+  alias Pleroma.User
+  alias Pleroma.Web.CommonAPI
+
+  @spec enabled?() :: boolean()
+  def enabled?, do: Config.get([:welcome, :chat_message, :enabled], false)
+
+  @spec post_message(User.t()) :: {:ok, Pleroma.Activity.t() | nil}
+  def post_message(user) do
+    [:welcome, :chat_message, :sender_nickname]
+    |> Config.get(nil)
+    |> fetch_sender()
+    |> do_post(user, welcome_message())
+  end
+
+  defp do_post(%User{} = sender, recipient, message)
+       when is_binary(message) do
+    CommonAPI.post_chat_message(
+      sender,
+      recipient,
+      message
+    )
+  end
+
+  defp do_post(_sender, _recipient, _message), do: {:ok, nil}
+
+  defp fetch_sender(nickname) when is_binary(nickname) do
+    with %User{local: true} = user <- User.get_cached_by_nickname(nickname) do
+      user
+    else
+      _ -> nil
+    end
+  end
+
+  defp fetch_sender(_), do: nil
+
+  defp welcome_message do
+    Config.get([:welcome, :chat_message, :message], nil)
+  end
+end
index 5f111c72f552ccbf1265bb9230c4cd58a89fdcfb..d45d2d7e36ef2ce1644d569cf4fae60f0fb2c740 100644 (file)
@@ -37,8 +37,13 @@ defmodule Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy do
   defp check_delist(message, actions) do
     if :delist in actions do
       with %User{} = user <- User.get_cached_by_ap_id(message["actor"]) do
-        to = List.delete(message["to"], Pleroma.Constants.as_public()) ++ [user.follower_address]
-        cc = List.delete(message["cc"], user.follower_address) ++ [Pleroma.Constants.as_public()]
+        to =
+          List.delete(message["to"] || [], Pleroma.Constants.as_public()) ++
+            [user.follower_address]
+
+        cc =
+          List.delete(message["cc"] || [], user.follower_address) ++
+            [Pleroma.Constants.as_public()]
 
         message =
           message
@@ -58,8 +63,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy do
   defp check_strip_followers(message, actions) do
     if :strip_followers in actions do
       with %User{} = user <- User.get_cached_by_ap_id(message["actor"]) do
-        to = List.delete(message["to"], user.follower_address)
-        cc = List.delete(message["cc"], user.follower_address)
+        to = List.delete(message["to"] || [], user.follower_address)
+        cc = List.delete(message["cc"] || [], user.follower_address)
 
         message =
           message
index b77b8c7b49eb2254d9fe3612d61d616f819bd214..bb193475ab12a47f0aa6967584368b36b3373f33 100644 (file)
@@ -7,6 +7,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
   @behaviour Pleroma.Web.ActivityPub.MRF
 
   alias Pleroma.Config
+  alias Pleroma.FollowingRelationship
   alias Pleroma.User
   alias Pleroma.Web.ActivityPub.MRF
 
@@ -108,6 +109,35 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
     {:ok, object}
   end
 
+  defp intersection(list1, list2) do
+    list1 -- list1 -- list2
+  end
+
+  defp check_followers_only(%{host: actor_host} = _actor_info, object) do
+    followers_only =
+      Config.get([:mrf_simple, :followers_only])
+      |> MRF.subdomains_regex()
+
+    object =
+      with true <- MRF.subdomain_match?(followers_only, actor_host),
+           user <- User.get_cached_by_ap_id(object["actor"]) do
+        # Don't use Map.get/3 intentionally, these must not be nil
+        fixed_to = object["to"] || []
+        fixed_cc = object["cc"] || []
+
+        to = FollowingRelationship.followers_ap_ids(user, fixed_to)
+        cc = FollowingRelationship.followers_ap_ids(user, fixed_cc)
+
+        object
+        |> Map.put("to", intersection([user.follower_address | to], fixed_to))
+        |> Map.put("cc", intersection([user.follower_address | cc], fixed_cc))
+      else
+        _ -> object
+      end
+
+    {:ok, object}
+  end
+
   defp check_report_removal(%{host: actor_host} = _actor_info, %{"type" => "Flag"} = object) do
     report_removal =
       Config.get([:mrf_simple, :report_removal])
@@ -174,6 +204,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
          {:ok, object} <- check_media_removal(actor_info, object),
          {:ok, object} <- check_media_nsfw(actor_info, object),
          {:ok, object} <- check_ftl_removal(actor_info, object),
+         {:ok, object} <- check_followers_only(actor_info, object),
          {:ok, object} <- check_report_removal(actor_info, object) do
       {:ok, object}
     else
index 50c8e0242e0b161bda0787bbff5b4cb3dd2e82e1..aaebc9b5cb72c3e3f991f64eb14c6dc6f16fca41 100644 (file)
@@ -449,21 +449,32 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
     }
   end
 
-  # TODO: This is actually a token respone, but there's no oauth operation file yet.
+  # Note: this is a token response (if login succeeds!), but there's no oauth operation file yet.
   defp create_response do
     %Schema{
       title: "AccountCreateResponse",
       description: "Response schema for an account",
       type: :object,
       properties: %{
+        # The response when auto-login on create succeeds (token is issued):
         token_type: %Schema{type: :string},
         access_token: %Schema{type: :string},
         refresh_token: %Schema{type: :string},
         scope: %Schema{type: :string},
         created_at: %Schema{type: :integer, format: :"date-time"},
         me: %Schema{type: :string},
-        expires_in: %Schema{type: :integer}
+        expires_in: %Schema{type: :integer},
+        #
+        # The response when registration succeeds but auto-login fails (no token):
+        identifier: %Schema{type: :string},
+        message: %Schema{type: :string}
       },
+      required: [],
+      # Note: example of successful registration with failed login response:
+      # example: %{
+      #   "identifier" => "missing_confirmed_email",
+      #   "message" => "You have been registered. Please check your email for further instructions."
+      # },
       example: %{
         "token_type" => "Bearer",
         "access_token" => "i9hAVVzGld86Pl5JtLtizKoXVvtTlSCJvwaugCxvZzk",
index 3ee85aa761928c632d774cf88603dfa56ce650b9..bbf2a442703d15553a9e753ee255daed0a59ec7a 100644 (file)
@@ -19,13 +19,46 @@ defmodule Pleroma.Web.ApiSpec.Schemas.ChatMessage do
       content: %Schema{type: :string, nullable: true},
       created_at: %Schema{type: :string, format: :"date-time"},
       emojis: %Schema{type: :array},
-      attachment: %Schema{type: :object, nullable: true}
+      attachment: %Schema{type: :object, nullable: true},
+      card: %Schema{
+        type: :object,
+        nullable: true,
+        description: "Preview card for links included within status content",
+        required: [:url, :title, :description, :type],
+        properties: %{
+          type: %Schema{
+            type: :string,
+            enum: ["link", "photo", "video", "rich"],
+            description: "The type of the preview card"
+          },
+          provider_name: %Schema{
+            type: :string,
+            nullable: true,
+            description: "The provider of the original resource"
+          },
+          provider_url: %Schema{
+            type: :string,
+            format: :uri,
+            description: "A link to the provider of the original resource"
+          },
+          url: %Schema{type: :string, format: :uri, description: "Location of linked resource"},
+          image: %Schema{
+            type: :string,
+            nullable: true,
+            format: :uri,
+            description: "Preview thumbnail"
+          },
+          title: %Schema{type: :string, description: "Title of linked resource"},
+          description: %Schema{type: :string, description: "Description of preview"}
+        }
+      }
     },
     example: %{
       "account_id" => "someflakeid",
       "chat_id" => "1",
       "content" => "hey you again",
       "created_at" => "2020-04-21T15:06:45.000Z",
+      "card" => nil,
       "emojis" => [
         %{
           "static_url" => "https://dontbulling.me/emoji/Firefox.gif",
index fe5d022f55fe85e959fecc3006eb4f8d484c1aa5..f45678184eeee58985fbddc30f3d5e9d24e38bca 100644 (file)
@@ -27,8 +27,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
   alias Pleroma.Web.MastodonAPI.MastodonAPI
   alias Pleroma.Web.MastodonAPI.MastodonAPIController
   alias Pleroma.Web.MastodonAPI.StatusView
+  alias Pleroma.Web.OAuth.OAuthController
   alias Pleroma.Web.OAuth.OAuthView
-  alias Pleroma.Web.OAuth.Token
   alias Pleroma.Web.TwitterAPI.TwitterAPI
 
   plug(Pleroma.Web.ApiSpec.CastAndValidate)
@@ -100,11 +100,34 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
   def create(%{assigns: %{app: app}, body_params: params} = conn, _params) do
     with :ok <- validate_email_param(params),
          :ok <- TwitterAPI.validate_captcha(app, params),
-         {:ok, user} <- TwitterAPI.register_user(params, need_confirmation: true),
-         {:ok, token} <- Token.create_token(app, user, %{scopes: app.scopes}) do
+         {:ok, user} <- TwitterAPI.register_user(params),
+         {_, {:ok, token}} <-
+           {:login, OAuthController.login(user, app, app.scopes)} do
       json(conn, OAuthView.render("token.json", %{user: user, token: token}))
     else
-      {:error, error} -> json_response(conn, :bad_request, %{error: error})
+      {:login, {:account_status, :confirmation_pending}} ->
+        json_response(conn, :ok, %{
+          message: "You have been registered. Please check your email for further instructions.",
+          identifier: "missing_confirmed_email"
+        })
+
+      {:login, {:account_status, :approval_pending}} ->
+        json_response(conn, :ok, %{
+          message:
+            "You have been registered. You'll be able to log in once your account is approved.",
+          identifier: "awaiting_approval"
+        })
+
+      {:login, _} ->
+        json_response(conn, :ok, %{
+          message:
+            "You have been registered. Some post-registration steps may be pending. " <>
+              "Please log in manually.",
+          identifier: "manual_login_required"
+        })
+
+      {:error, error} ->
+        json_response(conn, :bad_request, %{error: error})
     end
   end
 
index 9bb2ef117b414f15b40ca78fd3e729d5adf25029..ecfa38489837eadae7b299324fb6ebe8cf60dbc2 100644 (file)
@@ -314,7 +314,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
 
   @doc "GET /api/v1/statuses/:id/favourited_by"
   def favourited_by(%{assigns: %{user: user}} = conn, %{id: id}) do
-    with %Activity{} = activity <- Activity.get_by_id_with_object(id),
+    with true <- Pleroma.Config.get([:instance, :show_reactions]),
+         %Activity{} = activity <- Activity.get_by_id_with_object(id),
          {:visible, true} <- {:visible, Visibility.visible_for_user?(activity, user)},
          %Object{data: %{"likes" => likes}} <- Object.normalize(activity) do
       users =
index 61fe81d331fc0bc0e40e0a099aa86ee533df242d..f29b3cb5705f7d46160f8dc70167f5e32322d322 100644 (file)
@@ -260,11 +260,8 @@ defmodule Pleroma.Web.OAuth.OAuthController do
       ) do
     with {:ok, %User{} = user} <- Authenticator.get_user(conn),
          {:ok, app} <- Token.Utils.fetch_app(conn),
-         {:account_status, :active} <- {:account_status, User.account_status(user)},
-         {:ok, scopes} <- validate_scopes(app, params),
-         {:ok, auth} <- Authorization.create_authorization(app, user, scopes),
-         {:mfa_required, _, _, false} <- {:mfa_required, user, auth, MFA.require?(user)},
-         {:ok, token} <- Token.exchange_token(app, auth) do
+         requested_scopes <- Scopes.fetch_scopes(params, app.scopes),
+         {:ok, token} <- login(user, app, requested_scopes) do
       json(conn, OAuthView.render("token.json", %{user: user, token: token}))
     else
       error ->
@@ -522,6 +519,8 @@ defmodule Pleroma.Web.OAuth.OAuthController do
     end
   end
 
+  defp do_create_authorization(conn, auth_attrs, user \\ nil)
+
   defp do_create_authorization(
          %Plug.Conn{} = conn,
          %{
@@ -531,19 +530,37 @@ defmodule Pleroma.Web.OAuth.OAuthController do
                "redirect_uri" => redirect_uri
              } = auth_attrs
          },
-         user \\ nil
+         user
        ) do
     with {_, {:ok, %User{} = user}} <-
            {:get_user, (user && {:ok, user}) || Authenticator.get_user(conn)},
          %App{} = app <- Repo.get_by(App, client_id: client_id),
          true <- redirect_uri in String.split(app.redirect_uris),
-         {:ok, scopes} <- validate_scopes(app, auth_attrs),
-         {:account_status, :active} <- {:account_status, User.account_status(user)},
-         {:ok, auth} <- Authorization.create_authorization(app, user, scopes) do
+         requested_scopes <- Scopes.fetch_scopes(auth_attrs, app.scopes),
+         {:ok, auth} <- do_create_authorization(user, app, requested_scopes) do
       {:ok, auth, user}
     end
   end
 
+  defp do_create_authorization(%User{} = user, %App{} = app, requested_scopes)
+       when is_list(requested_scopes) do
+    with {:account_status, :active} <- {:account_status, User.account_status(user)},
+         {:ok, scopes} <- validate_scopes(app, requested_scopes),
+         {:ok, auth} <- Authorization.create_authorization(app, user, scopes) do
+      {:ok, auth}
+    end
+  end
+
+  # Note: intended to be a private function but opened for AccountController that logs in on signup
+  @doc "If checks pass, creates authorization and token for given user, app and requested scopes."
+  def login(%User{} = user, %App{} = app, requested_scopes) when is_list(requested_scopes) do
+    with {:ok, auth} <- do_create_authorization(user, app, requested_scopes),
+         {:mfa_required, _, _, false} <- {:mfa_required, user, auth, MFA.require?(user)},
+         {:ok, token} <- Token.exchange_token(app, auth) do
+      {:ok, token}
+    end
+  end
+
   # Special case: Local MastodonFE
   defp redirect_uri(%Plug.Conn{} = conn, "."), do: auth_url(conn, :login)
 
@@ -560,12 +577,15 @@ defmodule Pleroma.Web.OAuth.OAuthController do
     end
   end
 
-  @spec validate_scopes(App.t(), map()) ::
+  @spec validate_scopes(App.t(), map() | list()) ::
           {:ok, list()} | {:error, :missing_scopes | :unsupported_scopes}
-  defp validate_scopes(%App{} = app, params) do
-    params
-    |> Scopes.fetch_scopes(app.scopes)
-    |> Scopes.validate(app.scopes)
+  defp validate_scopes(%App{} = app, params) when is_map(params) do
+    requested_scopes = Scopes.fetch_scopes(params, app.scopes)
+    validate_scopes(app, requested_scopes)
+  end
+
+  defp validate_scopes(%App{} = app, requested_scopes) when is_list(requested_scopes) do
+    Scopes.validate(requested_scopes, app.scopes)
   end
 
   def default_redirect_uri(%App{} = app) do
index 19dcffdf344f72210c5424468304f4bd09de1585..7f9254c135dc7e8f80d88f6366ac81c9a342d0c5 100644 (file)
@@ -25,7 +25,8 @@ defmodule Pleroma.Web.PleromaAPI.EmojiReactionController do
   action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
 
   def index(%{assigns: %{user: user}} = conn, %{id: activity_id} = params) do
-    with %Activity{} = activity <- Activity.get_by_id_with_object(activity_id),
+    with true <- Pleroma.Config.get([:instance, :show_reactions]),
+         %Activity{} = activity <- Activity.get_by_id_with_object(activity_id),
          %Object{data: %{"reactions" => reactions}} when is_list(reactions) <-
            Object.normalize(activity) do
       reactions = filter(reactions, params)
index f2112a86ed5fbd8f5dcaabd44bb17e726c94e1f7..d4e08b50db95fdbb93abd03354307caf7942280e 100644 (file)
@@ -14,7 +14,7 @@ defmodule Pleroma.Web.PleromaAPI.Chat.MessageReferenceView do
         %{
           chat_message_reference: %{
             id: id,
-            object: %{data: chat_message},
+            object: %{data: chat_message} = object,
             chat_id: chat_id,
             unread: unread
           }
@@ -30,7 +30,12 @@ defmodule Pleroma.Web.PleromaAPI.Chat.MessageReferenceView do
       attachment:
         chat_message["attachment"] &&
           StatusView.render("attachment.json", attachment: chat_message["attachment"]),
-      unread: unread
+      unread: unread,
+      card:
+        StatusView.render(
+          "card.json",
+          Pleroma.Web.RichMedia.Helpers.fetch_data_for_object(object)
+        )
     }
   end
 
index 747f2dc6be5a2e22832b364c7ed93f15b4aaf512..5c7daf1a51429743808b373b58a41b6b2adce33a 100644 (file)
@@ -49,11 +49,11 @@ defmodule Pleroma.Web.RichMedia.Helpers do
     |> hd
   end
 
-  def fetch_data_for_activity(%Activity{data: %{"type" => "Create"}} = activity) do
+  def fetch_data_for_object(object) do
     with true <- Config.get([:rich_media, :enabled]),
-         %Object{} = object <- Object.normalize(activity),
          false <- object.data["sensitive"] || false,
-         {:ok, page_url} <- HTML.extract_first_external_url(object, object.data["content"]),
+         {:ok, page_url} <-
+           HTML.extract_first_external_url(object, object.data["content"]),
          :ok <- validate_page_url(page_url),
          {:ok, rich_media} <- Parser.parse(page_url) do
       %{page_url: page_url, rich_media: rich_media}
@@ -62,6 +62,15 @@ defmodule Pleroma.Web.RichMedia.Helpers do
     end
   end
 
+  def fetch_data_for_activity(%Activity{data: %{"type" => "Create"}} = activity) do
+    with true <- Config.get([:rich_media, :enabled]),
+         %Object{} = object <- Object.normalize(activity) do
+      fetch_data_for_object(object)
+    else
+      _ -> %{}
+    end
+  end
+
   def fetch_data_for_activity(_), do: %{}
 
   def perform(:fetch, %Activity{} = activity) do
diff --git a/mix.exs b/mix.exs
index a14b0c51a350fea0bff83b69056792a1f1219ca0..0e723c15f28542d2f171ae567b22a9a4873c57ec 100644 (file)
--- a/mix.exs
+++ b/mix.exs
@@ -114,63 +114,52 @@ defmodule Pleroma.Mixfile do
   # Type `mix help deps` for examples and options.
   defp deps do
     [
-      {:phoenix, "~> 1.4.8"},
+      {:phoenix, "~> 1.4.17"},
       {:tzdata, "~> 1.0.3"},
-      {:plug_cowboy, "~> 2.0"},
+      {:plug_cowboy, "~> 2.3"},
       {:phoenix_pubsub, "~> 1.1"},
       {:phoenix_ecto, "~> 4.0"},
       {:ecto_enum, "~> 1.4"},
       {:ecto_sql, "~> 3.4.4"},
-      {:postgrex, ">= 0.13.5"},
+      {:postgrex, ">= 0.15.5"},
       {:oban, "~> 2.0.0"},
-      {:gettext, "~> 0.15"},
-      {:pbkdf2_elixir, "~> 1.0"},
-      {:bcrypt_elixir, "~> 2.0"},
+      {:gettext, "~> 0.18"},
+      {:pbkdf2_elixir, "~> 1.2"},
+      {:bcrypt_elixir, "~> 2.2"},
       {:trailing_format_plug, "~> 0.0.7"},
       {:fast_sanitize, "~> 0.1"},
       {:html_entities, "~> 0.5", override: true},
-      {:phoenix_html, "~> 2.10"},
-      {:calendar, "~> 0.17.4"},
+      {:phoenix_html, "~> 2.14"},
+      {:calendar, "~> 1.0"},
       {:cachex, "~> 3.2"},
       {:poison, "~> 3.0", override: true},
-      # {:tesla, "~> 1.3", override: true},
       {:tesla,
        github: "teamon/tesla", ref: "af3707078b10793f6a534938e56b963aff82fe3c", override: true},
       {:castore, "~> 0.1"},
-      {:cowlib, "~> 2.8", override: true},
+      {:cowlib, "~> 2.9", override: true},
       {:gun,
        github: "ninenines/gun", ref: "921c47146b2d9567eac7e9a4d2ccc60fffd4f327", override: true},
-      {:jason, "~> 1.0"},
-      {:mogrify, "~> 0.6.1"},
+      {:jason, "~> 1.2"},
+      {:mogrify, "~> 0.7.4"},
       {:ex_aws, "~> 2.1"},
       {:ex_aws_s3, "~> 2.0"},
       {:sweet_xml, "~> 0.6.6"},
       {:earmark, "1.4.3"},
       {:bbcode_pleroma, "~> 0.2.0"},
-      {:ex_machina, "~> 2.3", only: :test},
-      {:credo, "~> 1.1.0", only: [:dev, :test], runtime: false},
-      {:mock, "~> 0.3.3", only: :test},
       {:crypt,
        git: "https://github.com/msantos/crypt.git",
        ref: "f63a705f92c26955977ee62a313012e309a4d77a"},
-      {:cors_plug, "~> 1.5"},
-      {:ex_doc, "~> 0.21", only: :dev, runtime: false},
-      {:web_push_encryption, "~> 0.2.1"},
-      {:swoosh,
-       git: "https://github.com/swoosh/swoosh.git",
-       ref: "c96e0ca8a00d8f211ec1f042a4626b09f249caa5",
-       override: true},
-      {:phoenix_swoosh, "~> 0.2"},
+      {:cors_plug, "~> 2.0"},
+      {:web_push_encryption, "~> 0.3"},
+      {:swoosh, "~> 1.0"},
+      {:phoenix_swoosh, "~> 0.3"},
       {:gen_smtp, "~> 0.13"},
-      {:websocket_client, git: "https://github.com/jeremyong/websocket_client.git", only: :test},
       {:ex_syslogger, "~> 1.4"},
-      {:floki, "~> 0.25"},
-      {:timex, "~> 3.5"},
+      {:floki, "~> 0.27"},
+      {:timex, "~> 3.6"},
       {:ueberauth, "~> 0.4"},
       {:linkify, "~> 0.2.0"},
-      {:http_signatures,
-       git: "https://git.pleroma.social/pleroma/http_signatures.git",
-       ref: "293d77bb6f4a67ac8bde1428735c3b42f22cbb30"},
+      {:http_signatures, "~> 0.1.0"},
       {:telemetry, "~> 0.3"},
       {:poolboy, "~> 1.5"},
       {:prometheus, "~> 4.6"},
@@ -182,26 +171,33 @@ defmodule Pleroma.Mixfile do
       {:quack, "~> 0.1.1"},
       {:joken, "~> 2.0"},
       {:benchee, "~> 1.0"},
-      {:pot, "~> 0.10.2"},
+      {:pot, "~> 0.11"},
       {:esshd, "~> 0.1.0", runtime: Application.get_env(:esshd, :enabled, false)},
       {:ex_const, "~> 0.2"},
       {:plug_static_index_html, "~> 1.0.0"},
-      {:excoveralls, "~> 0.12.1", only: :test},
       {:flake_id, "~> 0.1.0"},
       {:concurrent_limiter,
        git: "https://git.pleroma.social/pleroma/elixir-libraries/concurrent_limiter.git",
-       ref: "8eee96c6ba39b9286ec44c51c52d9f2758951365"},
+       ref: "55e92f84b4ed531bd487952a71040a9c69dc2807"},
       {:remote_ip,
        git: "https://git.pleroma.social/pleroma/remote_ip.git",
        ref: "b647d0deecaa3acb140854fe4bda5b7e1dc6d1c8"},
       {:captcha,
        git: "https://git.pleroma.social/pleroma/elixir-libraries/elixir-captcha.git",
        ref: "e0f16822d578866e186a0974d65ad58cddc1e2ab"},
-      {:mox, "~> 0.5", only: :test},
       {:restarter, path: "./restarter"},
       {:open_api_spex,
        git: "https://git.pleroma.social/pleroma/elixir-libraries/open_api_spex.git",
-       ref: "f296ac0924ba3cf79c7a588c4c252889df4c2edd"}
+       ref: "f296ac0924ba3cf79c7a588c4c252889df4c2edd"},
+
+      ## dev & test
+      {:ex_doc, "~> 0.22", only: :dev, runtime: false},
+      {:ex_machina, "~> 2.4", only: :test},
+      {:credo, "~> 1.4", only: [:dev, :test], runtime: false},
+      {:mock, "~> 0.3.5", only: :test},
+      {:excoveralls, "~> 0.13.1", only: :test},
+      {:mox, "~> 0.5", only: :test},
+      {:websocket_client, git: "https://github.com/jeremyong/websocket_client.git", only: :test}
     ] ++ oauth_deps()
   end
 
index 80679cdedd8c3ef316c0833a62d8d6bda2275eef..55c3c59c6eaafaabe5064aa1bd8c3b260f50123c 100644 (file)
--- a/mix.lock
+++ b/mix.lock
@@ -8,18 +8,18 @@
   "benchee": {:hex, :benchee, "1.0.1", "66b211f9bfd84bd97e6d1beaddf8fc2312aaabe192f776e8931cb0c16f53a521", [:mix], [{:deep_merge, "~> 1.0", [hex: :deep_merge, repo: "hexpm", optional: false]}], "hexpm", "3ad58ae787e9c7c94dd7ceda3b587ec2c64604563e049b2a0e8baafae832addb"},
   "bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"},
   "cachex": {:hex, :cachex, "3.2.0", "a596476c781b0646e6cb5cd9751af2e2974c3e0d5498a8cab71807618b74fe2f", [:mix], [{:eternal, "~> 1.2", [hex: :eternal, repo: "hexpm", optional: false]}, {:jumper, "~> 1.0", [hex: :jumper, repo: "hexpm", optional: false]}, {:sleeplocks, "~> 1.1", [hex: :sleeplocks, repo: "hexpm", optional: false]}, {:unsafe, "~> 1.0", [hex: :unsafe, repo: "hexpm", optional: false]}], "hexpm", "aef93694067a43697ae0531727e097754a9e992a1e7946296f5969d6dd9ac986"},
-  "calendar": {:hex, :calendar, "0.17.6", "ec291cb2e4ba499c2e8c0ef5f4ace974e2f9d02ae9e807e711a9b0c7850b9aee", [:mix], [{:tzdata, "~> 0.5.20 or ~> 0.1.201603 or ~> 1.0", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "738d0e17a93c2ccfe4ddc707bdc8e672e9074c8569498483feb1c4530fb91b2b"},
+  "calendar": {:hex, :calendar, "1.0.0", "f52073a708528482ec33d0a171954ca610fe2bd28f1e871f247dc7f1565fa807", [:mix], [{:tzdata, "~> 0.5.20 or ~> 0.1.201603 or ~> 1.0", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "990e9581920c82912a5ee50e62ff5ef96da6b15949a2ee4734f935fdef0f0a6f"},
   "captcha": {:git, "https://git.pleroma.social/pleroma/elixir-libraries/elixir-captcha.git", "e0f16822d578866e186a0974d65ad58cddc1e2ab", [ref: "e0f16822d578866e186a0974d65ad58cddc1e2ab"]},
-  "castore": {:hex, :castore, "0.1.5", "591c763a637af2cc468a72f006878584bc6c306f8d111ef8ba1d4c10e0684010", [:mix], [], "hexpm", "6db356b2bc6cc22561e051ff545c20ad064af57647e436650aa24d7d06cd941a"},
+  "castore": {:hex, :castore, "0.1.7", "1ca19eee705cde48c9e809e37fdd0730510752cc397745e550f6065a56a701e9", [:mix], [], "hexpm", "a2ae2c13d40e9c308387f1aceb14786dca019ebc2a11484fb2a9f797ea0aa0d8"},
   "certifi": {:hex, :certifi, "2.5.2", "b7cfeae9d2ed395695dd8201c57a2d019c0c43ecaf8b8bcb9320b40d6662f340", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm", "3b3b5f36493004ac3455966991eaf6e768ce9884693d9968055aeeeb1e575040"},
   "combine": {:hex, :combine, "0.10.0", "eff8224eeb56498a2af13011d142c5e7997a80c8f5b97c499f84c841032e429f", [:mix], [], "hexpm", "1b1dbc1790073076580d0d1d64e42eae2366583e7aecd455d1215b0d16f2451b"},
   "comeonin": {:hex, :comeonin, "5.3.1", "7fe612b739c78c9c1a75186ef2d322ce4d25032d119823269d0aa1e2f1e20025", [:mix], [], "hexpm", "d6222483060c17f0977fad1b7401ef0c5863c985a64352755f366aee3799c245"},
-  "concurrent_limiter": {:git, "https://git.pleroma.social/pleroma/elixir-libraries/concurrent_limiter.git", "8eee96c6ba39b9286ec44c51c52d9f2758951365", [ref: "8eee96c6ba39b9286ec44c51c52d9f2758951365"]},
+  "concurrent_limiter": {:git, "https://git.pleroma.social/pleroma/elixir-libraries/concurrent_limiter.git", "55e92f84b4ed531bd487952a71040a9c69dc2807", [ref: "55e92f84b4ed531bd487952a71040a9c69dc2807"]},
   "connection": {:hex, :connection, "1.0.4", "a1cae72211f0eef17705aaededacac3eb30e6625b04a6117c1b2db6ace7d5976", [:mix], [], "hexpm", "4a0850c9be22a43af9920a71ab17c051f5f7d45c209e40269a1938832510e4d9"},
-  "cors_plug": {:hex, :cors_plug, "1.5.2", "72df63c87e4f94112f458ce9d25800900cc88608c1078f0e4faddf20933eda6e", [:mix], [{:plug, "~> 1.3 or ~> 1.4 or ~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "9af027d20dc12dd0c4345a6b87247e0c62965871feea0bfecf9764648b02cc69"},
-  "cowboy": {:hex, :cowboy, "2.7.0", "91ed100138a764355f43316b1d23d7ff6bdb0de4ea618cb5d8677c93a7a2f115", [:rebar3], [{:cowlib, "~> 2.8.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.7.1", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "04fd8c6a39edc6aaa9c26123009200fc61f92a3a94f3178c527b70b767c6e605"},
-  "cowlib": {:hex, :cowlib, "2.8.0", "fd0ff1787db84ac415b8211573e9a30a3ebe71b5cbff7f720089972b2319c8a4", [:rebar3], [], "hexpm", "79f954a7021b302186a950a32869dbc185523d99d3e44ce430cd1f3289f41ed4"},
-  "credo": {:hex, :credo, "1.1.5", "caec7a3cadd2e58609d7ee25b3931b129e739e070539ad1a0cd7efeeb47014f4", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "d0bbd3222607ccaaac5c0340f7f525c627ae4d7aee6c8c8c108922620c5b6446"},
+  "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"},
+  "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"},
   "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"},
@@ -27,6 +27,7 @@
   "decimal": {:hex, :decimal, "1.8.1", "a4ef3f5f3428bdbc0d35374029ffcf4ede8533536fa79896dd450168d9acdf3c", [:mix], [], "hexpm", "3cb154b00225ac687f6cbd4acc4b7960027c757a5152b369923ead9ddbca7aec"},
   "deep_merge": {:hex, :deep_merge, "1.0.0", "b4aa1a0d1acac393bdf38b2291af38cb1d4a52806cf7a4906f718e1feb5ee961", [:mix], [], "hexpm", "ce708e5f094b9cd4e8f2be4f00d2f4250c4095be93f8cd6d018c753894885430"},
   "earmark": {:hex, :earmark, "1.4.3", "364ca2e9710f6bff494117dbbd53880d84bebb692dafc3a78eb50aa3183f2bfd", [:mix], [], "hexpm", "8cf8a291ebf1c7b9539e3cddb19e9cef066c2441b1640f13c34c1d3cfc825fec"},
+  "earmark_parser": {:hex, :earmark_parser, "1.4.10", "6603d7a603b9c18d3d20db69921527f82ef09990885ed7525003c7fe7dc86c56", [:mix], [], "hexpm", "8e2d5370b732385db2c9b22215c3f59c84ac7dda7ed7e544d7c459496ae519c0"},
   "ecto": {:hex, :ecto, "3.4.5", "2bcd262f57b2c888b0bd7f7a28c8a48aa11dc1a2c6a858e45dd8f8426d504265", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "8c6d1d4d524559e9b7a062f0498e2c206122552d63eacff0a6567ffe7a8e8691"},
   "ecto_enum": {:hex, :ecto_enum, "1.4.0", "d14b00e04b974afc69c251632d1e49594d899067ee2b376277efd8233027aec8", [:mix], [{:ecto, ">= 3.0.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:ecto_sql, "> 3.0.0", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:mariaex, ">= 0.0.0", [hex: :mariaex, repo: "hexpm", optional: true]}, {:postgrex, ">= 0.0.0", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm", "8fb55c087181c2b15eee406519dc22578fa60dd82c088be376d0010172764ee4"},
   "ecto_sql": {:hex, :ecto_sql, "3.4.5", "30161f81b167d561a9a2df4329c10ae05ff36eca7ccc84628f2c8b9fa1e43323", [:mix], [{:db_connection, "~> 2.2", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.4.3", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.3.0 or ~> 0.4.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.15.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.0", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "31990c6a3579b36a3c0841d34a94c275e727de8b84f58509da5f1b2032c98ac2"},
   "esshd": {:hex, :esshd, "0.1.1", "d4dd4c46698093a40a56afecce8a46e246eb35463c457c246dacba2e056f31b5", [:mix], [], "hexpm", "d73e341e3009d390aa36387dc8862860bf9f874c94d9fd92ade2926376f49981"},
   "eternal": {:hex, :eternal, "1.2.1", "d5b6b2499ba876c57be2581b5b999ee9bdf861c647401066d3eeed111d096bc4", [:mix], [], "hexpm", "b14f1dc204321429479c569cfbe8fb287541184ed040956c8862cb7a677b8406"},
   "ex2ms": {:hex, :ex2ms, "1.5.0", "19e27f9212be9a96093fed8cdfbef0a2b56c21237196d26760f11dfcfae58e97", [:mix], [], "hexpm"},
-  "ex_aws": {:hex, :ex_aws, "2.1.1", "1e4de2106cfbf4e837de41be41cd15813eabc722315e388f0d6bb3732cec47cd", [:mix], [{:configparser_ex, "~> 4.0", [hex: :configparser_ex, repo: "hexpm", optional: true]}, {:hackney, "1.6.3 or 1.6.5 or 1.7.1 or 1.8.6 or ~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jsx, "~> 2.8", [hex: :jsx, repo: "hexpm", optional: true]}, {:poison, ">= 1.2.0", [hex: :poison, repo: "hexpm", optional: true]}, {:sweet_xml, "~> 0.6", [hex: :sweet_xml, repo: "hexpm", optional: true]}], "hexpm", "06b6fde12b33bb6d65d5d3493e903ba5a56d57a72350c15285a4298338089e10"},
+  "ex_aws": {:hex, :ex_aws, "2.1.3", "26b6f036f0127548706aade4a509978fc7c26bd5334b004fba9bfe2687a525df", [:mix], [{:configparser_ex, "~> 4.0", [hex: :configparser_ex, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:jsx, "~> 2.8", [hex: :jsx, repo: "hexpm", optional: true]}, {:sweet_xml, "~> 0.6", [hex: :sweet_xml, repo: "hexpm", optional: true]}], "hexpm", "0bdbe2aed9f326922fc5a6a80417e32f0c895f4b3b2b0b9676ebf23dd16c5da4"},
   "ex_aws_s3": {:hex, :ex_aws_s3, "2.0.2", "c0258bbdfea55de4f98f0b2f0ca61fe402cc696f573815134beb1866e778f47b", [:mix], [{:ex_aws, "~> 2.0", [hex: :ex_aws, repo: "hexpm", optional: false]}, {:sweet_xml, ">= 0.0.0", [hex: :sweet_xml, repo: "hexpm", optional: true]}], "hexpm", "0569f5b211b1a3b12b705fe2a9d0e237eb1360b9d76298028df2346cad13097a"},
   "ex_const": {:hex, :ex_const, "0.2.4", "d06e540c9d834865b012a17407761455efa71d0ce91e5831e86881b9c9d82448", [:mix], [], "hexpm", "96fd346610cc992b8f896ed26a98be82ac4efb065a0578f334a32d60a3ba9767"},
-  "ex_doc": {:hex, :ex_doc, "0.21.3", "857ec876b35a587c5d9148a2512e952e24c24345552259464b98bfbb883c7b42", [:mix], [{:earmark, "~> 1.4", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm", "0db1ee8d1547ab4877c5b5dffc6604ef9454e189928d5ba8967d4a58a801f161"},
-  "ex_machina": {:hex, :ex_machina, "2.3.0", "92a5ad0a8b10ea6314b876a99c8c9e3f25f4dde71a2a835845b136b9adaf199a", [:mix], [{:ecto, "~> 2.2 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_sql, "~> 3.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}], "hexpm", "b84f6af156264530b312a8ab98ac6088f6b77ae5fe2058305c81434aa01fbaf9"},
+  "ex_doc": {:hex, :ex_doc, "0.22.2", "03a2a58bdd2ba0d83d004507c4ee113b9c521956938298eba16e55cc4aba4a6c", [:mix], [{:earmark_parser, "~> 1.4.0", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm", "cf60e1b3e2efe317095b6bb79651f83a2c1b3edcb4d319c421d7fcda8b3aff26"},
+  "ex_machina": {:hex, :ex_machina, "2.4.0", "09a34c5d371bfb5f78399029194a8ff67aff340ebe8ba19040181af35315eabb", [:mix], [{:ecto, "~> 2.2 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_sql, "~> 3.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}], "hexpm", "a20bc9ddc721b33ea913b93666c5d0bdca5cbad7a67540784ae277228832d72c"},
   "ex_syslogger": {:hex, :ex_syslogger, "1.5.2", "72b6aa2d47a236e999171f2e1ec18698740f40af0bd02c8c650bf5f1fd1bac79", [:mix], [{:poison, ">= 1.5.0", [hex: :poison, repo: "hexpm", optional: true]}, {:syslog, "~> 1.1.0", [hex: :syslog, repo: "hexpm", optional: false]}], "hexpm", "ab9fab4136dbc62651ec6f16fa4842f10cf02ab4433fa3d0976c01be99398399"},
-  "excoveralls": {:hex, :excoveralls, "0.12.2", "a513defac45c59e310ac42fcf2b8ae96f1f85746410f30b1ff2b710a4b6cd44b", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "151c476331d49b45601ffc45f43cb3a8beb396b02a34e3777fea0ad34ae57d89"},
+  "excoveralls": {:hex, :excoveralls, "0.13.1", "b9f1697f7c9e0cfe15d1a1d737fb169c398803ffcbc57e672aa007e9fd42864c", [:mix], [{:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "b4bb550e045def1b4d531a37fb766cbbe1307f7628bf8f0414168b3f52021cce"},
   "fast_html": {:hex, :fast_html, "1.0.3", "2cc0d4b68496266a1530e0c852cafeaede0bd10cfdee26fda50dc696c203162f", [:make, :mix], [], "hexpm", "ab3d782b639d3c4655fbaec0f9d032c91f8cab8dd791ac7469c2381bc7c32f85"},
   "fast_sanitize": {:hex, :fast_sanitize, "0.1.7", "2a7cd8734c88a2de6de55022104f8a3b87f1fdbe8bbf131d9049764b53d50d0d", [:mix], [{:fast_html, "~> 1.0", [hex: :fast_html, repo: "hexpm", optional: false]}, {:plug, "~> 1.8", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "f39fe8ea08fbac17487c30bf09b7d9f3e12472e51fb07a88ffeb8fd17da8ab67"},
   "flake_id": {:hex, :flake_id, "0.1.0", "7716b086d2e405d09b647121a166498a0d93d1a623bead243e1f74216079ccb3", [:mix], [{:base62, "~> 1.2", [hex: :base62, repo: "hexpm", optional: false]}, {:ecto, ">= 2.0.0", [hex: :ecto, repo: "hexpm", optional: true]}], "hexpm", "31fc8090fde1acd267c07c36ea7365b8604055f897d3a53dd967658c691bd827"},
-  "floki": {:hex, :floki, "0.25.0", "b1c9ddf5f32a3a90b43b76f3386ca054325dc2478af020e87b5111c19f2284ac", [:mix], [{:html_entities, "~> 0.5.0", [hex: :html_entities, repo: "hexpm", optional: false]}], "hexpm", "631f4e627c46d5ecd347df5a2accdaf0621c77c3693c5b75a8ad58e84c61f242"},
+  "floki": {:hex, :floki, "0.27.0", "6b29a14283f1e2e8fad824bc930eaa9477c462022075df6bea8f0ad811c13599", [:mix], [{:html_entities, "~> 0.5.0", [hex: :html_entities, repo: "hexpm", optional: false]}], "hexpm", "583b8c13697c37179f1f82443bcc7ad2f76fbc0bf4c186606eebd658f7f2631b"},
   "gen_smtp": {:hex, :gen_smtp, "0.15.0", "9f51960c17769b26833b50df0b96123605a8024738b62db747fece14eb2fbfcc", [:rebar3], [], "hexpm", "29bd14a88030980849c7ed2447b8db6d6c9278a28b11a44cafe41b791205440f"},
   "gen_stage": {:hex, :gen_stage, "0.14.3", "d0c66f1c87faa301c1a85a809a3ee9097a4264b2edf7644bf5c123237ef732bf", [:mix], [], "hexpm"},
   "gen_state_machine": {:hex, :gen_state_machine, "2.0.5", "9ac15ec6e66acac994cc442dcc2c6f9796cf380ec4b08267223014be1c728a95", [:mix], [], "hexpm"},
-  "gettext": {:hex, :gettext, "0.17.4", "f13088e1ec10ce01665cf25f5ff779e7df3f2dc71b37084976cf89d1aa124d5c", [:mix], [], "hexpm", "3c75b5ea8288e2ee7ea503ff9e30dfe4d07ad3c054576a6e60040e79a801e14d"},
+  "gettext": {:hex, :gettext, "0.18.0", "406d6b9e0e3278162c2ae1de0a60270452c553536772167e2d701f028116f870", [:mix], [], "hexpm", "c3f850be6367ebe1a08616c2158affe4a23231c70391050bf359d5f92f66a571"},
   "gun": {:git, "https://github.com/ninenines/gun.git", "921c47146b2d9567eac7e9a4d2ccc60fffd4f327", [ref: "921c47146b2d9567eac7e9a4d2ccc60fffd4f327"]},
   "hackney": {:hex, :hackney, "1.16.0", "5096ac8e823e3a441477b2d187e30dd3fff1a82991a806b2003845ce72ce2d84", [:rebar3], [{:certifi, "2.5.2", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "6.0.1", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.3.0", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.6", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm", "3bf0bebbd5d3092a3543b783bf065165fa5d3ad4b899b836810e513064134e18"},
   "html_entities": {:hex, :html_entities, "0.5.1", "1c9715058b42c35a2ab65edc5b36d0ea66dd083767bef6e3edb57870ef556549", [:mix], [], "hexpm", "30efab070904eb897ff05cd52fa61c1025d7f8ef3a9ca250bc4e6513d16c32de"},
   "html_sanitize_ex": {:hex, :html_sanitize_ex, "1.3.0", "f005ad692b717691203f940c686208aa3d8ffd9dd4bb3699240096a51fa9564e", [:mix], [{:mochiweb, "~> 2.15", [hex: :mochiweb, repo: "hexpm", optional: false]}], "hexpm"},
-  "http_signatures": {:git, "https://git.pleroma.social/pleroma/http_signatures.git", "293d77bb6f4a67ac8bde1428735c3b42f22cbb30", [ref: "293d77bb6f4a67ac8bde1428735c3b42f22cbb30"]},
-  "httpoison": {:hex, :httpoison, "1.6.2", "ace7c8d3a361cebccbed19c283c349b3d26991eff73a1eaaa8abae2e3c8089b6", [:mix], [{:hackney, "~> 1.15 and >= 1.15.2", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "aa2c74bd271af34239a3948779612f87df2422c2fdcfdbcec28d9c105f0773fe"},
+  "http_signatures": {:hex, :http_signatures, "0.1.0", "4e4b501a936dbf4cb5222597038a89ea10781776770d2e185849fa829686b34c", [:mix], [], "hexpm", "f8a7b3731e3fd17d38fa6e343fcad7b03d6874a3b0a108c8568a71ed9c2cf824"},
+  "httpoison": {:hex, :httpoison, "1.7.0", "abba7d086233c2d8574726227b6c2c4f6e53c4deae7fe5f6de531162ce9929a0", [:mix], [{:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "975cc87c845a103d3d1ea1ccfd68a2700c211a434d8428b10c323dc95dc5b980"},
   "idna": {:hex, :idna, "6.0.1", "1d038fb2e7668ce41fbf681d2c45902e52b3cb9e9c77b55334353b222c2ee50c", [:rebar3], [{:unicode_util_compat, "0.5.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "a02c8a1c4fd601215bb0b0324c8a6986749f807ce35f25449ec9e69758708122"},
   "inet_cidr": {:hex, :inet_cidr, "1.0.4", "a05744ab7c221ca8e395c926c3919a821eb512e8f36547c062f62c4ca0cf3d6e", [:mix], [], "hexpm", "64a2d30189704ae41ca7dbdd587f5291db5d1dda1414e0774c29ffc81088c1bc"},
   "jason": {:hex, :jason, "1.2.1", "12b22825e22f468c02eb3e4b9985f3d0cb8dc40b9bd704730efa11abd2708c44", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "b659b8571deedf60f79c5a608e15414085fa141344e2716fbd6988a084b5f993"},
   "jumper": {:hex, :jumper, "1.0.1", "3c00542ef1a83532b72269fab9f0f0c82bf23a35e27d278bfd9ed0865cecabff", [:mix], [], "hexpm", "318c59078ac220e966d27af3646026db9b5a5e6703cb2aa3e26bcfaba65b7433"},
   "libring": {:hex, :libring, "1.4.0", "41246ba2f3fbc76b3971f6bce83119dfec1eee17e977a48d8a9cfaaf58c2a8d6", [:mix], [], "hexpm"},
   "linkify": {:hex, :linkify, "0.2.0", "2518bbbea21d2caa9d372424e1ad845b640c6630e2d016f1bd1f518f9ebcca28", [:mix], [], "hexpm", "b8ca8a68b79e30b7938d6c996085f3db14939f29538a59ca5101988bb7f917f6"},
-  "makeup": {:hex, :makeup, "1.0.0", "671df94cf5a594b739ce03b0d0316aa64312cee2574b6a44becb83cd90fb05dc", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "a10c6eb62cca416019663129699769f0c2ccf39428b3bb3c0cb38c718a0c186d"},
-  "makeup_elixir": {:hex, :makeup_elixir, "0.14.0", "cf8b7c66ad1cff4c14679698d532f0b5d45a3968ffbcbfd590339cb57742f1ae", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "d4b316c7222a85bbaa2fd7c6e90e37e953257ad196dc229505137c5e505e9eff"},
+  "makeup": {:hex, :makeup, "1.0.3", "e339e2f766d12e7260e6672dd4047405963c5ec99661abdc432e6ec67d29ef95", [:mix], [{:nimble_parsec, "~> 0.5", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "2e9b4996d11832947731f7608fed7ad2f9443011b3b479ae288011265cdd3dad"},
+  "makeup_elixir": {:hex, :makeup_elixir, "0.14.1", "4f0e96847c63c17841d42c08107405a005a2680eb9c7ccadfd757bd31dabccfb", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "f2438b1a80eaec9ede832b5c41cd4f373b38fd7aa33e3b22d9db79e640cbde11"},
   "meck": {:hex, :meck, "0.8.13", "ffedb39f99b0b99703b8601c6f17c7f76313ee12de6b646e671e3188401f7866", [:rebar3], [], "hexpm", "d34f013c156db51ad57cc556891b9720e6a1c1df5fe2e15af999c84d6cebeb1a"},
   "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"},
   "mime": {:hex, :mime, "1.3.1", "30ce04ab3175b6ad0bdce0035cba77bba68b813d523d1aac73d9781b4d193cf8", [:mix], [], "hexpm", "6cbe761d6a0ca5a31a0931bf4c63204bceb64538e664a8ecf784a9a6f3b875f1"},
   "mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"},
   "mochiweb": {:hex, :mochiweb, "2.18.0", "eb55f1db3e6e960fac4e6db4e2db9ec3602cc9f30b86cd1481d56545c3145d2e", [:rebar3], [], "hexpm"},
-  "mock": {:hex, :mock, "0.3.4", "c5862eb3b8c64237f45f586cf00c9d892ba07bb48305a43319d428ce3c2897dd", [:mix], [{:meck, "~> 0.8.13", [hex: :meck, repo: "hexpm", optional: false]}], "hexpm", "e6d886252f1a41f4ba06ecf2b4c8d38760b34b1c08a11c28f7397b2e03995964"},
-  "mogrify": {:hex, :mogrify, "0.6.1", "de1b527514f2d95a7bbe9642eb556061afb337e220cf97adbf3a4e6438ed70af", [:mix], [], "hexpm", "3bc928d817974fa10cc11e6c89b9a9361e37e96dbbf3d868c41094ec05745dcd"},
-  "mox": {:hex, :mox, "0.5.1", "f86bb36026aac1e6f924a4b6d024b05e9adbed5c63e8daa069bd66fb3292165b", [:mix], [], "hexpm", "052346cf322311c49a0f22789f3698eea030eec09b8c47367f0686ef2634ae14"},
+  "mock": {:hex, :mock, "0.3.5", "feb81f52b8dcf0a0d65001d2fec459f6b6a8c22562d94a965862f6cc066b5431", [:mix], [{:meck, "~> 0.8.13", [hex: :meck, repo: "hexpm", optional: false]}], "hexpm", "6fae404799408300f863550392635d8f7e3da6b71abdd5c393faf41b131c8728"},
+  "mogrify": {:hex, :mogrify, "0.7.4", "9b2496dde44b1ce12676f85d7dc531900939e6367bc537c7243a1b089435b32d", [:mix], [], "hexpm", "50d79e337fba6bc95bfbef918058c90f50b17eed9537771e61d4619488f099c3"},
+  "mox": {:hex, :mox, "0.5.2", "55a0a5ba9ccc671518d068c8dddd20eeb436909ea79d1799e2209df7eaa98b6c", [:mix], [], "hexpm", "df4310628cd628ee181df93f50ddfd07be3e5ecc30232d3b6aadf30bdfe6092b"},
   "myhtmlex": {:git, "https://git.pleroma.social/pleroma/myhtmlex.git", "ad0097e2f61d4953bfef20fb6abddf23b87111e6", [ref: "ad0097e2f61d4953bfef20fb6abddf23b87111e6", submodules: true]},
-  "nimble_parsec": {:hex, :nimble_parsec, "0.5.3", "def21c10a9ed70ce22754fdeea0810dafd53c2db3219a0cd54cf5526377af1c6", [:mix], [], "hexpm", "589b5af56f4afca65217a1f3eb3fee7e79b09c40c742fddc1c312b3ac0b3399f"},
+  "nimble_parsec": {:hex, :nimble_parsec, "0.6.0", "32111b3bf39137144abd7ba1cce0914533b2d16ef35e8abc5ec8be6122944263", [:mix], [], "hexpm", "27eac315a94909d4dc68bc07a4a83e06c8379237c5ea528a9acff4ca1c873c52"},
   "nodex": {:git, "https://git.pleroma.social/pleroma/nodex", "cb6730f943cfc6aad674c92161be23a8411f15d1", [ref: "cb6730f943cfc6aad674c92161be23a8411f15d1"]},
   "oban": {:hex, :oban, "2.0.0", "e6ce70d94dd46815ec0882a1ffb7356df9a9d5b8a40a64ce5c2536617a447379", [:mix], [{:ecto_sql, ">= 3.4.3", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.14", [hex: :postgrex, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "cf574813bd048b98a698aa587c21367d2e06842d4e1b1993dcd6a696e9e633bd"},
   "open_api_spex": {:git, "https://git.pleroma.social/pleroma/elixir-libraries/open_api_spex.git", "f296ac0924ba3cf79c7a588c4c252889df4c2edd", [ref: "f296ac0924ba3cf79c7a588c4c252889df4c2edd"]},
   "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.13", "67271ad69b51f3719354604f4a3f968f83aa61c19199343656c9caee057ff3b8", [: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", "ab765a0feddb81fc62e2116c827b5f068df85159c162bee760745276ad7ddc1b"},
+  "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_html": {:hex, :phoenix_html, "2.14.0", "d8c6bc28acc8e65f8ea0080ee05aa13d912c8758699283b8d3427b655aabe284", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "b0bb30eda478a06dbfbe96728061a93833db3861a49ccb516f839ecb08493fbb"},
+  "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.2.0", "a7e0b32077cd6d2323ae15198839b05d9caddfa20663fd85787479e81f89520e", [:mix], [{:phoenix, "~> 1.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.2", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:swoosh, "~> 0.1", [hex: :swoosh, repo: "hexpm", optional: false]}], "hexpm", "ebf1bfa7b3c1c850c04929afe02e2e0d7ab135e0706332c865de03e761676b1f"},
-  "plug": {:hex, :plug, "1.9.0", "8d7c4e26962283ff9f8f3347bd73838e2413fbc38b7bb5467d5924f68f3a5a4a", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "9902eda2c52ada2a096434682e99a2493f5d06a94d6ac6bcfff9805f952350f1"},
-  "plug_cowboy": {:hex, :plug_cowboy, "2.1.2", "8b0addb5908c5238fac38e442e81b6fcd32788eaa03246b4d55d147c47c5805e", [:mix], [{:cowboy, "~> 2.5", [hex: :cowboy, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "7d722581ce865a237e14da6d946f92704101740a256bd13ec91e63c0b122fc70"},
+  "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"},
+  "plug": {:hex, :plug, "1.10.3", "c9cebe917637d8db0e759039cc106adca069874e1a9034fd6e3fdd427fd3c283", [: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", "01f9037a2a1de1d633b5a881101e6a444bcabb1d386ca1e00bb273a1f1d9d939"},
+  "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_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"},
   "postgrex": {:hex, :postgrex, "0.15.5", "aec40306a622d459b01bff890fa42f1430dac61593b122754144ad9033a2152f", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "ed90c81e1525f65a2ba2279dbcebf030d6d13328daa2f8088b9661eb9143af7f"},
-  "pot": {:hex, :pot, "0.10.2", "9895c83bcff8cd22d9f5bc79dfc88a188176b261b618ad70d93faf5c5ca36e67", [:rebar3], [], "hexpm", "ac589a8e296b7802681e93cd0a436faec117ea63e9916709c628df31e17e91e2"},
+  "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_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"},
-  "recon": {:hex, :recon, "2.5.0", "2f7fcbec2c35034bade2f9717f77059dc54eb4e929a3049ca7ba6775c0bd66cd", [:mix, :rebar3], [], "hexpm", "72f3840fedd94f06315c523f6cecf5b4827233bed7ae3fe135b2a0ebeab5e196"},
+  "recon": {:hex, :recon, "2.5.1", "430ffa60685ac1efdfb1fe4c97b8767c92d0d92e6e7c3e8621559ba77598678a", [:mix, :rebar3], [], "hexpm", "5721c6b6d50122d8f68cccac712caa1231f97894bab779eff5ff0f886cb44648"},
   "remote_ip": {:git, "https://git.pleroma.social/pleroma/remote_ip.git", "b647d0deecaa3acb140854fe4bda5b7e1dc6d1c8", [ref: "b647d0deecaa3acb140854fe4bda5b7e1dc6d1c8"]},
   "sleeplocks": {:hex, :sleeplocks, "1.1.1", "3d462a0639a6ef36cc75d6038b7393ae537ab394641beb59830a1b8271faeed3", [:rebar3], [], "hexpm", "84ee37aeff4d0d92b290fff986d6a95ac5eedf9b383fadfd1d88e9b84a1c02e1"},
   "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.6", "cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3], [], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"},
   "sweet_xml": {:hex, :sweet_xml, "0.6.6", "fc3e91ec5dd7c787b6195757fbcf0abc670cee1e4172687b45183032221b66b8", [:mix], [], "hexpm", "2e1ec458f892ffa81f9f8386e3f35a1af6db7a7a37748a64478f13163a1f3573"},
-  "swoosh": {:git, "https://github.com/swoosh/swoosh.git", "c96e0ca8a00d8f211ec1f042a4626b09f249caa5", [ref: "c96e0ca8a00d8f211ec1f042a4626b09f249caa5"]},
+  "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"},
   "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.git", "af3707078b10793f6a534938e56b963aff82fe3c", [ref: "af3707078b10793f6a534938e56b963aff82fe3c"]},
-  "timex": {:hex, :timex, "3.6.1", "efdf56d0e67a6b956cc57774353b0329c8ab7726766a11547e529357ffdc1d56", [: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", "f354efb2400dd7a80fd9eb6c8419068c4f632da4ac47f3d8822d6e33f08bc852"},
+  "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"},
-  "ueberauth": {:hex, :ueberauth, "0.6.2", "25a31111249d60bad8b65438b2306a4dc91f3208faa62f5a8c33e8713989b2e8", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "db9fbfb5ac707bc4f85a297758406340bf0358b4af737a88113c1a9eee120ac7"},
+  "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.5.0", "8516502659002cec19e244ebd90d312183064be95025a319a6c7e89f4bccd65b", [:rebar3], [], "hexpm", "d48d002e15f5cc105a696cf2f1bbb3fc72b4b770a184d8420c8db20da2674b38"},
   "unsafe": {:hex, :unsafe, "1.0.1", "a27e1874f72ee49312e0a9ec2e0b27924214a05e3ddac90e91727bc76f8613d8", [:mix], [], "hexpm", "6c7729a2d214806450d29766abc2afaa7a2cbecf415be64f36a6691afebb50e5"},
-  "web_push_encryption": {:hex, :web_push_encryption, "0.2.3", "a0ceab85a805a30852f143d22d71c434046fbdbafbc7292e7887cec500826a80", [:mix], [{:httpoison, "~> 1.0", [hex: :httpoison, repo: "hexpm", optional: false]}, {:jose, "~> 1.8", [hex: :jose, repo: "hexpm", optional: false]}, {:poison, "~> 3.0", [hex: :poison, repo: "hexpm", optional: false]}], "hexpm", "9315c8f37c108835cf3f8e9157d7a9b8f420a34f402d1b1620a31aed5b93ecdf"},
+  "web_push_encryption": {:hex, :web_push_encryption, "0.3.0", "598b5135e696fd1404dc8d0d7c0fa2c027244a4e5d5e5a98ba267f14fdeaabc8", [:mix], [{:httpoison, "~> 1.0", [hex: :httpoison, repo: "hexpm", optional: false]}, {:jose, "~> 1.8", [hex: :jose, repo: "hexpm", optional: false]}], "hexpm", "f10bdd1afe527ede694749fb77a2f22f146a51b054c7fa541c9fd920fba7c875"},
   "websocket_client": {:git, "https://github.com/jeremyong/websocket_client.git", "9a6f65d05ebf2725d62fb19262b21f1805a59fbf", []},
 }
index 1ab9019ab756d4caee7d46463f31566d6c730901..1b9f4a12f5be8b3055cc2d49fb7ad492db7da429 100644 (file)
@@ -41,7 +41,8 @@ defmodule Pleroma.CaptchaTest do
                answer_data: answer,
                token: ^token,
                url: ^url,
-               type: :kocaptcha
+               type: :kocaptcha,
+               seconds_valid: 300
              } = new
 
       assert Kocaptcha.validate(token, "7oEy8c", answer) == :ok
@@ -56,7 +57,8 @@ defmodule Pleroma.CaptchaTest do
                answer_data: answer,
                token: token,
                type: :native,
-               url: "data:image/png;base64," <> _
+               url: "data:image/png;base64," <> _,
+               seconds_valid: 300
              } = new
 
       assert is_binary(answer)
diff --git a/test/report_note_test.exs b/test/report_note_test.exs
new file mode 100644 (file)
index 0000000..25c1d6a
--- /dev/null
@@ -0,0 +1,16 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.ReportNoteTest do
+  alias Pleroma.ReportNote
+  use Pleroma.DataCase
+  import Pleroma.Factory
+
+  test "create/3" do
+    user = insert(:user)
+    report = insert(:report_activity)
+    assert {:ok, note} = ReportNote.create(user.id, report.id, "naughty boy")
+    assert note.content == "naughty boy"
+  end
+end
index 7b0c1d5af72c7e3957e124b40b7011901febf7c9..2ed2ba3b405a751113b0b90682dae18423b442a4 100644 (file)
@@ -16,7 +16,8 @@ defmodule Pleroma.Captcha.Mock do
       type: :mock,
       token: "afa1815e14e29355e6c8f6b143a39fa2",
       answer_data: @solution,
-      url: "https://example.org/captcha.png"
+      url: "https://example.org/captcha.png",
+      seconds_valid: 300
     }
 
   @impl Service
index 635d83650b9fec2525ce305dcaeb85cf9f0ab96a..486eda8da5676fc0b86dc39ce16a7b093ec32016 100644 (file)
@@ -297,6 +297,30 @@ defmodule Pleroma.Factory do
     }
   end
 
+  def report_activity_factory(attrs \\ %{}) do
+    user = attrs[:user] || insert(:user)
+    activity = attrs[:activity] || insert(:note_activity)
+    state = attrs[:state] || "open"
+
+    data = %{
+      "id" => Pleroma.Web.ActivityPub.Utils.generate_activity_id(),
+      "actor" => user.ap_id,
+      "type" => "Flag",
+      "object" => [activity.actor, activity.data["id"]],
+      "published" => DateTime.utc_now() |> DateTime.to_iso8601(),
+      "to" => [],
+      "cc" => [activity.actor],
+      "context" => activity.data["context"],
+      "state" => state
+    }
+
+    %Pleroma.Activity{
+      data: data,
+      actor: data["actor"],
+      recipients: data["to"] ++ data["cc"]
+    }
+  end
+
   def oauth_app_factory do
     %Pleroma.Web.OAuth.App{
       client_name: sequence(:client_name, &"Some client #{&1}"),
diff --git a/test/user/welcome_chat_massage_test.exs b/test/user/welcome_chat_massage_test.exs
new file mode 100644 (file)
index 0000000..fe26d6e
--- /dev/null
@@ -0,0 +1,35 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.User.WelcomeChatMessageTest do
+  use Pleroma.DataCase
+
+  alias Pleroma.Config
+  alias Pleroma.User.WelcomeChatMessage
+
+  import Pleroma.Factory
+
+  setup do: clear_config([:welcome])
+
+  describe "post_message/1" do
+    test "send a chat welcome message" do
+      welcome_user = insert(:user, name: "mewmew")
+      user = insert(:user)
+
+      Config.put([:welcome, :chat_message, :enabled], true)
+      Config.put([:welcome, :chat_message, :sender_nickname], welcome_user.nickname)
+
+      Config.put(
+        [:welcome, :chat_message, :message],
+        "Hello, welcome to Blob/Cat!"
+      )
+
+      {:ok, %Pleroma.Activity{} = activity} = WelcomeChatMessage.post_message(user)
+
+      assert user.ap_id in activity.recipients
+      assert Pleroma.Object.normalize(activity).data["type"] == "ChatMessage"
+      assert Pleroma.Object.normalize(activity).data["content"] == "Hello, welcome to Blob/Cat!"
+    end
+  end
+end
index 624baf8ad15d323356a9fa767137de9a5e7afe5f..b4740589593bb8e673b6914ac63e51102ba4e566 100644 (file)
@@ -412,8 +412,36 @@ defmodule Pleroma.UserTest do
       welcome_user = insert(:user)
       Pleroma.Config.put([:welcome, :direct_message, :enabled], true)
       Pleroma.Config.put([:welcome, :direct_message, :sender_nickname], welcome_user.nickname)
-      Pleroma.Config.put([:welcome, :direct_message, :message], "Hello, this is a cool site")
+      Pleroma.Config.put([:welcome, :direct_message, :message], "Hello, this is a direct message")
 
+      cng = User.register_changeset(%User{}, @full_user_data)
+      {:ok, registered_user} = User.register(cng)
+      ObanHelpers.perform_all()
+
+      activity = Repo.one(Pleroma.Activity)
+      assert registered_user.ap_id in activity.recipients
+      assert Object.normalize(activity).data["content"] =~ "direct message"
+      assert activity.actor == welcome_user.ap_id
+    end
+
+    test "it sends a welcome chat message if it is set" do
+      welcome_user = insert(:user)
+      Pleroma.Config.put([:welcome, :chat_message, :enabled], true)
+      Pleroma.Config.put([:welcome, :chat_message, :sender_nickname], welcome_user.nickname)
+      Pleroma.Config.put([:welcome, :chat_message, :message], "Hello, this is a chat message")
+
+      cng = User.register_changeset(%User{}, @full_user_data)
+      {:ok, registered_user} = User.register(cng)
+      ObanHelpers.perform_all()
+
+      activity = Repo.one(Pleroma.Activity)
+      assert registered_user.ap_id in activity.recipients
+      assert Object.normalize(activity).data["content"] =~ "chat message"
+      assert activity.actor == welcome_user.ap_id
+    end
+
+    test "it sends a welcome email message if it is set" do
+      welcome_user = insert(:user)
       Pleroma.Config.put([:welcome, :email, :enabled], true)
       Pleroma.Config.put([:welcome, :email, :sender], welcome_user.email)
 
@@ -428,11 +456,6 @@ defmodule Pleroma.UserTest do
       {:ok, registered_user} = User.register(cng)
       ObanHelpers.perform_all()
 
-      activity = Repo.one(Pleroma.Activity)
-      assert registered_user.ap_id in activity.recipients
-      assert Object.normalize(activity).data["content"] =~ "cool site"
-      assert activity.actor == welcome_user.ap_id
-
       assert_email_sent(
         from: {instance_name, welcome_user.email},
         to: {registered_user.name, registered_user.email},
@@ -490,6 +513,29 @@ defmodule Pleroma.UserTest do
       refute changeset.valid?
     end
 
+    test "it blocks blacklisted email domains" do
+      clear_config([User, :email_blacklist], ["trolling.world"])
+
+      # Block with match
+      params = Map.put(@full_user_data, :email, "troll@trolling.world")
+      changeset = User.register_changeset(%User{}, params)
+      refute changeset.valid?
+
+      # Block with subdomain match
+      params = Map.put(@full_user_data, :email, "troll@gnomes.trolling.world")
+      changeset = User.register_changeset(%User{}, params)
+      refute changeset.valid?
+
+      # Pass with different domains that are similar
+      params = Map.put(@full_user_data, :email, "troll@gnomestrolling.world")
+      changeset = User.register_changeset(%User{}, params)
+      assert changeset.valid?
+
+      params = Map.put(@full_user_data, :email, "troll@trolling.world.us")
+      changeset = User.register_changeset(%User{}, params)
+      assert changeset.valid?
+    end
+
     test "it sets the password_hash and ap_id" do
       changeset = User.register_changeset(%User{}, @full_user_data)
 
@@ -500,6 +546,24 @@ defmodule Pleroma.UserTest do
 
       assert changeset.changes.follower_address == "#{changeset.changes.ap_id}/followers"
     end
+
+    test "it sets the 'accepts_chat_messages' set to true" do
+      changeset = User.register_changeset(%User{}, @full_user_data)
+      assert changeset.valid?
+
+      {:ok, user} = Repo.insert(changeset)
+
+      assert user.accepts_chat_messages
+    end
+
+    test "it creates a confirmed user" do
+      changeset = User.register_changeset(%User{}, @full_user_data)
+      assert changeset.valid?
+
+      {:ok, user} = Repo.insert(changeset)
+
+      refute user.confirmation_pending
+    end
   end
 
   describe "user registration, with :account_activation_required" do
@@ -513,15 +577,6 @@ defmodule Pleroma.UserTest do
     }
     setup do: clear_config([:instance, :account_activation_required], true)
 
-    test "it sets the 'accepts_chat_messages' set to true" do
-      changeset = User.register_changeset(%User{}, @full_user_data)
-      assert changeset.valid?
-
-      {:ok, user} = Repo.insert(changeset)
-
-      assert user.accepts_chat_messages
-    end
-
     test "it creates unconfirmed user" do
       changeset = User.register_changeset(%User{}, @full_user_data)
       assert changeset.valid?
index b0fb753bd71660f345a7c02babb511129c535bfd..cf6acc9a2d17ee2e16550f3dc20d184792e6eff1 100644 (file)
@@ -38,6 +38,17 @@ defmodule Pleroma.Web.ActivityPub.MRF.ObjectAgePolicyTest do
   end
 
   describe "with reject action" do
+    test "works with objects with empty to or cc fields" do
+      Config.put([:mrf_object_age, :actions], [:reject])
+
+      data =
+        get_old_message()
+        |> Map.put("cc", nil)
+        |> Map.put("to", nil)
+
+      assert match?({:reject, _}, ObjectAgePolicy.filter(data))
+    end
+
     test "it rejects an old post" do
       Config.put([:mrf_object_age, :actions], [:reject])
 
@@ -56,6 +67,21 @@ defmodule Pleroma.Web.ActivityPub.MRF.ObjectAgePolicyTest do
   end
 
   describe "with delist action" do
+    test "works with objects with empty to or cc fields" do
+      Config.put([:mrf_object_age, :actions], [:delist])
+
+      data =
+        get_old_message()
+        |> Map.put("cc", nil)
+        |> Map.put("to", nil)
+
+      {:ok, _u} = User.get_or_fetch_by_ap_id(data["actor"])
+
+      {:ok, data} = ObjectAgePolicy.filter(data)
+
+      assert Visibility.get_visibility(%{data: data}) == "unlisted"
+    end
+
     test "it delists an old post" do
       Config.put([:mrf_object_age, :actions], [:delist])
 
@@ -80,6 +106,22 @@ defmodule Pleroma.Web.ActivityPub.MRF.ObjectAgePolicyTest do
   end
 
   describe "with strip_followers action" do
+    test "works with objects with empty to or cc fields" do
+      Config.put([:mrf_object_age, :actions], [:strip_followers])
+
+      data =
+        get_old_message()
+        |> Map.put("cc", nil)
+        |> Map.put("to", nil)
+
+      {:ok, user} = User.get_or_fetch_by_ap_id(data["actor"])
+
+      {:ok, data} = ObjectAgePolicy.filter(data)
+
+      refute user.follower_address in data["to"]
+      refute user.follower_address in data["cc"]
+    end
+
     test "it strips followers collections from an old post" do
       Config.put([:mrf_object_age, :actions], [:strip_followers])
 
index e842d8d8de023fb3d3cdfbae9b5bf6ab5a11d096..d7dde62c40c8643bf2fbafc3b4fc7c08f6b17ec9 100644 (file)
@@ -7,6 +7,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
   import Pleroma.Factory
   alias Pleroma.Config
   alias Pleroma.Web.ActivityPub.MRF.SimplePolicy
+  alias Pleroma.Web.CommonAPI
 
   setup do:
           clear_config(:mrf_simple,
@@ -15,6 +16,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
             federated_timeline_removal: [],
             report_removal: [],
             reject: [],
+            followers_only: [],
             accept: [],
             avatar_removal: [],
             banner_removal: [],
@@ -261,6 +263,64 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
     end
   end
 
+  describe "when :followers_only" do
+    test "is empty" do
+      Config.put([:mrf_simple, :followers_only], [])
+      {_, ftl_message} = build_ftl_actor_and_message()
+      local_message = build_local_message()
+
+      assert SimplePolicy.filter(ftl_message) == {:ok, ftl_message}
+      assert SimplePolicy.filter(local_message) == {:ok, local_message}
+    end
+
+    test "has a matching host" do
+      actor = insert(:user)
+      following_user = insert(:user)
+      non_following_user = insert(:user)
+
+      {:ok, _, _, _} = CommonAPI.follow(following_user, actor)
+
+      activity = %{
+        "actor" => actor.ap_id,
+        "to" => [
+          "https://www.w3.org/ns/activitystreams#Public",
+          following_user.ap_id,
+          non_following_user.ap_id
+        ],
+        "cc" => [actor.follower_address, "http://foo.bar/qux"]
+      }
+
+      dm_activity = %{
+        "actor" => actor.ap_id,
+        "to" => [
+          following_user.ap_id,
+          non_following_user.ap_id
+        ],
+        "cc" => []
+      }
+
+      actor_domain =
+        activity
+        |> Map.fetch!("actor")
+        |> URI.parse()
+        |> Map.fetch!(:host)
+
+      Config.put([:mrf_simple, :followers_only], [actor_domain])
+
+      assert {:ok, new_activity} = SimplePolicy.filter(activity)
+      assert actor.follower_address in new_activity["cc"]
+      assert following_user.ap_id in new_activity["to"]
+      refute "https://www.w3.org/ns/activitystreams#Public" in new_activity["to"]
+      refute "https://www.w3.org/ns/activitystreams#Public" in new_activity["cc"]
+      refute non_following_user.ap_id in new_activity["to"]
+      refute non_following_user.ap_id in new_activity["cc"]
+
+      assert {:ok, new_dm_activity} = SimplePolicy.filter(dm_activity)
+      assert new_dm_activity["to"] == [following_user.ap_id]
+      assert new_dm_activity["cc"] == []
+    end
+  end
+
   describe "when :accept" do
     test "is empty" do
       Config.put([:mrf_simple, :accept], [])
index f30dc895629835cd9569f98dc134f75beda67e00..57946e6bb6a65f1e9e7e14a1e8b398065fff6873 100644 (file)
@@ -204,7 +204,7 @@ defmodule Pleroma.Web.AdminAPI.ReportControllerTest do
     test "returns empty response when no reports created", %{conn: conn} do
       response =
         conn
-        |> get("/api/pleroma/admin/reports")
+        |> get(report_path(conn, :index))
         |> json_response_and_validate_schema(:ok)
 
       assert Enum.empty?(response["reports"])
@@ -224,7 +224,7 @@ defmodule Pleroma.Web.AdminAPI.ReportControllerTest do
 
       response =
         conn
-        |> get("/api/pleroma/admin/reports")
+        |> get(report_path(conn, :index))
         |> json_response_and_validate_schema(:ok)
 
       [report] = response["reports"]
@@ -256,7 +256,7 @@ defmodule Pleroma.Web.AdminAPI.ReportControllerTest do
 
       response =
         conn
-        |> get("/api/pleroma/admin/reports?state=open")
+        |> get(report_path(conn, :index, %{state: "open"}))
         |> json_response_and_validate_schema(:ok)
 
       assert [open_report] = response["reports"]
@@ -268,7 +268,7 @@ defmodule Pleroma.Web.AdminAPI.ReportControllerTest do
 
       response =
         conn
-        |> get("/api/pleroma/admin/reports?state=closed")
+        |> get(report_path(conn, :index, %{state: "closed"}))
         |> json_response_and_validate_schema(:ok)
 
       assert [closed_report] = response["reports"]
@@ -280,9 +280,7 @@ defmodule Pleroma.Web.AdminAPI.ReportControllerTest do
 
       assert %{"total" => 0, "reports" => []} ==
                conn
-               |> get("/api/pleroma/admin/reports?state=resolved", %{
-                 "" => ""
-               })
+               |> get(report_path(conn, :index, %{state: "resolved"}))
                |> json_response_and_validate_schema(:ok)
     end
 
index e6b283aab390790074cb911678363b60f21038fa..17a1e7d661f9234102c28807e54ee0fa7ea8953a 100644 (file)
@@ -5,7 +5,6 @@
 defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
   use Pleroma.Web.ConnCase
 
-  alias Pleroma.Config
   alias Pleroma.Repo
   alias Pleroma.User
   alias Pleroma.Web.ActivityPub.ActivityPub
@@ -16,8 +15,6 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
   import Pleroma.Factory
 
   describe "account fetching" do
-    setup do: clear_config([:instance, :limit_to_local_content])
-
     test "works by id" do
       %User{id: user_id} = insert(:user)
 
@@ -42,7 +39,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
     end
 
     test "works by nickname for remote users" do
-      Config.put([:instance, :limit_to_local_content], false)
+      clear_config([:instance, :limit_to_local_content], false)
 
       user = insert(:user, nickname: "user@example.com", local: false)
 
@@ -53,7 +50,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
     end
 
     test "respects limit_to_local_content == :all for remote user nicknames" do
-      Config.put([:instance, :limit_to_local_content], :all)
+      clear_config([:instance, :limit_to_local_content], :all)
 
       user = insert(:user, nickname: "user@example.com", local: false)
 
@@ -63,7 +60,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
     end
 
     test "respects limit_to_local_content == :unauthenticated for remote user nicknames" do
-      Config.put([:instance, :limit_to_local_content], :unauthenticated)
+      clear_config([:instance, :limit_to_local_content], :unauthenticated)
 
       user = insert(:user, nickname: "user@example.com", local: false)
       reading_user = insert(:user)
@@ -903,10 +900,11 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
       [valid_params: valid_params]
     end
 
-    setup do: clear_config([:instance, :account_activation_required])
-    setup do: clear_config([:instance, :account_approval_required])
+    test "registers and logs in without :account_activation_required / :account_approval_required",
+         %{conn: conn} do
+      clear_config([:instance, :account_activation_required], false)
+      clear_config([:instance, :account_approval_required], false)
 
-    test "Account registration via Application", %{conn: conn} do
       conn =
         conn
         |> put_req_header("content-type", "application/json")
@@ -942,17 +940,32 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
       assert refresh
       assert scope == "read write follow"
 
+      clear_config([User, :email_blacklist], ["example.org"])
+
+      params = %{
+        username: "lain",
+        email: "lain@example.org",
+        password: "PlzDontHackLain",
+        bio: "Test Bio",
+        agreement: true
+      }
+
       conn =
         build_conn()
         |> put_req_header("content-type", "multipart/form-data")
         |> put_req_header("authorization", "Bearer " <> token)
-        |> post("/api/v1/accounts", %{
-          username: "lain",
-          email: "lain@example.org",
-          password: "PlzDontHackLain",
-          bio: "Test Bio",
-          agreement: true
-        })
+        |> post("/api/v1/accounts", params)
+
+      assert %{"error" => "{\"email\":[\"Invalid email\"]}"} =
+               json_response_and_validate_schema(conn, 400)
+
+      Pleroma.Config.put([User, :email_blacklist], [])
+
+      conn =
+        build_conn()
+        |> put_req_header("content-type", "multipart/form-data")
+        |> put_req_header("authorization", "Bearer " <> token)
+        |> post("/api/v1/accounts", params)
 
       %{
         "access_token" => token,
@@ -963,14 +976,16 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
 
       token_from_db = Repo.get_by(Token, token: token)
       assert token_from_db
-      token_from_db = Repo.preload(token_from_db, :user)
-      assert token_from_db.user
+      user = Repo.preload(token_from_db, :user).user
 
-      assert token_from_db.user.confirmation_pending
+      assert user
+      refute user.confirmation_pending
+      refute user.approval_pending
     end
 
-    test "Account registration via app with account_approval_required", %{conn: conn} do
-      Pleroma.Config.put([:instance, :account_approval_required], true)
+    test "registers but does not log in with :account_activation_required", %{conn: conn} do
+      clear_config([:instance, :account_activation_required], true)
+      clear_config([:instance, :account_approval_required], false)
 
       conn =
         conn
@@ -1016,26 +1031,79 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
           email: "lain@example.org",
           password: "PlzDontHackLain",
           bio: "Test Bio",
-          agreement: true,
-          reason: "I'm a cool dude, bro"
+          agreement: true
         })
 
-      %{
-        "access_token" => token,
-        "created_at" => _created_at,
-        "scope" => ^scope,
-        "token_type" => "Bearer"
-      } = json_response_and_validate_schema(conn, 200)
+      response = json_response_and_validate_schema(conn, 200)
+      assert %{"identifier" => "missing_confirmed_email"} = response
+      refute response["access_token"]
+      refute response["token_type"]
 
+      user = Repo.get_by(User, email: "lain@example.org")
+      assert user.confirmation_pending
+    end
+
+    test "registers but does not log in with :account_approval_required", %{conn: conn} do
+      clear_config([:instance, :account_approval_required], true)
+      clear_config([:instance, :account_activation_required], false)
+
+      conn =
+        conn
+        |> put_req_header("content-type", "application/json")
+        |> post("/api/v1/apps", %{
+          client_name: "client_name",
+          redirect_uris: "urn:ietf:wg:oauth:2.0:oob",
+          scopes: "read, write, follow"
+        })
+
+      assert %{
+               "client_id" => client_id,
+               "client_secret" => client_secret,
+               "id" => _,
+               "name" => "client_name",
+               "redirect_uri" => "urn:ietf:wg:oauth:2.0:oob",
+               "vapid_key" => _,
+               "website" => nil
+             } = json_response_and_validate_schema(conn, 200)
+
+      conn =
+        post(conn, "/oauth/token", %{
+          grant_type: "client_credentials",
+          client_id: client_id,
+          client_secret: client_secret
+        })
+
+      assert %{"access_token" => token, "refresh_token" => refresh, "scope" => scope} =
+               json_response(conn, 200)
+
+      assert token
       token_from_db = Repo.get_by(Token, token: token)
       assert token_from_db
-      token_from_db = Repo.preload(token_from_db, :user)
-      assert token_from_db.user
+      assert refresh
+      assert scope == "read write follow"
 
-      assert token_from_db.user.confirmation_pending
-      assert token_from_db.user.approval_pending
+      conn =
+        build_conn()
+        |> put_req_header("content-type", "multipart/form-data")
+        |> put_req_header("authorization", "Bearer " <> token)
+        |> post("/api/v1/accounts", %{
+          username: "lain",
+          email: "lain@example.org",
+          password: "PlzDontHackLain",
+          bio: "Test Bio",
+          agreement: true,
+          reason: "I'm a cool dude, bro"
+        })
 
-      assert token_from_db.user.registration_reason == "I'm a cool dude, bro"
+      response = json_response_and_validate_schema(conn, 200)
+      assert %{"identifier" => "awaiting_approval"} = response
+      refute response["access_token"]
+      refute response["token_type"]
+
+      user = Repo.get_by(User, email: "lain@example.org")
+
+      assert user.approval_pending
+      assert user.registration_reason == "I'm a cool dude, bro"
     end
 
     test "returns error when user already registred", %{conn: conn, valid_params: valid_params} do
@@ -1089,11 +1157,9 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
       end)
     end
 
-    setup do: clear_config([:instance, :account_activation_required])
-
     test "returns bad_request if missing email params when :account_activation_required is enabled",
          %{conn: conn, valid_params: valid_params} do
-      Pleroma.Config.put([:instance, :account_activation_required], true)
+      clear_config([:instance, :account_activation_required], true)
 
       app_token = insert(:oauth_token, user: nil)
 
@@ -1258,8 +1324,6 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
         assert token_from_db
         token_from_db = Repo.preload(token_from_db, :user)
         assert token_from_db.user
-
-        assert token_from_db.user.confirmation_pending
       end
 
       conn =
index d34f300da932246a02a5429c424ec25d039558ad..5955d833401ff29e2b4c821952fb761966f33257 100644 (file)
@@ -1432,6 +1432,20 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
       [%{"id" => id}] = response
       assert id == other_user.id
     end
+
+    test "returns empty array when :show_reactions is disabled", %{conn: conn, activity: activity} do
+      clear_config([:instance, :show_reactions], false)
+
+      other_user = insert(:user)
+      {:ok, _} = CommonAPI.favorite(other_user, activity.id)
+
+      response =
+        conn
+        |> get("/api/v1/statuses/#{activity.id}/favourited_by")
+        |> json_response_and_validate_schema(:ok)
+
+      assert Enum.empty?(response)
+    end
   end
 
   describe "GET /api/v1/statuses/:id/reblogged_by" do
index e1bb5ebfe39c3e49791ab617df03d63c2db4d8f9..3deab30d1678a659840d9e88f07677b77a5196b9 100644 (file)
@@ -106,6 +106,23 @@ defmodule Pleroma.Web.PleromaAPI.EmojiReactionControllerTest do
              result
   end
 
+  test "GET /api/v1/pleroma/statuses/:id/reactions with :show_reactions disabled", %{conn: conn} do
+    clear_config([:instance, :show_reactions], false)
+
+    user = insert(:user)
+    other_user = insert(:user)
+
+    {:ok, activity} = CommonAPI.post(user, %{status: "#cofe"})
+    {:ok, _} = CommonAPI.react_with_emoji(activity.id, other_user, "🎅")
+
+    result =
+      conn
+      |> get("/api/v1/pleroma/statuses/#{activity.id}/reactions")
+      |> json_response_and_validate_schema(200)
+
+    assert result == []
+  end
+
   test "GET /api/v1/pleroma/statuses/:id/reactions/:emoji", %{conn: conn} do
     user = insert(:user)
     other_user = insert(:user)
index e5b165255989c8df26d379052bab9a326ad27af8..40dbae3cd4e9b35cabbdbef711901aadc5acfd13 100644 (file)
@@ -43,7 +43,17 @@ defmodule Pleroma.Web.PleromaAPI.Chat.MessageReferenceViewTest do
     assert chat_message[:unread] == false
     assert match?([%{shortcode: "firefox"}], chat_message[:emojis])
 
-    {:ok, activity} = CommonAPI.post_chat_message(recipient, user, "gkgkgk", media_id: upload.id)
+    clear_config([:rich_media, :enabled], true)
+
+    Tesla.Mock.mock(fn
+      %{url: "https://example.com/ogp"} ->
+        %Tesla.Env{status: 200, body: File.read!("test/fixtures/rich_media/ogp.html")}
+    end)
+
+    {:ok, activity} =
+      CommonAPI.post_chat_message(recipient, user, "gkgkgk https://example.com/ogp",
+        media_id: upload.id
+      )
 
     object = Object.normalize(activity)
 
@@ -52,10 +62,11 @@ defmodule Pleroma.Web.PleromaAPI.Chat.MessageReferenceViewTest do
     chat_message_two = MessageReferenceView.render("show.json", chat_message_reference: cm_ref)
 
     assert chat_message_two[:id] == cm_ref.id
-    assert chat_message_two[:content] == "gkgkgk"
+    assert chat_message_two[:content] == object.data["content"]
     assert chat_message_two[:account_id] == recipient.id
     assert chat_message_two[:chat_id] == chat_message[:chat_id]
     assert chat_message_two[:attachment]
     assert chat_message_two[:unread] == true
+    assert chat_message_two[:card]
   end
 end