Merge branch 'hide-follower-following-count' into 'develop'
authorfeld <feld@feld.me>
Wed, 18 Sep 2019 21:13:15 +0000 (21:13 +0000)
committerfeld <feld@feld.me>
Wed, 18 Sep 2019 21:13:15 +0000 (21:13 +0000)
Add a setting to hide follows/followers stats from the user profile

See merge request pleroma/pleroma!1663

32 files changed:
CHANGELOG.md
config/description.exs
docs/api/admin_api.md
lib/pleroma/application.ex
lib/pleroma/constants.ex
lib/pleroma/docs/markdown.ex
lib/pleroma/flake_id.ex
lib/pleroma/object.ex
lib/pleroma/object/fetcher.ex
lib/pleroma/user.ex
lib/pleroma/web/activity_pub/activity_pub.ex
lib/pleroma/web/activity_pub/transmogrifier.ex
lib/pleroma/web/activity_pub/utils.ex
lib/pleroma/web/admin_api/admin_api_controller.ex
lib/pleroma/web/admin_api/views/report_view.ex
lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex
lib/pleroma/web/router.ex
lib/pleroma/web/streamer/state.ex
lib/pleroma/workers/web_pusher_worker.ex
mix.exs
mix.lock
priv/repo/migrations/20190917100019_update_oban.exs [new file with mode: 0644]
test/fixtures/tesla_mock/poll_modified.json [new file with mode: 0644]
test/fixtures/tesla_mock/poll_original.json [new file with mode: 0644]
test/fixtures/tesla_mock/rin.json [new file with mode: 0644]
test/integration/mastodon_websocket_test.exs
test/object_test.exs
test/support/http_request_mock.ex
test/test_helper.exs
test/web/activity_pub/utils_test.exs
test/web/admin_api/admin_api_controller_test.exs
test/web/twitter_api/util_controller_test.exs

index 7dfa477b4912385c1b06a404cd6b0108f66b44b9..906aa985ebbcbe46d43d1212fc0e0f90cdec033b 100644 (file)
@@ -4,14 +4,20 @@ All notable changes to this project will be documented in this file.
 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 
 ## [Unreleased]
+### Added
+- Refreshing poll results for remote polls
+### Changed
+- **Breaking:** Elixir >=1.8 is now required (was >= 1.7)
+- Replaced [pleroma_job_queue](https://git.pleroma.social/pleroma/pleroma_job_queue) and `Pleroma.Web.Federator.RetryQueue` with [Oban](https://github.com/sorentwo/oban) (see [`docs/config.md`](docs/config.md) on migrating customized worker / retry settings)
+- Introduced [quantum](https://github.com/quantum-elixir/quantum-core) job scheduler
+- Admin API: Return `total` when querying for reports
+
+## [1.1.0] - 2019-??-??
 ### Security
-- OStatus: eliminate the possibility of a protocol downgrade attack.
-- OStatus: prevent following locked accounts, bypassing the approval process.
 - Mastodon API: respect post privacy in `/api/v1/statuses/:id/{favourited,reblogged}_by`
 
 ### Removed
 - **Breaking:** GNU Social API with Qvitter extensions support
-- **Breaking:** ActivityPub: The `accept_blocks` configuration setting.
 - Emoji: Remove longfox emojis.
 - Remove `Reply-To` header from report emails for admins.
 
@@ -19,9 +25,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 - **Breaking:** Configuration: A setting to explicitly disable the mailer was added, defaulting to true, if you are using a mailer add `config :pleroma, Pleroma.Emails.Mailer, enabled: true` to your config
 - **Breaking:** Configuration: `/media/` is now removed when `base_url` is configured, append `/media/` to your `base_url` config to keep the old behaviour if desired
 - **Breaking:** `/api/pleroma/notifications/read` is moved to `/api/v1/pleroma/notifications/read` and now supports `max_id` and responds with Mastodon API entities.
+- **Breaking:** `/api/pleroma/admin/users/invite_token` now uses `POST`, changed accepted params and returns full invite in json instead of only token string.
+- Configuration: added `config/description.exs`, from which `docs/config.md` is generated
 - Configuration: OpenGraph and TwitterCard providers enabled by default
 - Configuration: Filter.AnonymizeFilename added ability to retain file extension with custom text
-- Configuration: added `config/description.exs`, from which `docs/config.md` is generated
+- Mastodon API: `pleroma.thread_muted` key in the Status entity
 - Federation: Return 403 errors when trying to request pages from a user's follower/following collections if they have `hide_followers`/`hide_follows` set
 - NodeInfo: Return `skipThreadContainment` in `metadata` for the `skip_thread_containment` option
 - NodeInfo: Return `mailerEnabled` in `metadata`
@@ -30,23 +38,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 - AdminAPI: Add "godmode" while fetching user statuses (i.e. admin can see private statuses)
 - Improve digest email template
 – Pagination: (optional) return `total` alongside with `items` when paginating
-- Replaced [pleroma_job_queue](https://git.pleroma.social/pleroma/pleroma_job_queue) and `Pleroma.Web.Federator.RetryQueue` with [Oban](https://github.com/sorentwo/oban) (see [`docs/config.md`](docs/config.md) on migrating customized worker / retry settings)
-- Introduced [quantum](https://github.com/quantum-elixir/quantum-core) job scheduler
 
 ### Fixed
 - Following from Osada
-- Not being able to pin unlisted posts
-- Objects being re-embedded to activities after being updated (e.g faved/reposted). Running 'mix pleroma.database prune_objects' again is advised.
 - Favorites timeline doing database-intensive queries
 - Metadata rendering errors resulting in the entire page being inaccessible
 - `federation_incoming_replies_max_depth` option being ignored in certain cases
-- Federation/MediaProxy not working with instances that have wrong certificate order
 - Mastodon API: Handling of search timeouts (`/api/v1/search` and `/api/v2/search`)
 - Mastodon API: Misskey's endless polls being unable to render
 - Mastodon API: Embedded relationships not being properly rendered in the Account entity of Status entity
 - Mastodon API: Notifications endpoint crashing if one notification failed to render
-- Mastodon API: follower/following counters not being nullified, when `hide_follows`/`hide_followers` is set
-- Mastodon API: `muted` in the Status entity, using author's account to determine if the tread was muted
 - Mastodon API: Add `account_id`, `type`, `offset`, and `limit` to search API (`/api/v1/search` and `/api/v2/search`)
 - Mastodon API, streaming: Fix filtering of notifications based on blocks/mutes/thread mutes
 - ActivityPub C2S: follower/following collection pages being inaccessible even when authentifucated if `hide_followers`/ `hide_follows` was set
@@ -54,15 +55,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 - Rich Media: Parser failing when no TTL can be found by image TTL setters
 - Rich Media: The crawled URL is now spliced into the rich media data.
 - ActivityPub S2S: sharedInbox usage has been mostly aligned with the rules in the AP specification.
-- ActivityPub S2S: remote user deletions now work the same as local user deletions.
-- ActivityPub S2S: POST requests are now signed with `(request-target)` pseudo-header.
-- Not being able to access the Mastodon FE login page on private instances
-- Invalid SemVer version generation, when the current branch does not have commits ahead of tag/checked out on a tag
 - Pleroma.Upload base_url was not automatically whitelisted by MediaProxy. Now your custom CDN or file hosting will be accessed directly as expected.
 - Report email not being sent to admins when the reporter is a remote user
-- MRF: ensure that subdomain_match calls are case-insensitive
 - Reverse Proxy limiting `max_body_length` was incorrectly defined and only checked `Content-Length` headers which may not be sufficient in some circumstances
-- MRF: fix use of unserializable keyword lists in describe() implementations
 - ActivityPub: Deactivated user deletion
 - ActivityPub: Fix `/users/:nickname/inbox` crashing without an authenticated user
 - MRF: fix ability to follow a relay when AntiFollowbotPolicy was enabled
@@ -73,16 +68,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 - Mastodon API: all status JSON responses contain a `pleroma.expires_at` item which states when an activity will expire. The value is only shown to the user who created the activity. To everyone else it's empty.
 - Configuration: `ActivityExpiration.enabled` controls whether expired activites will get deleted at the appropriate time. Enabled by default.
 - Conversations: Add Pleroma-specific conversation endpoints and status posting extensions. Run the `bump_all_conversations` task again to create the necessary data.
-- **Breaking:** MRF describe API, which adds support for exposing configuration information about MRF policies to NodeInfo.
-  Custom modules will need to be updated by adding, at the very least, `def describe, do: {:ok, %{}}` to the MRF policy modules.
 - MRF: Support for priming the mediaproxy cache (`Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy`)
 - MRF: Support for excluding specific domains from Transparency.
 - MRF: Support for filtering posts based on who they mention (`Pleroma.Web.ActivityPub.MRF.MentionPolicy`)
-- MRF: Support for filtering posts based on ActivityStreams vocabulary (`Pleroma.Web.ActivityPub.MRF.VocabularyPolicy`)
-- MRF (Simple Policy): Support for wildcard domains.
-- Support for wildcard domains in user domain blocks setting.
-- Configuration: `quarantined_instances` support wildcard domains.
-- Configuration: `federation_incoming_replies_max_depth` option
 - Mastodon API: Support for the [`tagged` filter](https://github.com/tootsuite/mastodon/pull/9755) in [`GET /api/v1/accounts/:id/statuses`](https://docs.joinmastodon.org/api/rest/accounts/#get-api-v1-accounts-id-statuses)
 - Mastodon API, streaming: Add support for passing the token in the `Sec-WebSocket-Protocol` header
 - Mastodon API, extension: Ability to reset avatar, profile banner, and background
@@ -111,9 +99,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 - Admin API: Endpoint for fetching latest user's statuses
 - Pleroma API: Add `/api/v1/pleroma/accounts/confirmation_resend?email=<email>` for resending account confirmation.
 - Pleroma API: Email change endpoint.
-- Relays: Added a task to list relay subscriptions.
-- Mix Tasks: `mix pleroma.database fix_likes_collections`
-- Federation: Remove `likes` from objects.
 - Admin API: Added moderation log
 - Web response cache (currently, enabled for ActivityPub)
 - Mastodon API: Added an endpoint to get multiple statuses by IDs (`GET /api/v1/statuses/?ids[]=1&ids[]=2`)
@@ -124,6 +109,61 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 - RichMedia: parsers and their order are configured in `rich_media` config.
 - RichMedia: add the rich media ttl based on image expiration time.
 
+## [1.0.6] - 2019-08-14
+### Fixed
+- MRF: fix use of unserializable keyword lists in describe() implementations
+- ActivityPub S2S: POST requests are now signed with `(request-target)` pseudo-header.
+
+## [1.0.5] - 2019-08-13
+### Fixed
+- Mastodon API: follower/following counters not being nullified, when `hide_follows`/`hide_followers` is set
+- Mastodon API: `muted` in the Status entity, using author's account to determine if the thread was muted
+- Mastodon API: return the actual profile URL in the Account entity's `url` property when appropriate
+- Templates: properly style anchor tags
+- Objects being re-embedded to activities after being updated (e.g faved/reposted). Running 'mix pleroma.database prune_objects' again is advised.
+- Not being able to access the Mastodon FE login page on private instances
+- MRF: ensure that subdomain_match calls are case-insensitive
+- Fix internal server error when using the healthcheck API.
+
+### Added
+- **Breaking:** MRF describe API, which adds support for exposing configuration information about MRF policies to NodeInfo.
+  Custom modules will need to be updated by adding, at the very least, `def describe, do: {:ok, %{}}` to the MRF policy modules.
+- Relays: Added a task to list relay subscriptions.
+- MRF: Support for filtering posts based on ActivityStreams vocabulary (`Pleroma.Web.ActivityPub.MRF.VocabularyPolicy`)
+- MRF (Simple Policy): Support for wildcard domains.
+- Support for wildcard domains in user domain blocks setting.
+- Configuration: `quarantined_instances` support wildcard domains.
+- Mix Tasks: `mix pleroma.database fix_likes_collections`
+- Configuration: `federation_incoming_replies_max_depth` option
+
+### Removed
+- Federation: Remove `likes` from objects.
+- **Breaking:** ActivityPub: The `accept_blocks` configuration setting.
+
+## [1.0.4] - 2019-08-01
+### Fixed
+- Invalid SemVer version generation, when the current branch does not have commits ahead of tag/checked out on a tag
+
+## [1.0.3] - 2019-07-31
+### Security
+- OStatus: eliminate the possibility of a protocol downgrade attack.
+- OStatus: prevent following locked accounts, bypassing the approval process.
+- TwitterAPI: use CommonAPI to handle remote follows instead of OStatus.
+
+## [1.0.2] - 2019-07-28
+### Fixed
+- Not being able to pin unlisted posts
+- Mastodon API: represent poll IDs as strings
+- MediaProxy: fix matching filenames
+- MediaProxy: fix filename encoding
+- Migrations: fix a sporadic migration failure
+- Metadata rendering errors resulting in the entire page being inaccessible
+- Federation/MediaProxy not working with instances that have wrong certificate order
+- ActivityPub S2S: remote user deletions now work the same as local user deletions.
+
+### Changed
+- Configuration: OpenGraph and TwitterCard providers enabled by default
+- Configuration: Filter.AnonymizeFilename added ability to retain file extension with custom text
 
 ## [1.0.1] - 2019-07-14
 ### Security
index 32d36d6d636a38894bfc958a6c21f5b2f5826767..65ea6bf01720a213a8155b6782438204116bca9a 100644 (file)
@@ -39,11 +39,7 @@ config :pleroma, :config_description, [
         key: :link_name,
         type: :boolean,
         description:
-          "If enabled, a name parameter will be added to the url of the upload. For example `https://instance.tld/media/imagehash.png?name=realname.png`",
-        suggestions: [
-          true,
-          false
-        ]
+          "If enabled, a name parameter will be added to the url of the upload. For example `https://instance.tld/media/imagehash.png?name=realname.png`"
       },
       %{
         key: :base_url,
@@ -57,11 +53,7 @@ config :pleroma, :config_description, [
         key: :proxy_remote,
         type: :boolean,
         description:
-          "If enabled, requests to media stored using a remote uploader will be proxied instead of being redirected.",
-        suggestions: [
-          true,
-          false
-        ]
+          "If enabled, requests to media stored using a remote uploader will be proxied instead of being redirected."
       },
       %{
         key: :proxy_opts,
@@ -117,8 +109,7 @@ config :pleroma, :config_description, [
         type: :string,
         description:
           "If you use S3 compatible service such as Digital Ocean Spaces or CDN, set folder name or \"\" etc." <>
-            " For example, when using CDN to S3 virtual host format, set \"\". At this time, write CNAME to CDN in public_endpoint.",
-        suggestions: [""]
+            " For example, when using CDN to S3 virtual host format, set \"\". At this time, write CNAME to CDN in public_endpoint."
       }
     ]
   },
@@ -190,11 +181,7 @@ config :pleroma, :config_description, [
       %{
         key: :enabled,
         type: :boolean,
-        description: "Allow/disallow send emails",
-        suggestions: [
-          true,
-          false
-        ]
+        description: "Allow/disallow send emails"
       },
       %{
         group: {:subgroup, Swoosh.Adapters.SMTP},
@@ -221,8 +208,7 @@ config :pleroma, :config_description, [
         group: {:subgroup, Swoosh.Adapters.SMTP},
         key: :ssl,
         type: :boolean,
-        description: "`Swoosh.Adapters.SMTP` adapter specific setting",
-        suggestions: [true, false]
+        description: "`Swoosh.Adapters.SMTP` adapter specific setting"
       },
       %{
         group: {:subgroup, Swoosh.Adapters.SMTP},
@@ -256,8 +242,7 @@ config :pleroma, :config_description, [
         group: {:subgroup, Swoosh.Adapters.SMTP},
         key: :no_mx_lookups,
         type: :boolean,
-        description: "`Swoosh.Adapters.SMTP` adapter specific setting",
-        suggestions: [true, false]
+        description: "`Swoosh.Adapters.SMTP` adapter specific setting"
       },
       %{
         group: {:subgroup, Swoosh.Adapters.Sendgrid},
@@ -284,8 +269,7 @@ config :pleroma, :config_description, [
         group: {:subgroup, Swoosh.Adapters.Sendmail},
         key: :qmail,
         type: :boolean,
-        description: "`Swoosh.Adapters.Sendmail` adapter specific setting",
-        suggestions: [true, false]
+        description: "`Swoosh.Adapters.Sendmail` adapter specific setting"
       },
       %{
         group: {:subgroup, Swoosh.Adapters.Mandrill},
@@ -375,22 +359,19 @@ config :pleroma, :config_description, [
         group: {:subgroup, Swoosh.Adapters.SocketLabs},
         key: :server_id,
         type: :string,
-        description: "`Swoosh.Adapters.SocketLabs` adapter specific setting",
-        suggestions: [""]
+        description: "`Swoosh.Adapters.SocketLabs` adapter specific setting"
       },
       %{
         group: {:subgroup, Swoosh.Adapters.SocketLabs},
         key: :api_key,
         type: :string,
-        description: "`Swoosh.Adapters.SocketLabs` adapter specific setting",
-        suggestions: [""]
+        description: "`Swoosh.Adapters.SocketLabs` adapter specific setting"
       },
       %{
         group: {:subgroup, Swoosh.Adapters.Gmail},
         key: :access_token,
         type: :string,
-        description: "`Swoosh.Adapters.Gmail` adapter specific setting",
-        suggestions: [""]
+        description: "`Swoosh.Adapters.Gmail` adapter specific setting"
       }
     ]
   },
@@ -553,38 +534,22 @@ config :pleroma, :config_description, [
       %{
         key: :registrations_open,
         type: :boolean,
-        description: "Enable registrations for anyone, invitations can be enabled when false",
-        suggestions: [
-          true,
-          false
-        ]
+        description: "Enable registrations for anyone, invitations can be enabled when false"
       },
       %{
         key: :invites_enabled,
         type: :boolean,
-        description: "Enable user invitations for admins (depends on registrations_open: false)",
-        suggestions: [
-          true,
-          false
-        ]
+        description: "Enable user invitations for admins (depends on registrations_open: false)"
       },
       %{
         key: :account_activation_required,
         type: :boolean,
-        description: "Require users to confirm their emails before signing in",
-        suggestions: [
-          true,
-          false
-        ]
+        description: "Require users to confirm their emails before signing in"
       },
       %{
         key: :federating,
         type: :boolean,
-        description: "Enable federation with other instances",
-        suggestions: [
-          true,
-          false
-        ]
+        description: "Enable federation with other instances"
       },
       %{
         key: :federation_incoming_replies_max_depth,
@@ -618,11 +583,7 @@ config :pleroma, :config_description, [
       %{
         key: :allow_relay,
         type: :boolean,
-        description: "Enable Pleroma's Relay, which makes it possible to follow a whole instance",
-        suggestions: [
-          true,
-          false
-        ]
+        description: "Enable Pleroma's Relay, which makes it possible to follow a whole instance"
       },
       %{
         key: :rewrite_policy,
@@ -638,11 +599,7 @@ config :pleroma, :config_description, [
         type: :boolean,
         description:
           "Makes the client API in authentificated mode-only except for user-profiles." <>
-            " Useful for disabling the Local Timeline and The Whole Known Network",
-        suggestions: [
-          true,
-          false
-        ]
+            " Useful for disabling the Local Timeline and The Whole Known Network"
       },
       %{
         key: :quarantined_instances,
@@ -658,11 +615,7 @@ config :pleroma, :config_description, [
         key: :managed_config,
         type: :boolean,
         description:
-          "Whenether the config for pleroma-fe is configured in this config or in static/config.json",
-        suggestions: [
-          true,
-          false
-        ]
+          "Whenether the config for pleroma-fe is configured in this config or in static/config.json"
       },
       %{
         key: :static_dir,
@@ -689,11 +642,7 @@ config :pleroma, :config_description, [
         key: :mrf_transparency,
         type: :boolean,
         description:
-          "Make the content of your Message Rewrite Facility settings public (via nodeinfo)",
-        suggestions: [
-          true,
-          false
-        ]
+          "Make the content of your Message Rewrite Facility settings public (via nodeinfo)"
       },
       %{
         key: :mrf_transparency_exclusions,
@@ -709,11 +658,7 @@ config :pleroma, :config_description, [
         type: :boolean,
         description:
           "Set to true to use extended local nicknames format (allows underscores/dashes)." <>
-            " This will break federation with older software for theses nicknames",
-        suggestions: [
-          true,
-          false
-        ]
+            " This will break federation with older software for theses nicknames"
       },
       %{
         key: :max_pinned_statuses,
@@ -741,11 +686,7 @@ config :pleroma, :config_description, [
         key: :no_attachment_links,
         type: :boolean,
         description:
-          "Set to true to disable automatically adding attachment link text to statuses",
-        suggestions: [
-          true,
-          false
-        ]
+          "Set to true to disable automatically adding attachment link text to statuses"
       },
       %{
         key: :welcome_message,
@@ -780,20 +721,12 @@ config :pleroma, :config_description, [
         description:
           "If set to true, only mentions at the beginning of a post will be used to address people in direct messages." <>
             " This is to prevent accidental mentioning of people when talking about them (e.g. \"@friend hey i really don't like @enemy\")." <>
-            " Default: false",
-        suggestions: [
-          true,
-          false
-        ]
+            " Default: false"
       },
       %{
         key: :healthcheck,
         type: :boolean,
-        description: "If set to true, system data will be shown on /api/pleroma/healthcheck",
-        suggestions: [
-          true,
-          false
-        ]
+        description: "If set to true, system data will be shown on /api/pleroma/healthcheck"
       },
       %{
         key: :remote_post_retention_days,
@@ -823,11 +756,7 @@ config :pleroma, :config_description, [
       %{
         key: :skip_thread_containment,
         type: :boolean,
-        description: "Skip filter out broken threads. The default is true",
-        suggestions: [
-          true,
-          false
-        ]
+        description: "Skip filter out broken threads. The default is true"
       },
       %{
         key: :limit_to_local_content,
@@ -844,11 +773,7 @@ config :pleroma, :config_description, [
         key: :dynamic_configuration,
         type: :boolean,
         description:
-          "Allow transferring configuration to DB with the subsequent customization from Admin api. Defaults to `false`",
-        suggestions: [
-          true,
-          false
-        ]
+          "Allow transferring configuration to DB with the subsequent customization from Admin api. Defaults to `false`"
       },
       %{
         key: :max_account_fields,
@@ -886,11 +811,7 @@ config :pleroma, :config_description, [
       %{
         key: :external_user_synchronization,
         type: :boolean,
-        description: "Enabling following/followers counters synchronization for external users",
-        suggestions: [
-          true,
-          false
-        ]
+        description: "Enabling following/followers counters synchronization for external users"
       }
     ]
   },
@@ -936,7 +857,6 @@ config :pleroma, :config_description, [
       %{
         key: :metadata,
         type: {:list, :atom},
-        description: "",
         suggestions: [[:request_id]]
       }
     ]
@@ -962,7 +882,6 @@ config :pleroma, :config_description, [
       %{
         key: :metadata,
         type: {:list, :atom},
-        description: "",
         suggestions: [[:request_id]]
       }
     ]
@@ -1069,48 +988,40 @@ config :pleroma, :config_description, [
           %{
             key: :showInstanceSpecificPanel,
             type: :boolean,
-            description: "Whenether to show the instance's specific panel",
-            suggestions: [true, false]
+            description: "Whenether to show the instance's specific panel"
           },
           %{
             key: :scopeOptionsEnabled,
             type: :boolean,
-            description: "Enable setting an notice visibility and subject/CW when posting",
-            suggestions: [true, false]
+            description: "Enable setting an notice visibility and subject/CW when posting"
           },
           %{
             key: :formattingOptionsEnabled,
             type: :boolean,
             description:
-              "Enable setting a formatting different than plain-text (ie. HTML, Markdown) when posting, relates to :instance, allowed_post_formats",
-            suggestions: [true, false]
+              "Enable setting a formatting different than plain-text (ie. HTML, Markdown) when posting, relates to :instance, allowed_post_formats"
           },
           %{
             key: :collapseMessageWithSubject,
             type: :boolean,
             description:
-              "When a message has a subject(aka Content Warning), collapse it by default",
-            suggestions: [true, false]
+              "When a message has a subject(aka Content Warning), collapse it by default"
           },
           %{
             key: :hidePostStats,
             type: :boolean,
-            description: "Hide notices statistics(repeats, favorites, ...)",
-            suggestions: [true, false]
+            description: "Hide notices statistics(repeats, favorites, ...)"
           },
           %{
             key: :hideUserStats,
             type: :boolean,
             description:
-              "Hide profile statistics(posts, posts per day, followers, followings, ...)",
-            suggestions: [true, false]
+              "Hide profile statistics(posts, posts per day, followers, followings, ...)"
           },
           %{
             key: :scopeCopy,
             type: :boolean,
-            description:
-              "Copy the scope (private/unlisted/public) in replies to posts by default",
-            suggestions: [true, false]
+            description: "Copy the scope (private/unlisted/public) in replies to posts by default"
           },
           %{
             key: :subjectLineBehavior,
@@ -1124,8 +1035,7 @@ config :pleroma, :config_description, [
           %{
             key: :alwaysShowSubjectInput,
             type: :boolean,
-            description: "When set to false, auto-hide the subject field when it's empty",
-            suggestions: [true, false]
+            description: "When set to false, auto-hide the subject field when it's empty"
           }
         ]
       },
@@ -1142,8 +1052,7 @@ config :pleroma, :config_description, [
           %{
             key: :showInstanceSpecificPanel,
             type: :boolean,
-            description: "Whenether to show the instance's specific panel",
-            suggestions: [true, false]
+            description: "Whenether to show the instance's specific panel"
           }
         ]
       }
@@ -1266,19 +1175,16 @@ config :pleroma, :config_description, [
     group: :pleroma,
     key: :mrf_rejectnonpublic,
     type: :group,
-    description: "",
     children: [
       %{
         key: :allow_followersonly,
         type: :boolean,
-        description: "whether to allow followers-only posts",
-        suggestions: [true, false]
+        description: "whether to allow followers-only posts"
       },
       %{
         key: :allow_direct,
         type: :boolean,
-        description: "whether to allow direct messages",
-        suggestions: [true, false]
+        description: "whether to allow direct messages"
       }
     ]
   },
@@ -1393,8 +1299,7 @@ config :pleroma, :config_description, [
       %{
         key: :enabled,
         type: :boolean,
-        description: "Enables proxying of remote media to the instance's proxy",
-        suggestions: [true, false]
+        description: "Enables proxying of remote media to the instance's proxy"
       },
       %{
         key: :base_url,
@@ -1426,8 +1331,7 @@ config :pleroma, :config_description, [
       %{
         key: :enabled,
         type: :boolean,
-        description: "Enables the gopher interface",
-        suggestions: [true, false]
+        description: "Enables the gopher interface"
       },
       %{
         key: :ip,
@@ -1537,43 +1441,36 @@ config :pleroma, :config_description, [
       %{
         key: :instrumenters,
         type: {:list, :module},
-        description: "",
         suggestions: [Pleroma.Web.Endpoint.Instrumenter]
       },
       %{
         key: :protocol,
         type: :string,
-        description: "",
         suggestions: ["https"]
       },
       %{
         key: :secret_key_base,
         type: :string,
-        description: "",
         suggestions: ["aK4Abxf29xU9TTDKre9coZPUgevcVCFQJe/5xP/7Lt4BEif6idBIbjupVbOrbKxl"]
       },
       %{
         key: :signing_salt,
         type: :string,
-        description: "",
         suggestions: ["CqaoopA2"]
       },
       %{
         key: :render_errors,
         type: :keyword,
-        description: "",
         suggestions: [[view: Pleroma.Web.ErrorView, accepts: ~w(json)]],
         children: [
           %{
             key: :view,
             type: :module,
-            description: "",
             suggestions: [Pleroma.Web.ErrorView]
           },
           %{
             key: :accepts,
             type: {:list, :string},
-            description: "",
             suggestions: ["json"]
           }
         ]
@@ -1581,33 +1478,27 @@ config :pleroma, :config_description, [
       %{
         key: :pubsub,
         type: :keyword,
-        description: "",
         suggestions: [[name: Pleroma.PubSub, adapter: Phoenix.PubSub.PG2]],
         children: [
           %{
             key: :name,
             type: :module,
-            description: "",
             suggestions: [Pleroma.PubSub]
           },
           %{
             key: :adapter,
             type: :module,
-            description: "",
             suggestions: [Phoenix.PubSub.PG2]
           }
         ]
       },
       %{
         key: :secure_cookie_flag,
-        type: :boolean,
-        description: "",
-        suggestions: [true, false]
+        type: :boolean
       },
       %{
         key: :extra_cookie_attrs,
         type: {:list, :string},
-        description: "",
         suggestions: ["SameSite=Lax"]
       }
     ]
@@ -1621,20 +1512,17 @@ config :pleroma, :config_description, [
       %{
         key: :unfollow_blocked,
         type: :boolean,
-        description: "Whether blocks result in people getting unfollowed",
-        suggestions: [true, false]
+        description: "Whether blocks result in people getting unfollowed"
       },
       %{
         key: :outgoing_blocks,
         type: :boolean,
-        description: "Whether to federate blocks to other instances",
-        suggestions: [true, false]
+        description: "Whether to federate blocks to other instances"
       },
       %{
         key: :sign_object_fetches,
         type: :boolean,
-        description: "Sign object fetches with HTTP signatures",
-        suggestions: [true, false]
+        description: "Sign object fetches with HTTP signatures"
       },
       %{
         key: :follow_handshake_timeout,
@@ -1653,14 +1541,12 @@ config :pleroma, :config_description, [
       %{
         key: :enabled,
         type: :boolean,
-        description: "Whether the managed content security policy is enabled",
-        suggestions: [true, false]
+        description: "Whether the managed content security policy is enabled"
       },
       %{
         key: :sts,
         type: :boolean,
-        description: "Whether to additionally send a Strict-Transport-Security header",
-        suggestions: [true, false]
+        description: "Whether to additionally send a Strict-Transport-Security header"
       },
       %{
         key: :sts_max_age,
@@ -1727,8 +1613,7 @@ config :pleroma, :config_description, [
       %{
         key: :enabled,
         type: :boolean,
-        description: "Whether the captcha should be shown on registration",
-        suggestions: [true, false]
+        description: "Whether the captcha should be shown on registration"
       },
       %{
         key: :method,
@@ -1778,8 +1663,7 @@ config :pleroma, :config_description, [
     group: :pleroma_job_queue,
     key: :queues,
     type: :group,
-    description: "[Deprecated] Replaced with `Oban`/`:queues` (keeping the same format)",
-    children: []
+    description: "[Deprecated] Replaced with `Oban`/`:queues` (keeping the same format)"
   },
   %{
     group: :pleroma,
@@ -1790,8 +1674,7 @@ config :pleroma, :config_description, [
       %{
         key: :max_retries,
         type: :integer,
-        description: "[Deprecated] Replaced as `Oban`/`:queues`/`:outgoing_federation` value",
-        suggestions: []
+        description: "[Deprecated] Replaced as `Oban`/`:queues`/`:outgoing_federation` value"
       }
     ]
   },
@@ -1817,8 +1700,7 @@ config :pleroma, :config_description, [
       %{
         key: :verbose,
         type: :boolean,
-        description: "Logs verbose mode",
-        suggestions: [false, true]
+        description: "Logs verbose mode"
       },
       %{
         key: :prune,
@@ -1937,11 +1819,7 @@ config :pleroma, :config_description, [
       %{
         key: :unfurl_nsfw,
         type: :boolean,
-        description: "If set to true nsfw attachments will be shown in previews",
-        suggestions: [
-          true,
-          false
-        ]
+        description: "If set to true nsfw attachments will be shown in previews"
       }
     ]
   },
@@ -1949,14 +1827,12 @@ config :pleroma, :config_description, [
     group: :pleroma,
     key: :rich_media,
     type: :group,
-    description: "",
     children: [
       %{
         key: :enabled,
         type: :boolean,
         description:
-          "if enabled the instance will parse metadata from attached links to generate link previews",
-        suggestions: [true, false]
+          "if enabled the instance will parse metadata from attached links to generate link previews"
       },
       %{
         key: :ignore_hosts,
@@ -1998,8 +1874,7 @@ config :pleroma, :config_description, [
         key: :enabled,
         type: :boolean,
         description:
-          "if enabled, when a new user is federated with, fetch some of their latest posts",
-        suggestions: [true, false]
+          "if enabled, when a new user is federated with, fetch some of their latest posts"
       },
       %{
         key: :pages,
@@ -2030,14 +1905,12 @@ config :pleroma, :config_description, [
       %{
         key: :new_window,
         type: :boolean,
-        description: "set to false to remove target='_blank' attribute",
-        suggestions: [true, false]
+        description: "set to false to remove target='_blank' attribute"
       },
       %{
         key: :scheme,
         type: :boolean,
-        description: "Set to true to link urls with schema http://google.com",
-        suggestions: [true, false]
+        description: "Set to true to link urls with schema http://google.com"
       },
       %{
         key: :truncate,
@@ -2049,14 +1922,12 @@ config :pleroma, :config_description, [
       %{
         key: :strip_prefix,
         type: :boolean,
-        description: "Strip the scheme prefix",
-        suggestions: [true, false]
+        description: "Strip the scheme prefix"
       },
       %{
         key: :extra,
         type: :boolean,
-        description: "link urls with rarely used schemes (magnet, ipfs, irc, etc.)",
-        suggestions: [true, false]
+        description: "link urls with rarely used schemes (magnet, ipfs, irc, etc.)"
       }
     ]
   },
@@ -2083,8 +1954,7 @@ config :pleroma, :config_description, [
       %{
         key: :enabled,
         type: :boolean,
-        description: "whether scheduled activities are sent to the job queue to be executed",
-        suggestions: [true, false]
+        description: "whether scheduled activities are sent to the job queue to be executed"
       }
     ]
   },
@@ -2097,8 +1967,7 @@ config :pleroma, :config_description, [
       %{
         key: :enabled,
         type: :boolean,
-        description: "whether expired activities will be sent to the job queue to be deleted",
-        suggestions: [true, false]
+        description: "whether expired activities will be sent to the job queue to be deleted"
       }
     ]
   },
@@ -2110,7 +1979,6 @@ config :pleroma, :config_description, [
       %{
         key: Pleroma.Web.Auth.Authenticator,
         type: :module,
-        description: "",
         suggestions: [Pleroma.Web.Auth.PleromaAuthenticator, Pleroma.Web.Auth.LDAPAuthenticator]
       }
     ]
@@ -2128,8 +1996,7 @@ config :pleroma, :config_description, [
       %{
         key: :enabled,
         type: :boolean,
-        description: "enables LDAP authentication",
-        suggestions: [true, false]
+        description: "enables LDAP authentication"
       },
       %{
         key: :host,
@@ -2146,26 +2013,22 @@ config :pleroma, :config_description, [
       %{
         key: :ssl,
         type: :boolean,
-        description: "true to use SSL, usually implies the port 636",
-        suggestions: [true, false]
+        description: "true to use SSL, usually implies the port 636"
       },
       %{
         key: :sslopts,
         type: :keyword,
-        description: "additional SSL options",
-        suggestions: []
+        description: "additional SSL options"
       },
       %{
         key: :tls,
         type: :boolean,
-        description: "true to start TLS, usually implies the port 389",
-        suggestions: [true, false]
+        description: "true to start TLS, usually implies the port 389"
       },
       %{
         key: :tlsopts,
         type: :keyword,
-        description: "additional TLS options",
-        suggestions: []
+        description: "additional TLS options"
       },
       %{
         key: :base,
@@ -2237,8 +2100,7 @@ config :pleroma, :config_description, [
           %{
             key: :active,
             type: :boolean,
-            description: "globally enable or disable digest emails",
-            suggestions: [true, false]
+            description: "globally enable or disable digest emails"
           },
           %{
             key: :schedule,
@@ -2271,7 +2133,7 @@ config :pleroma, :config_description, [
     children: [
       %{
         key: :logo,
-        type: [:string, nil],
+        type: [:string, nil],
         description: "a path to a custom logo. Set it to nil to use the default Pleroma logo",
         suggestions: ["some/path/logo.png", nil]
       },
@@ -2293,37 +2155,31 @@ config :pleroma, :config_description, [
           %{
             key: :link_color,
             type: :string,
-            description: "",
             suggestions: ["#d8a070"]
           },
           %{
             key: :background_color,
             type: :string,
-            description: "",
             suggestions: ["#2C3645"]
           },
           %{
             key: :content_background_color,
             type: :string,
-            description: "",
             suggestions: ["#1B2635"]
           },
           %{
             key: :header_color,
             type: :string,
-            description: "",
             suggestions: ["#d8a070"]
           },
           %{
             key: :text_color,
             type: :string,
-            description: "",
             suggestions: ["#b9b9ba"]
           },
           %{
             key: :text_muted_color,
             type: :string,
-            description: "",
             suggestions: ["#b9b9ba"]
           }
         ]
@@ -2346,14 +2202,12 @@ config :pleroma, :config_description, [
         key: :issue_new_refresh_token,
         type: :boolean,
         description:
-          "Keeps old refresh token or generate new refresh token when to obtain an access token",
-        suggestions: [true, false]
+          "Keeps old refresh token or generate new refresh token when to obtain an access token"
       },
       %{
         key: :clean_expired_tokens,
         type: :boolean,
-        description: "Enable a background job to clean expired oauth tokens. Defaults to false",
-        suggestions: [true, false]
+        description: "Enable a background job to clean expired oauth tokens. Defaults to false"
       },
       %{
         key: :clean_expired_tokens_interval,
@@ -2368,7 +2222,6 @@ config :pleroma, :config_description, [
     group: :pleroma,
     key: :emoji,
     type: :group,
-    description: "",
     children: [
       %{
         key: :shortcode_globs,
@@ -2415,8 +2268,7 @@ config :pleroma, :config_description, [
       %{
         key: :rum_enabled,
         type: :boolean,
-        description: "If RUM indexes should be used. Defaults to false",
-        suggestions: [true, false]
+        description: "If RUM indexes should be used. Defaults to false"
       }
     ]
   },
@@ -2475,8 +2327,7 @@ config :pleroma, :config_description, [
       %{
         key: :enabled,
         type: :boolean,
-        description: "Enables ssh",
-        suggestions: [true, false]
+        description: "Enables ssh"
       },
       %{
         key: :priv_dir,
@@ -2512,7 +2363,6 @@ config :pleroma, :config_description, [
       %{
         key: :types,
         type: :map,
-        description: "",
         suggestions: [
           %{
             "application/xml" => ["xml"],
@@ -2526,31 +2376,26 @@ config :pleroma, :config_description, [
           %{
             key: "application/xml",
             type: {:list, :string},
-            description: "",
             suggestions: [["xml"]]
           },
           %{
             key: "application/xrd+xml",
             type: {:list, :string},
-            description: "",
             suggestions: [["xrd+xml"]]
           },
           %{
             key: "application/jrd+json",
             type: {:list, :string},
-            description: "",
             suggestions: [["jrd+json"]]
           },
           %{
             key: "application/activity+json",
             type: {:list, :string},
-            description: "",
             suggestions: [["activity+json"]]
           },
           %{
             key: "application/ld+json",
             type: {:list, :string},
-            description: "",
             suggestions: [["activity+json"]]
           }
         ]
@@ -2578,9 +2423,7 @@ config :pleroma, :config_description, [
     children: [
       %{
         key: :enabled,
-        type: :boolean,
-        description: "",
-        suggestions: [true, false]
+        type: :boolean
       }
     ]
   },
@@ -2588,13 +2431,11 @@ config :pleroma, :config_description, [
     group: :pleroma,
     key: :suggestions,
     type: :group,
-    description: "",
     children: [
       %{
         key: :enabled,
         type: :boolean,
-        description: "Enables suggestions",
-        suggestions: []
+        description: "Enables suggestions"
       },
       %{
         key: :third_party_engine,
@@ -2619,7 +2460,6 @@ config :pleroma, :config_description, [
       %{
         key: :web,
         type: :string,
-        description: "",
         suggestions: ["https://vinayaka.distsn.org"]
       }
     ]
@@ -2646,7 +2486,6 @@ config :pleroma, :config_description, [
       %{
         key: :adapter,
         type: :module,
-        description: "",
         suggestions: [Pleroma.Signature]
       }
     ]
@@ -2655,18 +2494,15 @@ config :pleroma, :config_description, [
     group: :pleroma,
     key: Pleroma.Uploaders.MDII,
     type: :group,
-    description: "",
     children: [
       %{
         key: :cgi,
         type: :string,
-        description: "",
         suggestions: ["https://mdii.sakura.ne.jp/mdii-post.cgi"]
       },
       %{
         key: :files,
         type: :string,
-        description: "",
         suggestions: ["https://mdii.sakura.ne.jp"]
       }
     ]
@@ -2680,19 +2516,15 @@ config :pleroma, :config_description, [
       %{
         key: :proxy_url,
         type: [:string, :atom, nil],
-        description: "",
         suggestions: ["localhost:9020", {:socks5, :localhost, 3090}, nil]
       },
       %{
         key: :send_user_agent,
-        type: :boolean,
-        description: "",
-        suggestions: [true, false]
+        type: :boolean
       },
       %{
         key: :adapter,
         type: :keyword,
-        description: "",
         suggestions: [
           [
             ssl_options: [
@@ -2710,36 +2542,26 @@ config :pleroma, :config_description, [
     group: :pleroma,
     key: :markup,
     type: :group,
-    description: "",
     children: [
       %{
         key: :allow_inline_images,
-        type: :boolean,
-        description: "",
-        suggestions: [true, false]
+        type: :boolean
       },
       %{
         key: :allow_headings,
-        type: :boolean,
-        description: "",
-        suggestions: [true, false]
+        type: :boolean
       },
       %{
         key: :allow_tables,
-        type: :boolean,
-        description: "",
-        suggestions: [true, false]
+        type: :boolean
       },
       %{
         key: :allow_fonts,
-        type: :boolean,
-        description: "",
-        suggestions: [true, false]
+        type: :boolean
       },
       %{
         key: :scrub_policy,
         type: {:list, :module},
-        description: "",
         suggestions: [[Pleroma.HTML.Transform.MediaProxy, Pleroma.HTML.Scrubber.Default]]
       }
     ]
@@ -2748,13 +2570,10 @@ config :pleroma, :config_description, [
     group: :pleroma,
     key: :user,
     type: :group,
-    description: "",
     children: [
       %{
         key: :deny_follow_blocked,
-        type: :boolean,
-        description: "",
-        suggestions: [true, false]
+        type: :boolean
       }
     ]
   },
@@ -2762,12 +2581,10 @@ config :pleroma, :config_description, [
     group: :pleroma,
     key: :mrf_normalize_markup,
     type: :group,
-    description: "",
     children: [
       %{
         key: :scrub_policy,
         type: :module,
-        description: "",
         suggestions: [Pleroma.HTML.Scrubber.Default]
       }
     ]
@@ -2776,12 +2593,10 @@ config :pleroma, :config_description, [
     group: :pleroma,
     key: Pleroma.User,
     type: :group,
-    description: "",
     children: [
       %{
         key: :restricted_nicknames,
         type: {:list, :string},
-        description: "",
         suggestions: [
           [
             ".well-known",
@@ -2822,24 +2637,20 @@ config :pleroma, :config_description, [
   %{
     group: :cors_plug,
     type: :group,
-    description: "",
     children: [
       %{
         key: :max_age,
         type: :integer,
-        description: "",
         suggestions: [86_400]
       },
       %{
         key: :methods,
         type: {:list, :string},
-        description: "",
         suggestions: [["POST", "PUT", "DELETE", "GET", "PATCH", "OPTIONS"]]
       },
       %{
         key: :expose,
         type: :string,
-        description: "",
         suggestions: [
           [
             "Link",
@@ -2853,14 +2664,11 @@ config :pleroma, :config_description, [
       },
       %{
         key: :credentials,
-        type: :boolean,
-        description: "",
-        suggestions: [true, false]
+        type: :boolean
       },
       %{
         key: :headers,
         type: {:list, :string},
-        description: "",
         suggestions: [["Authorization", "Content-Type", "Idempotency-Key"]]
       }
     ]
index fd608c4598720f62012a91d133a60e8fecc9b90e..7637fa0d408728be4aa26ae5ce82549edc84c853 100644 (file)
@@ -224,15 +224,25 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret
 
 ## `/api/pleroma/admin/users/invite_token`
 
-### Get an account registration invite token
+### Create an account registration invite token
 
-- Methods: `GET`
+- Methods: `POST`
 - Params:
-  - *optional* `invite` => [
-    - *optional* `max_use` (integer)
-    - *optional* `expires_at` (date string e.g. "2019-04-07")
-  ]
-- Response: invite token (base64 string)
+  - *optional* `max_use` (integer)
+  - *optional* `expires_at` (date string e.g. "2019-04-07")
+- Response:
+
+```json
+{
+  "id": integer,
+  "token": string,
+  "used": boolean,
+  "expires_at": date,
+  "uses": integer,
+  "max_use": integer,
+  "invite_type": string (possible values: `one_time`, `reusable`, `date_limited`, `reusable_date_limited`)
+}
+```
 
 ## `/api/pleroma/admin/users/invites`
 
@@ -317,6 +327,7 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret
 
 ```json
 {
+  "total" : 1,
   "reports": [
     {
       "account": {
index 3b37ce630bf0545055235a7b533c5ff434b4d4bc..dabce771d402a7ef3d8d07a74a21ad56e91c1892 100644 (file)
@@ -43,23 +43,9 @@ defmodule Pleroma.Application do
         hackney_pool_children() ++
         [
           Pleroma.Stats,
-          {Oban, Pleroma.Config.get(Oban)},
-          %{
-            id: :web_push_init,
-            start: {Task, :start_link, [&Pleroma.Web.Push.init/0]},
-            restart: :temporary
-          },
-          %{
-            id: :federator_init,
-            start: {Task, :start_link, [&Pleroma.Web.Federator.init/0]},
-            restart: :temporary
-          },
-          %{
-            id: :internal_fetch_init,
-            start: {Task, :start_link, [&Pleroma.Web.ActivityPub.InternalFetchActor.init/0]},
-            restart: :temporary
-          }
+          {Oban, Pleroma.Config.get(Oban)}
         ] ++
+        task_children(@env) ++
         oauth_cleanup_child(oauth_cleanup_enabled?()) ++
         streamer_child(@env) ++
         chat_child(@env, chat_enabled?()) ++
@@ -163,4 +149,39 @@ defmodule Pleroma.Application do
       :hackney_pool.child_spec(pool, options)
     end
   end
+
+  defp task_children(:test) do
+    [
+      %{
+        id: :web_push_init,
+        start: {Task, :start_link, [&Pleroma.Web.Push.init/0]},
+        restart: :temporary
+      },
+      %{
+        id: :federator_init,
+        start: {Task, :start_link, [&Pleroma.Web.Federator.init/0]},
+        restart: :temporary
+      }
+    ]
+  end
+
+  defp task_children(_) do
+    [
+      %{
+        id: :web_push_init,
+        start: {Task, :start_link, [&Pleroma.Web.Push.init/0]},
+        restart: :temporary
+      },
+      %{
+        id: :federator_init,
+        start: {Task, :start_link, [&Pleroma.Web.Federator.init/0]},
+        restart: :temporary
+      },
+      %{
+        id: :internal_fetch_init,
+        start: {Task, :start_link, [&Pleroma.Web.ActivityPub.InternalFetchActor.init/0]},
+        restart: :temporary
+      }
+    ]
+  end
 end
index ef14185435273507e5e699d959646bfb11fa99b2..0bf20cdd0ecb8b384b93b194ed3d73d043e2fbb6 100644 (file)
@@ -6,4 +6,16 @@ defmodule Pleroma.Constants do
   use Const
 
   const(as_public, do: "https://www.w3.org/ns/activitystreams#Public")
+
+  const(object_internal_fields,
+    do: [
+      "likes",
+      "like_count",
+      "announcements",
+      "announcement_count",
+      "emoji",
+      "context_id",
+      "deleted_activity_id"
+    ]
+  )
 end
index 8386dc2fbe207c7a380a47853a69c0a2ac39e910..68b10649955ab2ab4a7cfc4a6adee1c36b9611e3 100644 (file)
@@ -23,7 +23,7 @@ defmodule Pleroma.Docs.Markdown do
 
       IO.write(file, "#{group[:description]}\n")
 
-      for child <- group[:children] do
+      for child <- group[:children] || [] do
         print_child_header(file, child)
 
         print_suggestions(file, child[:suggestions])
@@ -44,6 +44,17 @@ defmodule Pleroma.Docs.Markdown do
     {:ok, config_path}
   end
 
+  defp print_child_header(file, %{key: key, type: type, description: description} = _child) do
+    IO.write(
+      file,
+      "- `#{inspect(key)}` (`#{inspect(type)}`): #{description}  \n"
+    )
+  end
+
+  defp print_child_header(file, %{key: key, type: type} = _child) do
+    IO.write(file, "- `#{inspect(key)}` (`#{inspect(type)}`)  \n")
+  end
+
   defp print_suggestion(file, suggestion) when is_list(suggestion) do
     IO.write(file, "  `#{inspect(suggestion)}`\n")
   end
@@ -59,20 +70,19 @@ defmodule Pleroma.Docs.Markdown do
 
   defp print_suggestions(_file, nil), do: nil
 
-  defp print_suggestions(file, suggestions) do
-    IO.write(file, "Suggestions:\n")
+  defp print_suggestions(_file, ""), do: nil
 
+  defp print_suggestions(file, suggestions) do
     if length(suggestions) > 1 do
+      IO.write(file, "Suggestions:\n")
+
       for suggestion <- suggestions do
         print_suggestion(file, suggestion, true)
       end
     else
+      IO.write(file, "  Suggestion: ")
+
       print_suggestion(file, List.first(suggestions))
     end
   end
-
-  defp print_child_header(file, child) do
-    IO.write(file, "- `#{inspect(child[:key])}` -`#{inspect(child[:type])}`  \n")
-    IO.write(file, "#{child[:description]}  \n")
-  end
 end
index 47d61ca5f16e85990ebaa0197800fd08498ea702..042cf8659cd0e57ece74b6af6693c7d74d212717 100644 (file)
@@ -14,7 +14,7 @@ defmodule Pleroma.FlakeId do
 
   @type t :: binary
 
-  @behaviour Ecto.Type
+  use Ecto.Type
   use GenServer
   require Logger
   alias __MODULE__
index 5033798aeacbf11fc2f5c81d2c9d4a638c72a710..3fa407931e3bd43d8fba928852232f75f2d09192 100644 (file)
@@ -38,6 +38,24 @@ defmodule Pleroma.Object do
   def get_by_id(nil), do: nil
   def get_by_id(id), do: Repo.get(Object, id)
 
+  def get_by_id_and_maybe_refetch(id, opts \\ []) do
+    %{updated_at: updated_at} = object = get_by_id(id)
+
+    if opts[:interval] &&
+         NaiveDateTime.diff(NaiveDateTime.utc_now(), updated_at) > opts[:interval] do
+      case Fetcher.refetch_object(object) do
+        {:ok, %Object{} = object} ->
+          object
+
+        e ->
+          Logger.error("Couldn't refresh #{object.data["id"]}:\n#{inspect(e)}")
+          object
+      end
+    else
+      object
+    end
+  end
+
   def get_by_ap_id(nil), do: nil
 
   def get_by_ap_id(ap_id) do
index c1795ae0fe1e9c041d318335026b2744fae045d2..cea33b5af26e9ef3a56b12f688ca63a6de0c5a52 100644 (file)
@@ -6,18 +6,39 @@ defmodule Pleroma.Object.Fetcher do
   alias Pleroma.HTTP
   alias Pleroma.Object
   alias Pleroma.Object.Containment
+  alias Pleroma.Repo
   alias Pleroma.Signature
   alias Pleroma.Web.ActivityPub.InternalFetchActor
   alias Pleroma.Web.ActivityPub.Transmogrifier
   alias Pleroma.Web.OStatus
 
   require Logger
+  require Pleroma.Constants
 
-  defp reinject_object(data) do
+  defp touch_changeset(changeset) do
+    updated_at =
+      NaiveDateTime.utc_now()
+      |> NaiveDateTime.truncate(:second)
+
+    Ecto.Changeset.put_change(changeset, :updated_at, updated_at)
+  end
+
+  defp maybe_reinject_internal_fields(data, %{data: %{} = old_data}) do
+    internal_fields = Map.take(old_data, Pleroma.Constants.object_internal_fields())
+
+    Map.merge(data, internal_fields)
+  end
+
+  defp maybe_reinject_internal_fields(data, _), do: data
+
+  defp reinject_object(struct, data) do
     Logger.debug("Reinjecting object #{data["id"]}")
 
     with data <- Transmogrifier.fix_object(data),
-         {:ok, object} <- Object.create(data) do
+         data <- maybe_reinject_internal_fields(data, struct),
+         changeset <- Object.change(struct, %{data: data}),
+         changeset <- touch_changeset(changeset),
+         {:ok, object} <- Repo.insert_or_update(changeset) do
       {:ok, object}
     else
       e ->
@@ -26,6 +47,17 @@ defmodule Pleroma.Object.Fetcher do
     end
   end
 
+  def refetch_object(%Object{data: %{"id" => id}} = object) do
+    with {:local, false} <- {:local, String.starts_with?(id, Pleroma.Web.base_url() <> "/")},
+         {:ok, data} <- fetch_and_contain_remote_object_from_id(id),
+         {:ok, object} <- reinject_object(object, data) do
+      {:ok, object}
+    else
+      {:local, true} -> object
+      e -> {:error, e}
+    end
+  end
+
   # TODO:
   # This will create a Create activity, which we need internally at the moment.
   def fetch_object_from_id(id, options \\ []) do
@@ -57,7 +89,7 @@ defmodule Pleroma.Object.Fetcher do
           {:reject, nil}
 
         {:object, data, nil} ->
-          reinject_object(data)
+          reinject_object(%Object{}, data)
 
         {:normalize, object = %Object{}} ->
           {:ok, object}
index dd2b1c8c436e8a479884317a52164cc5ececb993..fb1f2425438c0de4b5e7c38b652dca8e5187f2e4 100644 (file)
@@ -150,6 +150,7 @@ defmodule Pleroma.User do
     Cachex.fetch!(:user_cache, key, fn _ -> {:commit, follow_state(user, target)} end)
   end
 
+  @spec set_follow_state_cache(String.t(), String.t(), String.t()) :: {:ok | :error, boolean()}
   def set_follow_state_cache(user_ap_id, target_ap_id, state) do
     Cachex.put(
       :user_cache,
index bc5ae7fbf92194943344b055422d39ef3d6d7996..e1e90d667f2d36262834d00930638cdf672cb691 100644 (file)
@@ -410,6 +410,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
     end
   end
 
+  @spec block(User.t(), User.t(), String.t() | nil, boolean) :: {:ok, Activity.t() | nil}
   def block(blocker, blocked, activity_id \\ nil, local \\ true) do
     outgoing_blocks = Config.get([:activitypub, :outgoing_blocks])
     unfollow_blocked = Config.get([:activitypub, :unfollow_blocked])
@@ -438,10 +439,11 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
     end
   end
 
+  @spec flag(map()) :: {:ok, Activity.t()} | any
   def flag(
         %{
           actor: actor,
-          context: context,
+          context: _context,
           account: account,
           statuses: statuses,
           content: content
@@ -453,14 +455,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
 
     additional = params[:additional] || %{}
 
-    params = %{
-      actor: actor,
-      context: context,
-      account: account,
-      statuses: statuses,
-      content: content
-    }
-
     additional =
       if forward do
         Map.merge(additional, %{"to" => [], "cc" => [account.ap_id]})
index acb3087d06defa4d869699ee08642fe05fb9e3fb..9d2ddc1cd75e094a9d2232a51561410e5786b1c7 100644 (file)
@@ -979,15 +979,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
 
   defp strip_internal_fields(object) do
     object
-    |> Map.drop([
-      "likes",
-      "like_count",
-      "announcements",
-      "announcement_count",
-      "emoji",
-      "context_id",
-      "deleted_activity_id"
-    ])
+    |> Map.drop(Pleroma.Constants.object_internal_fields())
   end
 
   defp strip_internal_tags(%{"tag" => tags} = object) do
@@ -1050,7 +1042,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
     with %User{local: false} = user <- User.get_cached_by_ap_id(ap_id),
          {:ok, data} <- ActivityPub.fetch_and_prepare_user_from_ap_id(ap_id),
          already_ap <- User.ap_enabled?(user),
-         {:ok, user} <- user |> User.upgrade_changeset(data) |> User.update_and_set_cache() do
+         {:ok, user} <- user |> User.upgrade_changeset(data, true) |> User.update_and_set_cache() do
       unless already_ap do
         TransmogrifierWorker.enqueue("user_upgrade", %{"user_id" => user.id})
       end
index 258e56066439372d612f4b73c58cac150fe0d546..30628a793e4162728b3c0bd0a475812792ff69e6 100644 (file)
@@ -33,50 +33,40 @@ defmodule Pleroma.Web.ActivityPub.Utils do
     Map.put(params, "actor", get_ap_id(params["actor"]))
   end
 
-  def determine_explicit_mentions(%{"tag" => tag} = _object) when is_list(tag) do
-    tag
-    |> Enum.filter(fn x -> is_map(x) end)
-    |> Enum.filter(fn x -> x["type"] == "Mention" end)
-    |> Enum.map(fn x -> x["href"] end)
+  @spec determine_explicit_mentions(map()) :: map()
+  def determine_explicit_mentions(%{"tag" => tag} = _) when is_list(tag) do
+    Enum.flat_map(tag, fn
+      %{"type" => "Mention", "href" => href} -> [href]
+      _ -> []
+    end)
   end
 
   def determine_explicit_mentions(%{"tag" => tag} = object) when is_map(tag) do
-    Map.put(object, "tag", [tag])
+    object
+    |> Map.put("tag", [tag])
     |> determine_explicit_mentions()
   end
 
   def determine_explicit_mentions(_), do: []
 
+  @spec recipient_in_collection(any(), any()) :: boolean()
   defp recipient_in_collection(ap_id, coll) when is_binary(coll), do: ap_id == coll
   defp recipient_in_collection(ap_id, coll) when is_list(coll), do: ap_id in coll
   defp recipient_in_collection(_, _), do: false
 
+  @spec recipient_in_message(User.t(), User.t(), map()) :: boolean()
   def recipient_in_message(%User{ap_id: ap_id} = recipient, %User{} = actor, params) do
-    cond do
-      recipient_in_collection(ap_id, params["to"]) ->
-        true
-
-      recipient_in_collection(ap_id, params["cc"]) ->
-        true
-
-      recipient_in_collection(ap_id, params["bto"]) ->
-        true
-
-      recipient_in_collection(ap_id, params["bcc"]) ->
-        true
+    addresses = [params["to"], params["cc"], params["bto"], params["bcc"]]
 
+    cond do
+      Enum.any?(addresses, &recipient_in_collection(ap_id, &1)) -> true
       # if the message is unaddressed at all, then assume it is directly addressed
       # to the recipient
-      !params["to"] && !params["cc"] && !params["bto"] && !params["bcc"] ->
-        true
-
+      Enum.all?(addresses, &is_nil(&1)) -> true
       # if the message is sent from somebody the user is following, then assume it
       # is addressed to the recipient
-      User.following?(recipient, actor) ->
-        true
-
-      true ->
-        false
+      User.following?(recipient, actor) -> true
+      true -> false
     end
   end
 
@@ -179,54 +169,59 @@ defmodule Pleroma.Web.ActivityPub.Utils do
   Adds an id and a published data if they aren't there,
   also adds it to an included object
   """
-  def lazy_put_activity_defaults(map, fake? \\ false) do
-    map =
-      if not fake? do
-        %{data: %{"id" => context}, id: context_id} = create_context(map["context"])
-
-        map
-        |> Map.put_new_lazy("id", &generate_activity_id/0)
-        |> Map.put_new_lazy("published", &make_date/0)
-        |> Map.put_new("context", context)
-        |> Map.put_new("context_id", context_id)
-      else
-        map
-        |> Map.put_new("id", "pleroma:fakeid")
-        |> Map.put_new_lazy("published", &make_date/0)
-        |> Map.put_new("context", "pleroma:fakecontext")
-        |> Map.put_new("context_id", -1)
-      end
+  @spec lazy_put_activity_defaults(map(), boolean) :: map()
+  def lazy_put_activity_defaults(map, fake? \\ false)
 
-    if is_map(map["object"]) do
-      object = lazy_put_object_defaults(map["object"], map, fake?)
-      %{map | "object" => object}
-    else
-      map
-    end
+  def lazy_put_activity_defaults(map, true) do
+    map
+    |> Map.put_new("id", "pleroma:fakeid")
+    |> Map.put_new_lazy("published", &make_date/0)
+    |> Map.put_new("context", "pleroma:fakecontext")
+    |> Map.put_new("context_id", -1)
+    |> lazy_put_object_defaults(true)
   end
 
-  @doc """
-  Adds an id and published date if they aren't there.
-  """
-  def lazy_put_object_defaults(map, activity \\ %{}, fake?)
+  def lazy_put_activity_defaults(map, _fake?) do
+    %{data: %{"id" => context}, id: context_id} = create_context(map["context"])
 
-  def lazy_put_object_defaults(map, activity, true = _fake?) do
     map
+    |> Map.put_new_lazy("id", &generate_activity_id/0)
     |> Map.put_new_lazy("published", &make_date/0)
-    |> Map.put_new("id", "pleroma:fake_object_id")
-    |> Map.put_new("context", activity["context"])
-    |> Map.put_new("fake", true)
-    |> Map.put_new("context_id", activity["context_id"])
+    |> Map.put_new("context", context)
+    |> Map.put_new("context_id", context_id)
+    |> lazy_put_object_defaults(false)
   end
 
-  def lazy_put_object_defaults(map, activity, _fake?) do
-    map
-    |> Map.put_new_lazy("id", &generate_object_id/0)
-    |> Map.put_new_lazy("published", &make_date/0)
-    |> Map.put_new("context", activity["context"])
-    |> Map.put_new("context_id", activity["context_id"])
+  # Adds an id and published date if they aren't there.
+  #
+  @spec lazy_put_object_defaults(map(), boolean()) :: map()
+  defp lazy_put_object_defaults(%{"object" => map} = activity, true)
+       when is_map(map) do
+    object =
+      map
+      |> Map.put_new("id", "pleroma:fake_object_id")
+      |> Map.put_new_lazy("published", &make_date/0)
+      |> Map.put_new("context", activity["context"])
+      |> Map.put_new("context_id", activity["context_id"])
+      |> Map.put_new("fake", true)
+
+    %{activity | "object" => object}
+  end
+
+  defp lazy_put_object_defaults(%{"object" => map} = activity, _)
+       when is_map(map) do
+    object =
+      map
+      |> Map.put_new_lazy("id", &generate_object_id/0)
+      |> Map.put_new_lazy("published", &make_date/0)
+      |> Map.put_new("context", activity["context"])
+      |> Map.put_new("context_id", activity["context_id"])
+
+    %{activity | "object" => object}
   end
 
+  defp lazy_put_object_defaults(activity, _), do: activity
+
   @doc """
   Inserts a full object if it is contained in an activity.
   """
@@ -345,24 +340,24 @@ defmodule Pleroma.Web.ActivityPub.Utils do
   @doc """
   Updates a follow activity's state (for locked accounts).
   """
+  @spec update_follow_state_for_all(Activity.t(), String.t()) :: {:ok, Activity} | {:error, any()}
   def update_follow_state_for_all(
         %Activity{data: %{"actor" => actor, "object" => object}} = activity,
         state
       ) do
-    try do
-      Ecto.Adapters.SQL.query!(
-        Repo,
-        "UPDATE activities SET data = jsonb_set(data, '{state}', $1) WHERE data->>'type' = 'Follow' AND data->>'actor' = $2 AND data->>'object' = $3 AND data->>'state' = 'pending'",
-        [state, actor, object]
-      )
+    "Follow"
+    |> Activity.Queries.by_type()
+    |> Activity.Queries.by_actor(actor)
+    |> Activity.Queries.by_object_id(object)
+    |> where(fragment("data->>'state' = 'pending'"))
+    |> update(set: [data: fragment("jsonb_set(data, '{state}', ?)", ^state)])
+    |> Repo.update_all([])
 
-      User.set_follow_state_cache(actor, object, state)
-      activity = Activity.get_by_id(activity.id)
-      {:ok, activity}
-    rescue
-      e ->
-        {:error, e}
-    end
+    User.set_follow_state_cache(actor, object, state)
+
+    activity = Activity.get_by_id(activity.id)
+
+    {:ok, activity}
   end
 
   def update_follow_state(
@@ -413,6 +408,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
   @doc """
   Retruns an existing announce activity if the notice has already been announced
   """
+  @spec get_existing_announce(String.t(), map()) :: Activity.t() | nil
   def get_existing_announce(actor, %{data: %{"id" => ap_id}}) do
     "Announce"
     |> Activity.Queries.by_type()
@@ -495,33 +491,35 @@ defmodule Pleroma.Web.ActivityPub.Utils do
     |> maybe_put("id", activity_id)
   end
 
+  @spec add_announce_to_object(Activity.t(), Object.t()) ::
+          {:ok, Object.t()} | {:error, Ecto.Changeset.t()}
   def add_announce_to_object(
-        %Activity{
-          data: %{"actor" => actor, "cc" => [Pleroma.Constants.as_public()]}
-        },
+        %Activity{data: %{"actor" => actor, "cc" => [Pleroma.Constants.as_public()]}},
         object
       ) do
-    announcements =
-      if is_list(object.data["announcements"]) do
-        Enum.uniq([actor | object.data["announcements"]])
-      else
-        [actor]
-      end
+    announcements = take_announcements(object)
 
-    update_element_in_object("announcement", announcements, object)
+    with announcements <- Enum.uniq([actor | announcements]) do
+      update_element_in_object("announcement", announcements, object)
+    end
   end
 
   def add_announce_to_object(_, object), do: {:ok, object}
 
+  @spec remove_announce_from_object(Activity.t(), Object.t()) ::
+          {:ok, Object.t()} | {:error, Ecto.Changeset.t()}
   def remove_announce_from_object(%Activity{data: %{"actor" => actor}}, object) do
-    announcements =
-      if is_list(object.data["announcements"]), do: object.data["announcements"], else: []
-
-    with announcements <- announcements |> List.delete(actor) do
+    with announcements <- List.delete(take_announcements(object), actor) do
       update_element_in_object("announcement", announcements, object)
     end
   end
 
+  defp take_announcements(%{data: %{"announcements" => announcements}} = _)
+       when is_list(announcements),
+       do: announcements
+
+  defp take_announcements(_), do: []
+
   #### Unfollow-related helpers
 
   def make_unfollow_data(follower, followed, follow_activity, activity_id) do
@@ -535,6 +533,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
   end
 
   #### Block-related helpers
+  @spec fetch_latest_block(User.t(), User.t()) :: Activity.t() | nil
   def fetch_latest_block(%User{ap_id: blocker_id}, %User{ap_id: blocked_id}) do
     "Block"
     |> Activity.Queries.by_type()
@@ -583,28 +582,32 @@ defmodule Pleroma.Web.ActivityPub.Utils do
   end
 
   #### Flag-related helpers
-
-  def make_flag_data(params, additional) do
-    status_ap_ids =
-      Enum.map(params.statuses || [], fn
-        %Activity{} = act -> act.data["id"]
-        act when is_map(act) -> act["id"]
-        act when is_binary(act) -> act
-      end)
-
-    object = [params.account.ap_id] ++ status_ap_ids
-
+  @spec make_flag_data(map(), map()) :: map()
+  def make_flag_data(%{actor: actor, context: context, content: content} = params, additional) do
     %{
       "type" => "Flag",
-      "actor" => params.actor.ap_id,
-      "content" => params.content,
-      "object" => object,
-      "context" => params.context,
+      "actor" => actor.ap_id,
+      "content" => content,
+      "object" => build_flag_object(params),
+      "context" => context,
       "state" => "open"
     }
     |> Map.merge(additional)
   end
 
+  def make_flag_data(_, _), do: %{}
+
+  defp build_flag_object(%{account: account, statuses: statuses} = _) do
+    [account.ap_id] ++
+      Enum.map(statuses || [], fn
+        %Activity{} = act -> act.data["id"]
+        act when is_map(act) -> act["id"]
+        act when is_binary(act) -> act
+      end)
+  end
+
+  defp build_flag_object(_), do: []
+
   @doc """
   Fetches the OrderedCollection/OrderedCollectionPage from `from`, limiting the amount of pages fetched after
   the first one to `pages_left` pages.
index 544b9d7d8b530018120c3f1a9f15af36a223e43a..8a8091daa2e39cf3375e13294febff14bdabaaed 100644 (file)
@@ -400,13 +400,23 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
     end
   end
 
-  @doc "Get a account registeration invite token (base64 string)"
-  def get_invite_token(conn, params) do
-    options = params["invite"] || %{}
-    {:ok, invite} = UserInviteToken.create_invite(options)
+  @doc "Create an account registration invite token"
+  def create_invite_token(conn, params) do
+    opts = %{}
 
-    conn
-    |> json(invite.token)
+    opts =
+      if params["max_use"],
+        do: Map.put(opts, :max_use, params["max_use"]),
+        else: opts
+
+    opts =
+      if params["expires_at"],
+        do: Map.put(opts, :expires_at, params["expires_at"]),
+        else: opts
+
+    {:ok, invite} = UserInviteToken.create_invite(opts)
+
+    json(conn, AccountView.render("invite.json", %{invite: invite}))
   end
 
   @doc "Get list of created invites"
@@ -442,11 +452,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
       params
       |> Map.put("type", "Flag")
       |> Map.put("skip_preload", true)
+      |> Map.put("total", true)
 
-    reports =
-      []
-      |> ActivityPub.fetch_activities(params)
-      |> Enum.reverse()
+    reports = ActivityPub.fetch_activities([], params)
 
     conn
     |> put_view(ReportView)
index a25f3f1fed39c80f3685b1301a7535df9e4e5a79..51b95ad5ef708b4178c895f3c21146d7ed99f621 100644 (file)
@@ -12,7 +12,9 @@ defmodule Pleroma.Web.AdminAPI.ReportView do
 
   def render("index.json", %{reports: reports}) do
     %{
-      reports: render_many(reports, __MODULE__, "show.json", as: :report)
+      reports:
+        render_many(reports[:items], __MODULE__, "show.json", as: :report) |> Enum.reverse(),
+      total: reports[:total]
     }
   end
 
index 1beb4bcf28fa49462b195bfbb9ae47a97daa75af..37eeb2ac33be4d14d70da77a2f2dfa0ea04eb29f 100644 (file)
@@ -487,7 +487,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
   end
 
   def get_poll(%{assigns: %{user: user}} = conn, %{"id" => id}) do
-    with %Object{} = object <- Object.get_by_id(id),
+    with %Object{} = object <- Object.get_by_id_and_maybe_refetch(id, interval: 60),
          %Activity{} = activity <- Activity.get_create_by_object_ap_id(object.data["id"]),
          true <- Visibility.visible_for_user?(activity, user) do
       conn
index 401133bf3d750c4a55adaf3dafce2b09467bad9b..b9b85fd6776ca31ffdf2c4970034c51cae0173f7 100644 (file)
@@ -180,7 +180,7 @@ defmodule Pleroma.Web.Router do
     post("/relay", AdminAPIController, :relay_follow)
     delete("/relay", AdminAPIController, :relay_unfollow)
 
-    get("/users/invite_token", AdminAPIController, :get_invite_token)
+    post("/users/invite_token", AdminAPIController, :create_invite_token)
     get("/users/invites", AdminAPIController, :invites)
     post("/users/revoke_invite", AdminAPIController, :revoke_invite)
     post("/users/email_invite", AdminAPIController, :email_invite)
index 7b5199068f2a1c82a5b40f333fae56dc6f181eef..c48752d95b2ab0d10d4dd2d523717b51b5711dc4 100644 (file)
@@ -4,16 +4,18 @@ defmodule Pleroma.Web.Streamer.State do
 
   alias Pleroma.Web.Streamer.StreamerSocket
 
+  @env Mix.env()
+
   def start_link(_) do
     GenServer.start_link(__MODULE__, %{sockets: %{}}, name: __MODULE__)
   end
 
   def add_socket(topic, socket) do
-    GenServer.call(__MODULE__, {:add, socket, topic})
+    GenServer.call(__MODULE__, {:add, topic, socket})
   end
 
   def remove_socket(topic, socket) do
-    GenServer.call(__MODULE__, {:remove, socket, topic})
+    do_remove_socket(@env, topic, socket)
   end
 
   def get_sockets do
@@ -29,7 +31,7 @@ defmodule Pleroma.Web.Streamer.State do
     {:reply, state, state}
   end
 
-  def handle_call({:add, socket, topic}, _from, %{sockets: sockets} = state) do
+  def handle_call({:add, topic, socket}, _from, %{sockets: sockets} = state) do
     internal_topic = internal_topic(topic, socket)
     stream_socket = StreamerSocket.from_socket(socket)
 
@@ -44,7 +46,7 @@ defmodule Pleroma.Web.Streamer.State do
     {:reply, state, state}
   end
 
-  def handle_call({:remove, socket, topic}, _from, %{sockets: sockets} = state) do
+  def handle_call({:remove, topic, socket}, _from, %{sockets: sockets} = state) do
     internal_topic = internal_topic(topic, socket)
     stream_socket = StreamerSocket.from_socket(socket)
 
@@ -57,6 +59,14 @@ defmodule Pleroma.Web.Streamer.State do
     {:reply, state, state}
   end
 
+  defp do_remove_socket(:test, _, _) do
+    :ok
+  end
+
+  defp do_remove_socket(_env, topic, socket) do
+    GenServer.call(__MODULE__, {:remove, topic, socket})
+  end
+
   defp internal_topic(topic, socket)
        when topic in ~w[user user:notification direct] do
     "#{topic}:#{socket.assigns[:user].id}"
index bea2baffb26d8dfc359c7abdcae3ced872ccfcf4..61b451e3ed99aecd8fb7bdee08c084b0138bf74f 100644 (file)
@@ -10,7 +10,11 @@ defmodule Pleroma.Workers.WebPusherWorker do
 
   @impl Oban.Worker
   def perform(%{"op" => "web_push", "notification_id" => notification_id}, _job) do
-    notification = Repo.get(Notification, notification_id)
+    notification =
+      Notification
+      |> Repo.get(notification_id)
+      |> Repo.preload([:activity])
+
     Pleroma.Web.Push.Impl.perform(notification)
   end
 end
diff --git a/mix.exs b/mix.exs
index 911ebad1d4479cc16e35df05919b688481e4f75b..f2635da2427feacc994c00d08ea7400d12f86f97 100644 (file)
--- a/mix.exs
+++ b/mix.exs
@@ -5,7 +5,7 @@ defmodule Pleroma.Mixfile do
     [
       app: :pleroma,
       version: version("1.0.0"),
-      elixir: "~> 1.7",
+      elixir: "~> 1.8",
       elixirc_paths: elixirc_paths(Mix.env()),
       compilers: [:phoenix, :gettext] ++ Mix.compilers(),
       elixirc_options: [warnings_as_errors: true],
@@ -99,9 +99,9 @@ defmodule Pleroma.Mixfile do
       {:plug_cowboy, "~> 2.0"},
       {:phoenix_pubsub, "~> 1.1"},
       {:phoenix_ecto, "~> 4.0"},
-      {:ecto_sql, "~> 3.1"},
+      {:ecto_sql, "~> 3.2"},
       {:postgrex, ">= 0.13.5"},
-      {:oban, "~> 0.7"},
+      {:oban, "~> 0.8.1"},
       {:quantum, "~> 2.3"},
       {:gettext, "~> 0.15"},
       {:comeonin, "~> 4.1.1"},
@@ -113,7 +113,7 @@ defmodule Pleroma.Mixfile do
       {:calendar, "~> 0.17.4"},
       {:cachex, "~> 3.0.2"},
       {:poison, "~> 3.0", override: true},
-      {:tesla, "~> 1.2"},
+      {:tesla, "~> 1.3", override: true},
       {:jason, "~> 1.0"},
       {:mogrify, "~> 0.6.1"},
       {:ex_aws, "~> 2.1"},
@@ -174,7 +174,8 @@ defmodule Pleroma.Mixfile do
       "ecto.rollback": ["pleroma.ecto.rollback"],
       "ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"],
       "ecto.reset": ["ecto.drop", "ecto.setup"],
-      test: ["ecto.create --quiet", "ecto.migrate", "test"]
+      test: ["ecto.create --quiet", "ecto.migrate", "test"],
+      docs: ["pleroma.docs", "docs"]
     ]
   end
 
index 0bf6a811ee53cc8e42789839de92e8c8cc458ed1..24b34c09c9f6e2fa91af2d49f861d0598ad5193b 100644 (file)
--- a/mix.lock
+++ b/mix.lock
@@ -21,8 +21,8 @@
   "decimal": {:hex, :decimal, "1.8.0", "ca462e0d885f09a1c5a342dbd7c1dcf27ea63548c65a65e67334f4b61803822e", [:mix], [], "hexpm"},
   "deep_merge": {:hex, :deep_merge, "1.0.0", "b4aa1a0d1acac393bdf38b2291af38cb1d4a52806cf7a4906f718e1feb5ee961", [:mix], [], "hexpm"},
   "earmark": {:hex, :earmark, "1.3.6", "ce1d0675e10a5bb46b007549362bd3f5f08908843957687d8484fe7f37466b19", [:mix], [], "hexpm"},
-  "ecto": {:hex, :ecto, "3.1.4", "69d852da7a9f04ede725855a35ede48d158ca11a404fe94f8b2fb3b2162cd3c9", [:mix], [{:decimal, "~> 1.6", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm"},
-  "ecto_sql": {:hex, :ecto_sql, "3.1.3", "2c536139190492d9de33c5fefac7323c5eaaa82e1b9bf93482a14649042f7cd9", [:mix], [{:db_connection, "~> 2.0", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.1.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:mariaex, "~> 0.9.1", [hex: :mariaex, repo: "hexpm", optional: true]}, {:myxql, "~> 0.2.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.14.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm"},
+  "ecto": {:hex, :ecto, "3.2.0", "940e2598813f205223d60c78d66e514afe1db5167ed8075510a59e496619cfb5", [:mix], [{:decimal, "~> 1.6", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm"},
+  "ecto_sql": {:hex, :ecto_sql, "3.2.0", "751cea597e8deb616084894dd75cbabfdbe7255ff01e8c058ca13f0353a3921b", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.2.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.2.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.15.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm"},
   "esshd": {:hex, :esshd, "0.1.0", "6f93a2062adb43637edad0ea7357db2702a4b80dd9683482fe00f5134e97f4c1", [:mix], [], "hexpm"},
   "eternal": {:hex, :eternal, "1.2.0", "e2a6b6ce3b8c248f7dc31451aefca57e3bdf0e48d73ae5043229380a67614c41", [:mix], [], "hexpm"},
   "ex2ms": {:hex, :ex2ms, "1.5.0", "19e27f9212be9a96093fed8cdfbef0a2b56c21237196d26760f11dfcfae58e97", [:mix], [], "hexpm"},
@@ -60,7 +60,7 @@
   "mogrify": {:hex, :mogrify, "0.6.1", "de1b527514f2d95a7bbe9642eb556061afb337e220cf97adbf3a4e6438ed70af", [:mix], [], "hexpm"},
   "mox": {:hex, :mox, "0.5.1", "f86bb36026aac1e6f924a4b6d024b05e9adbed5c63e8daa069bd66fb3292165b", [:mix], [], "hexpm"},
   "nimble_parsec": {:hex, :nimble_parsec, "0.5.1", "c90796ecee0289dbb5ad16d3ad06f957b0cd1199769641c961cfe0b97db190e0", [:mix], [], "hexpm"},
-  "oban": {:hex, :oban, "0.7.1", "171bdd1b69c1a4a839f8c768f5e962fc22d1de1513d459fb6b8e0cbd34817a9a", [:mix], [{:ecto_sql, "~> 3.1", [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"},
+  "oban": {:hex, :oban, "0.8.1", "4bbf62eb1829f856d69aeb5069ac7036afe07db8221a17de2a9169cc7a58a318", [:mix], [{:ecto_sql, "~> 3.1", [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"},
   "parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm"},
   "pbkdf2_elixir": {:hex, :pbkdf2_elixir, "0.12.3", "6706a148809a29c306062862c803406e88f048277f6e85b68faf73291e820b84", [:mix], [], "hexpm"},
   "phoenix": {:hex, :phoenix, "1.4.9", "746d098e10741c334d88143d3c94cab1756435f94387a63441792e66ec0ee974", [: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"},
@@ -74,7 +74,7 @@
   "plug_static_index_html": {:hex, :plug_static_index_html, "1.0.0", "840123d4d3975585133485ea86af73cb2600afd7f2a976f9f5fd8b3808e636a0", [:mix], [{:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
   "poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], [], "hexpm"},
   "poolboy": {:hex, :poolboy, "1.5.2", "392b007a1693a64540cead79830443abf5762f5d30cf50bc95cb2c1aaafa006b", [:rebar3], [], "hexpm"},
-  "postgrex": {:hex, :postgrex, "0.14.3", "5754dee2fdf6e9e508cbf49ab138df964278700b764177e8f3871e658b345a1e", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.0", [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"},
+  "postgrex": {:hex, :postgrex, "0.15.1", "23ce3417de70f4c0e9e7419ad85bdabcc6860a6925fe2c6f3b1b5b1e8e47bf2f", [: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"},
   "prometheus": {:hex, :prometheus, "4.4.1", "1e96073b3ed7788053768fea779cbc896ddc3bdd9ba60687f2ad50b252ac87d6", [:mix, :rebar3], [], "hexpm"},
   "prometheus_ecto": {:hex, :prometheus_ecto, "1.4.1", "6c768ea9654de871e5b32fab2eac348467b3021604ebebbcbd8bcbe806a65ed5", [: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"},
   "prometheus_ex": {:hex, :prometheus_ex, "3.0.5", "fa58cfd983487fc5ead331e9a3e0aa622c67232b3ec71710ced122c4c453a02f", [:mix], [{:prometheus, "~> 4.0", [hex: :prometheus, repo: "hexpm", optional: false]}], "hexpm"},
@@ -90,7 +90,7 @@
   "swoosh": {:hex, :swoosh, "0.23.2", "7dda95ff0bf54a2298328d6899c74dae1223777b43563ccebebb4b5d2b61df38", [: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: false]}, {: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"},
   "syslog": {:git, "https://github.com/Vagabond/erlang-syslog.git", "4a6c6f2c996483e86c1320e9553f91d337bcb6aa", [tag: "1.0.5"]},
   "telemetry": {:hex, :telemetry, "0.4.0", "8339bee3fa8b91cb84d14c2935f8ecf399ccd87301ad6da6b71c09553834b2ab", [:rebar3], [], "hexpm"},
-  "tesla": {:hex, :tesla, "1.2.1", "864783cc27f71dd8c8969163704752476cec0f3a51eb3b06393b3971dc9733ff", [:mix], [{:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]}, {:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "~> 4.4.0", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}], "hexpm"},
+  "tesla": {:hex, :tesla, "1.3.0", "f35d72f029e608f9cdc6f6d6fcc7c66cf6d6512a70cfef9206b21b8bd0203a30", [:mix], [{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: true]}, {:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]}, {:gun, "~> 1.3", [hex: :gun, repo: "hexpm", optional: true]}, {:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "~> 4.4.0", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 0.4", [hex: :mint, repo: "hexpm", optional: true]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.3", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm"},
   "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"},
   "trailing_format_plug": {:hex, :trailing_format_plug, "0.0.7", "64b877f912cf7273bed03379936df39894149e35137ac9509117e59866e10e45", [:mix], [{:plug, "> 0.12.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
   "tzdata": {:hex, :tzdata, "0.5.21", "8cbf3607fcce69636c672d5be2bbb08687fe26639a62bdcc283d267277db7cf0", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"},
diff --git a/priv/repo/migrations/20190917100019_update_oban.exs b/priv/repo/migrations/20190917100019_update_oban.exs
new file mode 100644 (file)
index 0000000..157dc54
--- /dev/null
@@ -0,0 +1,11 @@
+defmodule Pleroma.Repo.Migrations.UpdateOban do
+  use Ecto.Migration
+
+  def up do
+    Oban.Migrations.up(version: 4)
+  end
+
+  def down do
+    Oban.Migrations.down(version: 2)
+  end
+end
diff --git a/test/fixtures/tesla_mock/poll_modified.json b/test/fixtures/tesla_mock/poll_modified.json
new file mode 100644 (file)
index 0000000..1d026b5
--- /dev/null
@@ -0,0 +1 @@
+{"@context":["https://www.w3.org/ns/activitystreams","https://patch.cx/schemas/litepub-0.1.jsonld",{"@language":"und"}],"actor":"https://patch.cx/users/rin","attachment":[],"attributedTo":"https://patch.cx/users/rin","cc":["https://patch.cx/users/rin/followers"],"closed":"2019-09-19T00:32:36.785333","content":"can you vote on this poll?","context":"https://patch.cx/contexts/626ecafd-3377-46c4-b908-3721a4d4373c","conversation":"https://patch.cx/contexts/626ecafd-3377-46c4-b908-3721a4d4373c","id":"https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d","oneOf":[{"name":"yes","replies":{"totalItems":8,"type":"Collection"},"type":"Note"},{"name":"no","replies":{"totalItems":3,"type":"Collection"},"type":"Note"}],"published":"2019-09-18T14:32:36.802152Z","sensitive":false,"summary":"","tag":[],"to":["https://www.w3.org/ns/activitystreams#Public"],"type":"Question"}
\ No newline at end of file
diff --git a/test/fixtures/tesla_mock/poll_original.json b/test/fixtures/tesla_mock/poll_original.json
new file mode 100644 (file)
index 0000000..267876b
--- /dev/null
@@ -0,0 +1 @@
+{"@context":["https://www.w3.org/ns/activitystreams","https://patch.cx/schemas/litepub-0.1.jsonld",{"@language":"und"}],"actor":"https://patch.cx/users/rin","attachment":[],"attributedTo":"https://patch.cx/users/rin","cc":["https://patch.cx/users/rin/followers"],"closed":"2019-09-19T00:32:36.785333","content":"can you vote on this poll?","context":"https://patch.cx/contexts/626ecafd-3377-46c4-b908-3721a4d4373c","conversation":"https://patch.cx/contexts/626ecafd-3377-46c4-b908-3721a4d4373c","id":"https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d","oneOf":[{"name":"yes","replies":{"totalItems":4,"type":"Collection"},"type":"Note"},{"name":"no","replies":{"totalItems":0,"type":"Collection"},"type":"Note"}],"published":"2019-09-18T14:32:36.802152Z","sensitive":false,"summary":"","tag":[],"to":["https://www.w3.org/ns/activitystreams#Public"],"type":"Question"}
\ No newline at end of file
diff --git a/test/fixtures/tesla_mock/rin.json b/test/fixtures/tesla_mock/rin.json
new file mode 100644 (file)
index 0000000..2cf6237
--- /dev/null
@@ -0,0 +1 @@
+{"@context":["https://www.w3.org/ns/activitystreams","https://patch.cx/schemas/litepub-0.1.jsonld",{"@language":"und"}],"attachment":[],"endpoints":{"oauthAuthorizationEndpoint":"https://patch.cx/oauth/authorize","oauthRegistrationEndpoint":"https://patch.cx/api/v1/apps","oauthTokenEndpoint":"https://patch.cx/oauth/token","sharedInbox":"https://patch.cx/inbox"},"followers":"https://patch.cx/users/rin/followers","following":"https://patch.cx/users/rin/following","icon":{"type":"Image","url":"https://patch.cx/media/4e914f5b84e4a259a3f6c2d2edc9ab642f2ab05f3e3d9c52c81fc2d984b3d51e.jpg"},"id":"https://patch.cx/users/rin","image":{"type":"Image","url":"https://patch.cx/media/f739efddefeee49c6e67e947c4811fdc911785c16ae43da4c3684051fbf8da6a.jpg?name=f739efddefeee49c6e67e947c4811fdc911785c16ae43da4c3684051fbf8da6a.jpg"},"inbox":"https://patch.cx/users/rin/inbox","manuallyApprovesFollowers":false,"name":"rinpatch","outbox":"https://patch.cx/users/rin/outbox","preferredUsername":"rin","publicKey":{"id":"https://patch.cx/users/rin#main-key","owner":"https://patch.cx/users/rin","publicKeyPem":"-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5DLtwGXNZElJyxFGfcVc\nXANhaMadj/iYYQwZjOJTV9QsbtiNBeIK54PJrYuU0/0YIdrvS1iqheX5IwXRhcwa\nhm3ZyLz7XeN9st7FBni4BmZMBtMpxAuYuu5p/jbWy13qAiYOhPreCx0wrWgm/lBD\n9mkgaxIxPooBE0S4ZWEJIDIV1Vft3AWcRUyWW1vIBK0uZzs6GYshbQZB952S0yo4\nFzI1hABGHncH8UvuFauh4EZ8tY7/X5I0pGRnDOcRN1dAht5w5yTA+6r5kebiFQjP\nIzN/eCO/a9Flrj9YGW7HDNtjSOH0A31PLRGlJtJO3yK57dnf5ppyCZGfL4emShQo\ncQIDAQAB\n-----END PUBLIC KEY-----\n\n"},"summary":"your friendly neighborhood pleroma developer<br>I like cute things and distributed systems, and really hate delete and redrafts","tag":[],"type":"Person","url":"https://patch.cx/users/rin"}
\ No newline at end of file
index c04262808fec233b5625b66b414c18de23ce1d14..d02a3cc4dcba85a0e34246862f44b2f988493af0 100644 (file)
@@ -18,6 +18,11 @@ defmodule Pleroma.Integration.MastodonWebsocketTest do
         |> Map.put(:path, "/api/v1/streaming")
         |> URI.to_string()
 
+  setup_all do
+    start_supervised(Pleroma.Web.Streamer.supervisor())
+    :ok
+  end
+
   def start_socket(qs \\ nil, headers \\ []) do
     path =
       case qs do
@@ -32,6 +37,7 @@ defmodule Pleroma.Integration.MastodonWebsocketTest do
     capture_log(fn ->
       assert {:error, {400, _}} = start_socket()
       assert {:error, {404, _}} = start_socket("?stream=ncjdk")
+      Process.sleep(30)
     end)
   end
 
@@ -39,17 +45,16 @@ defmodule Pleroma.Integration.MastodonWebsocketTest do
     capture_log(fn ->
       assert {:error, {403, _}} = start_socket("?stream=user&access_token=aaaaaaaaaaaa")
       assert {:error, {403, _}} = start_socket("?stream=user")
+      Process.sleep(30)
     end)
   end
 
-  @tag needs_streamer: true
   test "allows public streams without authentication" do
     assert {:ok, _} = start_socket("?stream=public")
     assert {:ok, _} = start_socket("?stream=public:local")
     assert {:ok, _} = start_socket("?stream=hashtag&tag=lain")
   end
 
-  @tag needs_streamer: true
   test "receives well formatted events" do
     user = insert(:user)
     {:ok, _} = start_socket("?stream=public")
@@ -94,31 +99,32 @@ defmodule Pleroma.Integration.MastodonWebsocketTest do
       assert {:ok, _} = start_socket("?stream=user&access_token=#{state.token.token}")
     end
 
-    @tag needs_streamer: true
     test "accepts the 'user' stream", %{token: token} = _state do
       assert {:ok, _} = start_socket("?stream=user&access_token=#{token.token}")
 
       assert capture_log(fn ->
                assert {:error, {403, "Forbidden"}} = start_socket("?stream=user")
+               Process.sleep(30)
              end) =~ ":badarg"
     end
 
-    @tag needs_streamer: true
     test "accepts the 'user:notification' stream", %{token: token} = _state do
       assert {:ok, _} = start_socket("?stream=user:notification&access_token=#{token.token}")
 
       assert capture_log(fn ->
                assert {:error, {403, "Forbidden"}} = start_socket("?stream=user:notification")
+               Process.sleep(30)
              end) =~ ":badarg"
     end
 
-    @tag needs_streamer: true
     test "accepts valid token on Sec-WebSocket-Protocol header", %{token: token} do
       assert {:ok, _} = start_socket("?stream=user", [{"Sec-WebSocket-Protocol", token.token}])
 
       assert capture_log(fn ->
                assert {:error, {403, "Forbidden"}} =
                         start_socket("?stream=user", [{"Sec-WebSocket-Protocol", "I am a friend"}])
+
+               Process.sleep(30)
              end) =~ ":badarg"
     end
   end
index ba96aeea4d67ba793e5181fc9b1844bdf7daaa8e..3d64fdb49d82d9e494db00524f5791c57c7e0cf5 100644 (file)
@@ -4,10 +4,13 @@
 
 defmodule Pleroma.ObjectTest do
   use Pleroma.DataCase
+  import ExUnit.CaptureLog
   import Pleroma.Factory
   import Tesla.Mock
+  alias Pleroma.Activity
   alias Pleroma.Object
   alias Pleroma.Repo
+  alias Pleroma.Web.CommonAPI
 
   setup do
     mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
@@ -89,4 +92,110 @@ defmodule Pleroma.ObjectTest do
              )
     end
   end
+
+  describe "get_by_id_and_maybe_refetch" do
+    setup do
+      mock(fn
+        %{method: :get, url: "https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d"} ->
+          %Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/poll_original.json")}
+
+        env ->
+          apply(HttpRequestMock, :request, [env])
+      end)
+
+      mock_modified = fn resp ->
+        mock(fn
+          %{method: :get, url: "https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d"} ->
+            resp
+
+          env ->
+            apply(HttpRequestMock, :request, [env])
+        end)
+      end
+
+      on_exit(fn -> mock(fn env -> apply(HttpRequestMock, :request, [env]) end) end)
+
+      [mock_modified: mock_modified]
+    end
+
+    test "refetches if the time since the last refetch is greater than the interval", %{
+      mock_modified: mock_modified
+    } do
+      %Object{} =
+        object = Object.normalize("https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d")
+
+      assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4
+      assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0
+
+      mock_modified.(%Tesla.Env{
+        status: 200,
+        body: File.read!("test/fixtures/tesla_mock/poll_modified.json")
+      })
+
+      updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: -1)
+      assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 8
+      assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 3
+    end
+
+    test "returns the old object if refetch fails", %{mock_modified: mock_modified} do
+      %Object{} =
+        object = Object.normalize("https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d")
+
+      assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4
+      assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0
+
+      assert capture_log(fn ->
+               mock_modified.(%Tesla.Env{status: 404, body: ""})
+
+               updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: -1)
+               assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 4
+               assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 0
+             end) =~
+               "[error] Couldn't refresh https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d"
+    end
+
+    test "does not refetch if the time since the last refetch is greater than the interval", %{
+      mock_modified: mock_modified
+    } do
+      %Object{} =
+        object = Object.normalize("https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d")
+
+      assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4
+      assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0
+
+      mock_modified.(%Tesla.Env{
+        status: 200,
+        body: File.read!("test/fixtures/tesla_mock/poll_modified.json")
+      })
+
+      updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: 100)
+      assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 4
+      assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 0
+    end
+
+    test "preserves internal fields on refetch", %{mock_modified: mock_modified} do
+      %Object{} =
+        object = Object.normalize("https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d")
+
+      assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4
+      assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0
+
+      user = insert(:user)
+      activity = Activity.get_create_by_object_ap_id(object.data["id"])
+      {:ok, _activity, object} = CommonAPI.favorite(activity.id, user)
+
+      assert object.data["like_count"] == 1
+
+      mock_modified.(%Tesla.Env{
+        status: 200,
+        body: File.read!("test/fixtures/tesla_mock/poll_modified.json")
+      })
+
+      updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: -1)
+      assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 8
+      assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 3
+
+      assert updated_object.data["like_count"] == 1
+    end
+  end
 end
index 231e7c49839d3b372c543dc47da18c4b8f9ad62c..833162a61cfb494de0cd8252aca4f82555d0fc40 100644 (file)
@@ -1004,6 +1004,10 @@ defmodule HttpRequestMock do
     {:ok, %Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/sjw.json")}}
   end
 
+  def get("https://patch.cx/users/rin", _, _, _) do
+    {:ok, %Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/rin.json")}}
+  end
+
   def get(url, query, body, headers) do
     {:error,
      "Mock response not implemented for GET #{inspect(url)}, #{query}, #{inspect(body)}, #{
index a927b2c3d8021267aedcc2057008e73d0df2116a..6a389365f58693f9808aed80a2eb7ca6ff0dcb11 100644 (file)
@@ -7,3 +7,8 @@ ExUnit.start(exclude: os_exclude)
 Ecto.Adapters.SQL.Sandbox.mode(Pleroma.Repo, :manual)
 Mox.defmock(Pleroma.ReverseProxy.ClientMock, for: Pleroma.ReverseProxy.Client)
 {:ok, _} = Application.ensure_all_started(:ex_machina)
+
+ExUnit.after_suite(fn _results ->
+  uploads = Pleroma.Config.get([Pleroma.Uploaders.Local, :uploads], "test/uploads")
+  File.rm_rf!(uploads)
+end)
index eb429b2c48530d9eb33a7be002e6646844e4ac0a..b1c1d6f716a6ef4c9ec073b3a0f75c1d7c9ad1db 100644 (file)
@@ -87,6 +87,18 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
 
       assert Utils.determine_explicit_mentions(object) == []
     end
+
+    test "works with an object has tags as map" do
+      object = %{
+        "tag" => %{
+          "type" => "Mention",
+          "href" => "https://example.com/~alyssa",
+          "name" => "Alyssa P. Hacker"
+        }
+      }
+
+      assert Utils.determine_explicit_mentions(object) == ["https://example.com/~alyssa"]
+    end
   end
 
   describe "make_unlike_data/3" do
@@ -300,8 +312,8 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
       {:ok, follow_activity_two} =
         Utils.update_follow_state_for_all(follow_activity_two, "accept")
 
-      assert Repo.get(Activity, follow_activity.id).data["state"] == "accept"
-      assert Repo.get(Activity, follow_activity_two.id).data["state"] == "accept"
+      assert refresh_record(follow_activity).data["state"] == "accept"
+      assert refresh_record(follow_activity_two).data["state"] == "accept"
     end
   end
 
@@ -323,8 +335,8 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
 
       {:ok, follow_activity_two} = Utils.update_follow_state(follow_activity_two, "reject")
 
-      assert Repo.get(Activity, follow_activity.id).data["state"] == "pending"
-      assert Repo.get(Activity, follow_activity_two.id).data["state"] == "reject"
+      assert refresh_record(follow_activity).data["state"] == "pending"
+      assert refresh_record(follow_activity_two).data["state"] == "reject"
     end
   end
 
@@ -401,4 +413,216 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
       assert ^like_activity = Utils.get_existing_like(user.ap_id, object)
     end
   end
+
+  describe "get_get_existing_announce/2" do
+    test "returns nil if announce not found" do
+      actor = insert(:user)
+      refute Utils.get_existing_announce(actor.ap_id, %{data: %{"id" => "test"}})
+    end
+
+    test "fetches existing announce" do
+      note_activity = insert(:note_activity)
+      assert object = Object.normalize(note_activity)
+      actor = insert(:user)
+
+      {:ok, announce, _object} = ActivityPub.announce(actor, object)
+      assert Utils.get_existing_announce(actor.ap_id, object) == announce
+    end
+  end
+
+  describe "fetch_latest_block/2" do
+    test "fetches last block activities" do
+      user1 = insert(:user)
+      user2 = insert(:user)
+
+      assert {:ok, %Activity{} = _} = ActivityPub.block(user1, user2)
+      assert {:ok, %Activity{} = _} = ActivityPub.block(user1, user2)
+      assert {:ok, %Activity{} = activity} = ActivityPub.block(user1, user2)
+
+      assert Utils.fetch_latest_block(user1, user2) == activity
+    end
+  end
+
+  describe "recipient_in_message/3" do
+    test "returns true when recipient in `to`" do
+      recipient = insert(:user)
+      actor = insert(:user)
+      assert Utils.recipient_in_message(recipient, actor, %{"to" => recipient.ap_id})
+
+      assert Utils.recipient_in_message(
+               recipient,
+               actor,
+               %{"to" => [recipient.ap_id], "cc" => ""}
+             )
+    end
+
+    test "returns true when recipient in `cc`" do
+      recipient = insert(:user)
+      actor = insert(:user)
+      assert Utils.recipient_in_message(recipient, actor, %{"cc" => recipient.ap_id})
+
+      assert Utils.recipient_in_message(
+               recipient,
+               actor,
+               %{"cc" => [recipient.ap_id], "to" => ""}
+             )
+    end
+
+    test "returns true when recipient in `bto`" do
+      recipient = insert(:user)
+      actor = insert(:user)
+      assert Utils.recipient_in_message(recipient, actor, %{"bto" => recipient.ap_id})
+
+      assert Utils.recipient_in_message(
+               recipient,
+               actor,
+               %{"bcc" => "", "bto" => [recipient.ap_id]}
+             )
+    end
+
+    test "returns true when recipient in `bcc`" do
+      recipient = insert(:user)
+      actor = insert(:user)
+      assert Utils.recipient_in_message(recipient, actor, %{"bcc" => recipient.ap_id})
+
+      assert Utils.recipient_in_message(
+               recipient,
+               actor,
+               %{"bto" => "", "bcc" => [recipient.ap_id]}
+             )
+    end
+
+    test "returns true when message without addresses fields" do
+      recipient = insert(:user)
+      actor = insert(:user)
+      assert Utils.recipient_in_message(recipient, actor, %{"bccc" => recipient.ap_id})
+
+      assert Utils.recipient_in_message(
+               recipient,
+               actor,
+               %{"btod" => "", "bccc" => [recipient.ap_id]}
+             )
+    end
+
+    test "returns false" do
+      recipient = insert(:user)
+      actor = insert(:user)
+      refute Utils.recipient_in_message(recipient, actor, %{"to" => "ap_id"})
+    end
+  end
+
+  describe "lazy_put_activity_defaults/2" do
+    test "returns map with id and published data" do
+      note_activity = insert(:note_activity)
+      object = Object.normalize(note_activity)
+      res = Utils.lazy_put_activity_defaults(%{"context" => object.data["id"]})
+      assert res["context"] == object.data["id"]
+      assert res["context_id"] == object.id
+      assert res["id"]
+      assert res["published"]
+    end
+
+    test "returns map with fake id and published data" do
+      assert %{
+               "context" => "pleroma:fakecontext",
+               "context_id" => -1,
+               "id" => "pleroma:fakeid",
+               "published" => _
+             } = Utils.lazy_put_activity_defaults(%{}, true)
+    end
+
+    test "returns activity data with object" do
+      note_activity = insert(:note_activity)
+      object = Object.normalize(note_activity)
+
+      res =
+        Utils.lazy_put_activity_defaults(%{
+          "context" => object.data["id"],
+          "object" => %{}
+        })
+
+      assert res["context"] == object.data["id"]
+      assert res["context_id"] == object.id
+      assert res["id"]
+      assert res["published"]
+      assert res["object"]["id"]
+      assert res["object"]["published"]
+      assert res["object"]["context"] == object.data["id"]
+      assert res["object"]["context_id"] == object.id
+    end
+  end
+
+  describe "make_flag_data" do
+    test "returns empty map when params is invalid" do
+      assert Utils.make_flag_data(%{}, %{}) == %{}
+    end
+
+    test "returns map with Flag object" do
+      reporter = insert(:user)
+      target_account = insert(:user)
+      {:ok, activity} = CommonAPI.post(target_account, %{"status" => "foobar"})
+      context = Utils.generate_context_id()
+      content = "foobar"
+
+      target_ap_id = target_account.ap_id
+      activity_ap_id = activity.data["id"]
+
+      res =
+        Utils.make_flag_data(
+          %{
+            actor: reporter,
+            context: context,
+            account: target_account,
+            statuses: [%{"id" => activity.data["id"]}],
+            content: content
+          },
+          %{}
+        )
+
+      assert %{
+               "type" => "Flag",
+               "content" => ^content,
+               "context" => ^context,
+               "object" => [^target_ap_id, ^activity_ap_id],
+               "state" => "open"
+             } = res
+    end
+  end
+
+  describe "add_announce_to_object/2" do
+    test "adds actor to announcement" do
+      user = insert(:user)
+      object = insert(:note)
+
+      activity =
+        insert(:note_activity,
+          data: %{
+            "actor" => user.ap_id,
+            "cc" => [Pleroma.Constants.as_public()]
+          }
+        )
+
+      assert {:ok, updated_object} = Utils.add_announce_to_object(activity, object)
+      assert updated_object.data["announcements"] == [user.ap_id]
+      assert updated_object.data["announcement_count"] == 1
+    end
+  end
+
+  describe "remove_announce_from_object/2" do
+    test "removes actor from announcements" do
+      user = insert(:user)
+      user2 = insert(:user)
+
+      object =
+        insert(:note,
+          data: %{"announcements" => [user.ap_id, user2.ap_id], "announcement_count" => 2}
+        )
+
+      activity = insert(:note_activity, data: %{"actor" => user.ap_id})
+
+      assert {:ok, updated_object} = Utils.remove_announce_from_object(activity, object)
+      assert updated_object.data["announcements"] == [user2.ap_id]
+      assert updated_object.data["announcement_count"] == 1
+    end
+  end
 end
index 516de5d0cfc5535c54c9d6fe36a577eb78610c13..5f36d42e4e22c88f9648dd485a0d92f0dc464e7d 100644 (file)
@@ -574,18 +574,6 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
     end
   end
 
-  test "/api/pleroma/admin/users/invite_token" do
-    admin = insert(:user, info: %{is_admin: true})
-
-    conn =
-      build_conn()
-      |> assign(:user, admin)
-      |> put_req_header("accept", "application/json")
-      |> get("/api/pleroma/admin/users/invite_token")
-
-    assert conn.status == 200
-  end
-
   test "/api/pleroma/admin/users/:nickname/password_reset" do
     admin = insert(:user, info: %{is_admin: true})
     user = insert(:user)
@@ -1064,7 +1052,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
              "@#{admin.nickname} deactivated user @#{user.nickname}"
   end
 
-  describe "GET /api/pleroma/admin/users/invite_token" do
+  describe "POST /api/pleroma/admin/users/invite_token" do
     setup do
       admin = insert(:user, info: %{is_admin: true})
 
@@ -1076,10 +1064,10 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
     end
 
     test "without options", %{conn: conn} do
-      conn = get(conn, "/api/pleroma/admin/users/invite_token")
+      conn = post(conn, "/api/pleroma/admin/users/invite_token")
 
-      token = json_response(conn, 200)
-      invite = UserInviteToken.find_by_token!(token)
+      invite_json = json_response(conn, 200)
+      invite = UserInviteToken.find_by_token!(invite_json["token"])
       refute invite.used
       refute invite.expires_at
       refute invite.max_use
@@ -1088,12 +1076,12 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
 
     test "with expires_at", %{conn: conn} do
       conn =
-        get(conn, "/api/pleroma/admin/users/invite_token", %{
-          "invite" => %{"expires_at" => Date.to_string(Date.utc_today())}
+        post(conn, "/api/pleroma/admin/users/invite_token", %{
+          "expires_at" => Date.to_string(Date.utc_today())
         })
 
-      token = json_response(conn, 200)
-      invite = UserInviteToken.find_by_token!(token)
+      invite_json = json_response(conn, 200)
+      invite = UserInviteToken.find_by_token!(invite_json["token"])
 
       refute invite.used
       assert invite.expires_at == Date.utc_today()
@@ -1102,13 +1090,10 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
     end
 
     test "with max_use", %{conn: conn} do
-      conn =
-        get(conn, "/api/pleroma/admin/users/invite_token", %{
-          "invite" => %{"max_use" => 150}
-        })
+      conn = post(conn, "/api/pleroma/admin/users/invite_token", %{"max_use" => 150})
 
-      token = json_response(conn, 200)
-      invite = UserInviteToken.find_by_token!(token)
+      invite_json = json_response(conn, 200)
+      invite = UserInviteToken.find_by_token!(invite_json["token"])
       refute invite.used
       refute invite.expires_at
       assert invite.max_use == 150
@@ -1117,12 +1102,13 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
 
     test "with max use and expires_at", %{conn: conn} do
       conn =
-        get(conn, "/api/pleroma/admin/users/invite_token", %{
-          "invite" => %{"max_use" => 150, "expires_at" => Date.to_string(Date.utc_today())}
+        post(conn, "/api/pleroma/admin/users/invite_token", %{
+          "max_use" => 150,
+          "expires_at" => Date.to_string(Date.utc_today())
         })
 
-      token = json_response(conn, 200)
-      invite = UserInviteToken.find_by_token!(token)
+      invite_json = json_response(conn, 200)
+      invite = UserInviteToken.find_by_token!(invite_json["token"])
       refute invite.used
       assert invite.expires_at == Date.utc_today()
       assert invite.max_use == 150
@@ -1309,6 +1295,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
         |> json_response(:ok)
 
       assert Enum.empty?(response["reports"])
+      assert response["total"] == 0
     end
 
     test "returns reports", %{conn: conn} do
@@ -1331,6 +1318,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
 
       assert length(response["reports"]) == 1
       assert report["id"] == report_id
+
+      assert response["total"] == 1
     end
 
     test "returns reports with specified state", %{conn: conn} do
@@ -1364,6 +1353,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
       assert length(response["reports"]) == 1
       assert open_report["id"] == first_report_id
 
+      assert response["total"] == 1
+
       response =
         conn
         |> get("/api/pleroma/admin/reports", %{
@@ -1376,6 +1367,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
       assert length(response["reports"]) == 1
       assert closed_report["id"] == second_report_id
 
+      assert response["total"] == 1
+
       response =
         conn
         |> get("/api/pleroma/admin/reports", %{
@@ -1384,6 +1377,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
         |> json_response(:ok)
 
       assert Enum.empty?(response["reports"])
+      assert response["total"] == 0
     end
 
     test "returns 403 when requested by a non-admin" do
index 0a2a48fb703df856c7a9560bbb5a146284a2b53f..56e318182de75c222070474375ebcc547eab7c67 100644 (file)
@@ -775,4 +775,109 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do
       assert json_response(conn, 200) == %{"status" => "success"}
     end
   end
+
+  describe "POST /api/pleroma/change_password" do
+    setup [:valid_user]
+
+    test "without credentials", %{conn: conn} do
+      conn = post(conn, "/api/pleroma/change_password")
+      assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
+    end
+
+    test "with credentials and invalid password", %{conn: conn, user: current_user} do
+      conn =
+        conn
+        |> with_credentials(current_user.nickname, "test")
+        |> post("/api/pleroma/change_password", %{
+          "password" => "hi",
+          "new_password" => "newpass",
+          "new_password_confirmation" => "newpass"
+        })
+
+      assert json_response(conn, 200) == %{"error" => "Invalid password."}
+    end
+
+    test "with credentials, valid password and new password and confirmation not matching", %{
+      conn: conn,
+      user: current_user
+    } do
+      conn =
+        conn
+        |> with_credentials(current_user.nickname, "test")
+        |> post("/api/pleroma/change_password", %{
+          "password" => "test",
+          "new_password" => "newpass",
+          "new_password_confirmation" => "notnewpass"
+        })
+
+      assert json_response(conn, 200) == %{
+               "error" => "New password does not match confirmation."
+             }
+    end
+
+    test "with credentials, valid password and invalid new password", %{
+      conn: conn,
+      user: current_user
+    } do
+      conn =
+        conn
+        |> with_credentials(current_user.nickname, "test")
+        |> post("/api/pleroma/change_password", %{
+          "password" => "test",
+          "new_password" => "",
+          "new_password_confirmation" => ""
+        })
+
+      assert json_response(conn, 200) == %{
+               "error" => "New password can't be blank."
+             }
+    end
+
+    test "with credentials, valid password and matching new password and confirmation", %{
+      conn: conn,
+      user: current_user
+    } do
+      conn =
+        conn
+        |> with_credentials(current_user.nickname, "test")
+        |> post("/api/pleroma/change_password", %{
+          "password" => "test",
+          "new_password" => "newpass",
+          "new_password_confirmation" => "newpass"
+        })
+
+      assert json_response(conn, 200) == %{"status" => "success"}
+      fetched_user = User.get_cached_by_id(current_user.id)
+      assert Comeonin.Pbkdf2.checkpw("newpass", fetched_user.password_hash) == true
+    end
+  end
+
+  describe "POST /api/pleroma/delete_account" do
+    setup [:valid_user]
+
+    test "without credentials", %{conn: conn} do
+      conn = post(conn, "/api/pleroma/delete_account")
+      assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
+    end
+
+    test "with credentials and invalid password", %{conn: conn, user: current_user} do
+      conn =
+        conn
+        |> with_credentials(current_user.nickname, "test")
+        |> post("/api/pleroma/delete_account", %{"password" => "hi"})
+
+      assert json_response(conn, 200) == %{"error" => "Invalid password."}
+    end
+
+    test "with credentials and valid password", %{conn: conn, user: current_user} do
+      conn =
+        conn
+        |> with_credentials(current_user.nickname, "test")
+        |> post("/api/pleroma/delete_account", %{"password" => "test"})
+
+      assert json_response(conn, 200) == %{"status" => "success"}
+      # Wait a second for the started task to end
+      :timer.sleep(1000)
+    end
+  end
 end