summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlain <lain@soykaf.club>2020-08-28 12:17:19 +0000
committerlain <lain@soykaf.club>2020-08-28 12:17:19 +0000
commit73dd5bdb7dcdf804bdbabcf632671d4de5042ebc (patch)
treeefcb0b8e68f86d067de98a23f40a24c7dab79d2f
parentf891e2b2f1d1daa122b9856e4b660be394d31e34 (diff)
parentb141e35d641e733dffe7bd6a45a5bbcafe586c56 (diff)
Merge branch 'release/2.1.0' into 'stable'v2.1.0
Release/2.1.0 See merge request pleroma/pleroma!2927
-rw-r--r--.gitignore1
-rw-r--r--.gitlab-ci.yml65
-rw-r--r--.gitlab/issue_templates/Bug.md18
-rw-r--r--.gitlab/merge_request_templates/Release.md6
-rw-r--r--CHANGELOG.md123
-rw-r--r--COPYING4
-rw-r--r--Dockerfile6
-rw-r--r--README.md10
-rw-r--r--SECURITY.md16
-rw-r--r--benchmarks/load_testing/activities.ex595
-rw-r--r--benchmarks/load_testing/fetcher.ex795
-rw-r--r--benchmarks/load_testing/generator.ex409
-rw-r--r--benchmarks/load_testing/helper.ex17
-rw-r--r--benchmarks/load_testing/users.ex189
-rw-r--r--benchmarks/mix/tasks/pleroma/benchmarks/tags.ex50
-rw-r--r--benchmarks/mix/tasks/pleroma/benchmarks/timelines.ex70
-rw-r--r--benchmarks/mix/tasks/pleroma/load_testing.ex137
-rw-r--r--config/benchmark.exs4
-rw-r--r--config/config.exs273
-rw-r--r--config/description.exs1253
-rw-r--r--config/dev.exs2
-rw-r--r--config/test.exs37
-rw-r--r--coveralls.json6
-rw-r--r--docs/API/admin_api.md341
-rw-r--r--docs/API/chats.md248
-rw-r--r--docs/API/differences_in_mastoapi_responses.md144
-rw-r--r--docs/API/pleroma_api.md207
-rw-r--r--docs/administration/CLI_tasks/config.md29
-rw-r--r--docs/administration/CLI_tasks/database.md132
-rw-r--r--docs/administration/CLI_tasks/digest.md32
-rw-r--r--docs/administration/CLI_tasks/email.md32
-rw-r--r--docs/administration/CLI_tasks/emoji.md55
-rw-r--r--docs/administration/CLI_tasks/frontend.md69
-rw-r--r--docs/administration/CLI_tasks/instance.md16
-rw-r--r--docs/administration/CLI_tasks/oauth_app.md20
-rw-r--r--docs/administration/CLI_tasks/relay.md48
-rw-r--r--docs/administration/CLI_tasks/robots_txt.md21
-rw-r--r--docs/administration/CLI_tasks/uploads.md16
-rw-r--r--docs/administration/CLI_tasks/user.md291
-rw-r--r--docs/administration/backup.md5
-rw-r--r--docs/administration/updating.md2
-rw-r--r--docs/ap_extensions.md35
-rw-r--r--docs/clients.md52
-rw-r--r--docs/configuration/cheatsheet.md364
-rw-r--r--docs/configuration/howto_database_config.md153
-rw-r--r--docs/configuration/howto_theming_your_instance.md2
-rw-r--r--docs/configuration/mrf.md26
-rw-r--r--docs/configuration/postgresql.md31
-rw-r--r--docs/configuration/static_dir.md65
-rw-r--r--docs/configuration/storing_remote_media.md38
-rw-r--r--docs/dev.md23
-rw-r--r--docs/index.md26
-rw-r--r--docs/installation/alpine_linux_en.md8
-rw-r--r--docs/installation/arch_linux_en.md8
-rw-r--r--docs/installation/debian_based_en.md22
-rw-r--r--docs/installation/debian_based_jp.md34
-rw-r--r--docs/installation/freebsd_en.md210
-rw-r--r--docs/installation/further_reading.include5
-rw-r--r--docs/installation/gentoo_en.md8
-rw-r--r--docs/installation/migrating_from_source_otp_en.md48
-rw-r--r--docs/installation/netbsd_en.md9
-rw-r--r--docs/installation/openbsd_en.md11
-rw-r--r--docs/installation/openbsd_fi.md2
-rw-r--r--docs/installation/otp_en.md191
-rw-r--r--docs/introduction.md65
-rw-r--r--elixir_buildpack.config4
-rwxr-xr-xinstallation/freebsd/rc.d/pleroma27
-rwxr-xr-xinstallation/init.d/pleroma48
-rwxr-xr-xinstallation/nginx-cache-purge.sh.example40
-rw-r--r--installation/pleroma.nginx11
-rw-r--r--lib/mix/pleroma.ex47
-rw-r--r--lib/mix/tasks/pleroma/app.ex49
-rw-r--r--lib/mix/tasks/pleroma/benchmark.ex39
-rw-r--r--lib/mix/tasks/pleroma/config.ex19
-rw-r--r--lib/mix/tasks/pleroma/database.ex57
-rw-r--r--lib/mix/tasks/pleroma/digest.ex7
-rw-r--r--lib/mix/tasks/pleroma/ecto/migrate.ex4
-rw-r--r--lib/mix/tasks/pleroma/ecto/rollback.ex4
-rw-r--r--lib/mix/tasks/pleroma/emoji.ex129
-rw-r--r--lib/mix/tasks/pleroma/frontend.ex140
-rw-r--r--lib/mix/tasks/pleroma/instance.ex12
-rw-r--r--lib/mix/tasks/pleroma/notification_settings.ex18
-rw-r--r--lib/mix/tasks/pleroma/refresh_counter_cache.ex49
-rw-r--r--lib/mix/tasks/pleroma/relay.ex10
-rw-r--r--lib/mix/tasks/pleroma/user.ex43
-rw-r--r--lib/pleroma/activity.ex46
-rw-r--r--lib/pleroma/activity/queries.ex7
-rw-r--r--lib/pleroma/activity_expiration.ex17
-rw-r--r--lib/pleroma/application.ex143
-rw-r--r--lib/pleroma/application_requirements.ex143
-rw-r--r--lib/pleroma/bbs/authenticator.ex4
-rw-r--r--lib/pleroma/bbs/handler.ex12
-rw-r--r--lib/pleroma/captcha/captcha.ex135
-rw-r--r--lib/pleroma/captcha/kocaptcha.ex8
-rw-r--r--lib/pleroma/captcha/native.ex8
-rw-r--r--lib/pleroma/chat.ex72
-rw-r--r--lib/pleroma/chat/message_reference.ex117
-rw-r--r--lib/pleroma/config.ex51
-rw-r--r--lib/pleroma/config/config_db.ex284
-rw-r--r--lib/pleroma/config/deprecation_warnings.ex75
-rw-r--r--lib/pleroma/config/helpers.ex17
-rw-r--r--lib/pleroma/config/loader.ex8
-rw-r--r--lib/pleroma/config/transfer_task.ex168
-rw-r--r--lib/pleroma/constants.ex5
-rw-r--r--lib/pleroma/conversation.ex2
-rw-r--r--lib/pleroma/conversation/participation.ex26
-rw-r--r--lib/pleroma/counter_cache.ex66
-rw-r--r--lib/pleroma/docs/generator.ex31
-rw-r--r--lib/pleroma/docs/json.ex22
-rw-r--r--lib/pleroma/docs/markdown.ex5
-rw-r--r--lib/pleroma/ecto_type/activity_pub/object_validators/date_time.ex38
-rw-r--r--lib/pleroma/ecto_type/activity_pub/object_validators/object_id.ex27
-rw-r--r--lib/pleroma/ecto_type/activity_pub/object_validators/recipients.ex40
-rw-r--r--lib/pleroma/ecto_type/activity_pub/object_validators/safe_text.ex25
-rw-r--r--lib/pleroma/ecto_type/activity_pub/object_validators/uri.ex24
-rw-r--r--lib/pleroma/ecto_type/config/atom.ex26
-rw-r--r--lib/pleroma/ecto_type/config/binary_value.ex27
-rw-r--r--lib/pleroma/emails/admin_email.ex19
-rw-r--r--lib/pleroma/emails/new_users_digest_email.ex6
-rw-r--r--lib/pleroma/emails/user_email.ex48
-rw-r--r--lib/pleroma/emoji/formatter.ex14
-rw-r--r--lib/pleroma/emoji/loader.ex2
-rw-r--r--lib/pleroma/emoji/pack.ex572
-rw-r--r--lib/pleroma/filter.ex51
-rw-r--r--lib/pleroma/following_relationship.ex86
-rw-r--r--lib/pleroma/formatter.ex57
-rw-r--r--lib/pleroma/gopher/server.ex19
-rw-r--r--lib/pleroma/gun/api.ex46
-rw-r--r--lib/pleroma/gun/conn.ex135
-rw-r--r--lib/pleroma/gun/connection_pool.ex82
-rw-r--r--lib/pleroma/gun/connection_pool/reclaimer.ex85
-rw-r--r--lib/pleroma/gun/connection_pool/worker.ex133
-rw-r--r--lib/pleroma/gun/connection_pool/worker_supervisor.ex45
-rw-r--r--lib/pleroma/gun/gun.ex31
-rw-r--r--lib/pleroma/helpers/uri_helper.ex9
-rw-r--r--lib/pleroma/html.ex2
-rw-r--r--lib/pleroma/http/adapter_helper.ex140
-rw-r--r--lib/pleroma/http/adapter_helper/default.ex14
-rw-r--r--lib/pleroma/http/adapter_helper/gun.ex78
-rw-r--r--lib/pleroma/http/adapter_helper/hackney.ex29
-rw-r--r--lib/pleroma/http/connection.ex43
-rw-r--r--lib/pleroma/http/ex_aws.ex22
-rw-r--r--lib/pleroma/http/http.ex135
-rw-r--r--lib/pleroma/http/request.ex23
-rw-r--r--lib/pleroma/http/request_builder.ex125
-rw-r--r--lib/pleroma/http/tzdata.ex25
-rw-r--r--lib/pleroma/instances/instance.ex48
-rw-r--r--lib/pleroma/job_queue_monitor.ex14
-rw-r--r--lib/pleroma/maintenance.ex37
-rw-r--r--lib/pleroma/maps.ex15
-rw-r--r--lib/pleroma/marker.ex45
-rw-r--r--lib/pleroma/mfa.ex155
-rw-r--r--lib/pleroma/mfa/backup_codes.ex31
-rw-r--r--lib/pleroma/mfa/changeset.ex64
-rw-r--r--lib/pleroma/mfa/settings.ex24
-rw-r--r--lib/pleroma/mfa/token.ex106
-rw-r--r--lib/pleroma/mfa/totp.ex86
-rw-r--r--lib/pleroma/migration_helper/notification_backfill.ex93
-rw-r--r--lib/pleroma/moderation_log.ex11
-rw-r--r--lib/pleroma/notification.ex348
-rw-r--r--lib/pleroma/object.ex69
-rw-r--r--lib/pleroma/object/containment.ex14
-rw-r--r--lib/pleroma/object/fetcher.ex57
-rw-r--r--lib/pleroma/otp_version.ex28
-rw-r--r--lib/pleroma/pagination.ex20
-rw-r--r--lib/pleroma/plugs/admin_secret_authentication_plug.ex27
-rw-r--r--lib/pleroma/plugs/auth_expected_plug.ex17
-rw-r--r--lib/pleroma/plugs/authentication_plug.ex33
-rw-r--r--lib/pleroma/plugs/ensure_authenticated_plug.ex24
-rw-r--r--lib/pleroma/plugs/ensure_public_or_authenticated_plug.ex6
-rw-r--r--lib/pleroma/plugs/expect_authenticated_check_plug.ex20
-rw-r--r--lib/pleroma/plugs/expect_public_or_authenticated_check_plug.ex21
-rw-r--r--lib/pleroma/plugs/federating_plug.ex21
-rw-r--r--lib/pleroma/plugs/frontend_static.ex55
-rw-r--r--lib/pleroma/plugs/http_security_plug.ex77
-rw-r--r--lib/pleroma/plugs/instance_static.ex15
-rw-r--r--lib/pleroma/plugs/mapped_signature_to_identity_plug.ex6
-rw-r--r--lib/pleroma/plugs/oauth_scopes_plug.ex27
-rw-r--r--lib/pleroma/plugs/rate_limiter/rate_limiter.ex17
-rw-r--r--lib/pleroma/plugs/static_fe_plug.ex9
-rw-r--r--lib/pleroma/plugs/uploaded_media.ex16
-rw-r--r--lib/pleroma/plugs/user_is_admin_plug.ex25
-rw-r--r--lib/pleroma/repo.ex59
-rw-r--r--lib/pleroma/reverse_proxy/client.ex26
-rw-r--r--lib/pleroma/reverse_proxy/client/hackney.ex24
-rw-r--r--lib/pleroma/reverse_proxy/client/tesla.ex86
-rw-r--r--lib/pleroma/reverse_proxy/reverse_proxy.ex79
-rw-r--r--lib/pleroma/scheduled_activity.ex2
-rw-r--r--lib/pleroma/signature.ex13
-rw-r--r--lib/pleroma/stats.ex23
-rw-r--r--lib/pleroma/telemetry/logger.ex76
-rw-r--r--lib/pleroma/tesla/middleware/follow_redirects.ex110
-rw-r--r--lib/pleroma/tests/auth_test_controller.ex93
-rw-r--r--lib/pleroma/tests/oauth_test_controller.ex31
-rw-r--r--lib/pleroma/thread_mute.ex8
-rw-r--r--lib/pleroma/upload.ex21
-rw-r--r--lib/pleroma/upload/filter/exiftool.ex26
-rw-r--r--lib/pleroma/upload/filter/mogrifun.ex15
-rw-r--r--lib/pleroma/upload/filter/mogrify.ex12
-rw-r--r--lib/pleroma/user.ex820
-rw-r--r--lib/pleroma/user/notification_setting.ex14
-rw-r--r--lib/pleroma/user/query.ex21
-rw-r--r--lib/pleroma/user/search.ex23
-rw-r--r--lib/pleroma/user/welcome_chat_message.ex45
-rw-r--r--lib/pleroma/user/welcome_email.ex62
-rw-r--r--lib/pleroma/user/welcome_message.ex43
-rw-r--r--lib/pleroma/user_relationship.ex51
-rw-r--r--lib/pleroma/utils.ex15
-rw-r--r--lib/pleroma/web/activity_pub/activity_pub.ex1026
-rw-r--r--lib/pleroma/web/activity_pub/activity_pub_controller.ex117
-rw-r--r--lib/pleroma/web/activity_pub/builder.ex269
-rw-r--r--lib/pleroma/web/activity_pub/mrf.ex11
-rw-r--r--lib/pleroma/web/activity_pub/mrf/activity_expiration_policy.ex43
-rw-r--r--lib/pleroma/web/activity_pub/mrf/anti_followbot_policy.ex4
-rw-r--r--lib/pleroma/web/activity_pub/mrf/anti_link_spam_policy.ex12
-rw-r--r--lib/pleroma/web/activity_pub/mrf/ensure_re_prepended.ex3
-rw-r--r--lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex11
-rw-r--r--lib/pleroma/web/activity_pub/mrf/keyword_policy.ex7
-rw-r--r--lib/pleroma/web/activity_pub/mrf/media_proxy_warming_policy.ex14
-rw-r--r--lib/pleroma/web/activity_pub/mrf/mention_policy.ex5
-rw-r--r--lib/pleroma/web/activity_pub/mrf/no_placeholder_text_policy.ex2
-rw-r--r--lib/pleroma/web/activity_pub/mrf/object_age_policy.ex23
-rw-r--r--lib/pleroma/web/activity_pub/mrf/reject_non_public.ex4
-rw-r--r--lib/pleroma/web/activity_pub/mrf/simple_policy.ex88
-rw-r--r--lib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex97
-rw-r--r--lib/pleroma/web/activity_pub/mrf/tag_policy.ex7
-rw-r--r--lib/pleroma/web/activity_pub/mrf/user_allow_list_policy.ex2
-rw-r--r--lib/pleroma/web/activity_pub/mrf/vocabulary_policy.ex18
-rw-r--r--lib/pleroma/web/activity_pub/object_validator.ex275
-rw-r--r--lib/pleroma/web/activity_pub/object_validators/accept_reject_validator.ex56
-rw-r--r--lib/pleroma/web/activity_pub/object_validators/announce_validator.ex101
-rw-r--r--lib/pleroma/web/activity_pub/object_validators/answer_validator.ex62
-rw-r--r--lib/pleroma/web/activity_pub/object_validators/attachment_validator.ex80
-rw-r--r--lib/pleroma/web/activity_pub/object_validators/audio_validator.ex106
-rw-r--r--lib/pleroma/web/activity_pub/object_validators/block_validator.ex42
-rw-r--r--lib/pleroma/web/activity_pub/object_validators/chat_message_validator.ex129
-rw-r--r--lib/pleroma/web/activity_pub/object_validators/common_fixes.ex22
-rw-r--r--lib/pleroma/web/activity_pub/object_validators/common_validations.ex141
-rw-r--r--lib/pleroma/web/activity_pub/object_validators/create_chat_message_validator.ex91
-rw-r--r--lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex144
-rw-r--r--lib/pleroma/web/activity_pub/object_validators/create_note_validator.ex29
-rw-r--r--lib/pleroma/web/activity_pub/object_validators/delete_validator.ex75
-rw-r--r--lib/pleroma/web/activity_pub/object_validators/emoji_react_validator.ex81
-rw-r--r--lib/pleroma/web/activity_pub/object_validators/event_validator.ex96
-rw-r--r--lib/pleroma/web/activity_pub/object_validators/follow_validator.ex44
-rw-r--r--lib/pleroma/web/activity_pub/object_validators/like_validator.ex99
-rw-r--r--lib/pleroma/web/activity_pub/object_validators/note_validator.ex66
-rw-r--r--lib/pleroma/web/activity_pub/object_validators/question_options_validator.ex37
-rw-r--r--lib/pleroma/web/activity_pub/object_validators/question_validator.ex111
-rw-r--r--lib/pleroma/web/activity_pub/object_validators/undo_validator.ex62
-rw-r--r--lib/pleroma/web/activity_pub/object_validators/update_validator.ex59
-rw-r--r--lib/pleroma/web/activity_pub/object_validators/url_object_validator.ex24
-rw-r--r--lib/pleroma/web/activity_pub/pipeline.ex71
-rw-r--r--lib/pleroma/web/activity_pub/publisher.ex33
-rw-r--r--lib/pleroma/web/activity_pub/relay.ex67
-rw-r--r--lib/pleroma/web/activity_pub/side_effects.ex441
-rw-r--r--lib/pleroma/web/activity_pub/transmogrifier.ex545
-rw-r--r--lib/pleroma/web/activity_pub/utils.ex193
-rw-r--r--lib/pleroma/web/activity_pub/views/user_view.ex19
-rw-r--r--lib/pleroma/web/activity_pub/visibility.ex15
-rw-r--r--lib/pleroma/web/admin_api/controllers/admin_api_controller.ex (renamed from lib/pleroma/web/admin_api/admin_api_controller.ex)611
-rw-r--r--lib/pleroma/web/admin_api/controllers/config_controller.ex150
-rw-r--r--lib/pleroma/web/admin_api/controllers/fallback_controller.ex37
-rw-r--r--lib/pleroma/web/admin_api/controllers/invite_controller.ex78
-rw-r--r--lib/pleroma/web/admin_api/controllers/media_proxy_cache_controller.ex74
-rw-r--r--lib/pleroma/web/admin_api/controllers/oauth_app_controller.ex77
-rw-r--r--lib/pleroma/web/admin_api/controllers/relay_controller.ex67
-rw-r--r--lib/pleroma/web/admin_api/controllers/report_controller.ex107
-rw-r--r--lib/pleroma/web/admin_api/controllers/status_controller.ex77
-rw-r--r--lib/pleroma/web/admin_api/search.ex2
-rw-r--r--lib/pleroma/web/admin_api/views/account_view.ex33
-rw-r--r--lib/pleroma/web/admin_api/views/config_view.ex19
-rw-r--r--lib/pleroma/web/admin_api/views/invite_view.ex25
-rw-r--r--lib/pleroma/web/admin_api/views/media_proxy_cache_view.ex15
-rw-r--r--lib/pleroma/web/admin_api/views/report_view.ex46
-rw-r--r--lib/pleroma/web/admin_api/views/status_view.ex29
-rw-r--r--lib/pleroma/web/api_spec.ex57
-rw-r--r--lib/pleroma/web/api_spec/cast_and_validate.ex139
-rw-r--r--lib/pleroma/web/api_spec/helpers.ex81
-rw-r--r--lib/pleroma/web/api_spec/operations/account_operation.ex766
-rw-r--r--lib/pleroma/web/api_spec/operations/admin/config_operation.ex145
-rw-r--r--lib/pleroma/web/api_spec/operations/admin/invite_operation.ex152
-rw-r--r--lib/pleroma/web/api_spec/operations/admin/media_proxy_cache_operation.ex121
-rw-r--r--lib/pleroma/web/api_spec/operations/admin/oauth_app_operation.ex217
-rw-r--r--lib/pleroma/web/api_spec/operations/admin/relay_operation.ex94
-rw-r--r--lib/pleroma/web/api_spec/operations/admin/report_operation.ex240
-rw-r--r--lib/pleroma/web/api_spec/operations/admin/status_operation.ex166
-rw-r--r--lib/pleroma/web/api_spec/operations/app_operation.ex148
-rw-r--r--lib/pleroma/web/api_spec/operations/chat_operation.ex355
-rw-r--r--lib/pleroma/web/api_spec/operations/conversation_operation.ex61
-rw-r--r--lib/pleroma/web/api_spec/operations/custom_emoji_operation.ex88
-rw-r--r--lib/pleroma/web/api_spec/operations/domain_block_operation.ex86
-rw-r--r--lib/pleroma/web/api_spec/operations/emoji_reaction_operation.ex104
-rw-r--r--lib/pleroma/web/api_spec/operations/filter_operation.ex230
-rw-r--r--lib/pleroma/web/api_spec/operations/follow_request_operation.ex65
-rw-r--r--lib/pleroma/web/api_spec/operations/instance_operation.ex175
-rw-r--r--lib/pleroma/web/api_spec/operations/list_operation.ex188
-rw-r--r--lib/pleroma/web/api_spec/operations/marker_operation.ex142
-rw-r--r--lib/pleroma/web/api_spec/operations/media_operation.ex132
-rw-r--r--lib/pleroma/web/api_spec/operations/notification_operation.ex219
-rw-r--r--lib/pleroma/web/api_spec/operations/pleroma_account_operation.ex96
-rw-r--r--lib/pleroma/web/api_spec/operations/pleroma_conversation_operation.ex106
-rw-r--r--lib/pleroma/web/api_spec/operations/pleroma_emoji_pack_operation.ex418
-rw-r--r--lib/pleroma/web/api_spec/operations/pleroma_mascot_operation.ex79
-rw-r--r--lib/pleroma/web/api_spec/operations/pleroma_notification_operation.ex48
-rw-r--r--lib/pleroma/web/api_spec/operations/pleroma_scrobble_operation.ex102
-rw-r--r--lib/pleroma/web/api_spec/operations/poll_operation.ex76
-rw-r--r--lib/pleroma/web/api_spec/operations/report_operation.ex82
-rw-r--r--lib/pleroma/web/api_spec/operations/scheduled_activity_operation.ex96
-rw-r--r--lib/pleroma/web/api_spec/operations/search_operation.ex208
-rw-r--r--lib/pleroma/web/api_spec/operations/status_operation.ex519
-rw-r--r--lib/pleroma/web/api_spec/operations/subscription_operation.ex232
-rw-r--r--lib/pleroma/web/api_spec/operations/timeline_operation.ex191
-rw-r--r--lib/pleroma/web/api_spec/render_error.ex234
-rw-r--r--lib/pleroma/web/api_spec/schemas/account.ex220
-rw-r--r--lib/pleroma/web/api_spec/schemas/account_field.ex26
-rw-r--r--lib/pleroma/web/api_spec/schemas/account_relationship.ex44
-rw-r--r--lib/pleroma/web/api_spec/schemas/actor_type.ex13
-rw-r--r--lib/pleroma/web/api_spec/schemas/api_error.ex19
-rw-r--r--lib/pleroma/web/api_spec/schemas/attachment.ex68
-rw-r--r--lib/pleroma/web/api_spec/schemas/boolean_like.ex36
-rw-r--r--lib/pleroma/web/api_spec/schemas/chat.ex75
-rw-r--r--lib/pleroma/web/api_spec/schemas/chat_message.ex74
-rw-r--r--lib/pleroma/web/api_spec/schemas/conversation.ex41
-rw-r--r--lib/pleroma/web/api_spec/schemas/emoji.ex29
-rw-r--r--lib/pleroma/web/api_spec/schemas/flake_id.ex14
-rw-r--r--lib/pleroma/web/api_spec/schemas/list.ex23
-rw-r--r--lib/pleroma/web/api_spec/schemas/poll.ex82
-rw-r--r--lib/pleroma/web/api_spec/schemas/push_subscription.ex66
-rw-r--r--lib/pleroma/web/api_spec/schemas/scheduled_status.ex54
-rw-r--r--lib/pleroma/web/api_spec/schemas/status.ex334
-rw-r--r--lib/pleroma/web/api_spec/schemas/tag.ex27
-rw-r--r--lib/pleroma/web/api_spec/schemas/visibility_scope.ex14
-rw-r--r--lib/pleroma/web/auth/ldap_authenticator.ex43
-rw-r--r--lib/pleroma/web/auth/pleroma_authenticator.ex7
-rw-r--r--lib/pleroma/web/auth/totp_authenticator.ex45
-rw-r--r--lib/pleroma/web/chat_channel.ex7
-rw-r--r--lib/pleroma/web/common_api/activity_draft.ex42
-rw-r--r--lib/pleroma/web/common_api/common_api.ex367
-rw-r--r--lib/pleroma/web/common_api/utils.ex73
-rw-r--r--lib/pleroma/web/controller_helper.ex84
-rw-r--r--lib/pleroma/web/embed_controller.ex42
-rw-r--r--lib/pleroma/web/endpoint.ex25
-rw-r--r--lib/pleroma/web/fallback_redirect_controller.ex81
-rw-r--r--lib/pleroma/web/federator/federator.ex13
-rw-r--r--lib/pleroma/web/feed/feed_view.ex9
-rw-r--r--lib/pleroma/web/feed/tag_controller.ex8
-rw-r--r--lib/pleroma/web/feed/user_controller.ex33
-rw-r--r--lib/pleroma/web/masto_fe_controller.ex12
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/account_controller.ex297
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/app_controller.ex17
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/auth_controller.ex4
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/conversation_controller.ex7
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/custom_emoji_controller.ex10
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/domain_block_controller.ex19
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex4
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/filter_controller.ex57
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/follow_request_controller.ex5
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/instance_controller.ex10
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/list_controller.ex30
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/marker_controller.ex12
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex8
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/media_controller.ex49
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/notification_controller.ex42
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/poll_controller.ex8
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/report_controller.ex5
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/scheduled_activity_controller.ex14
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/search_controller.ex114
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/status_controller.ex145
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex44
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/suggestion_controller.ex21
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex157
-rw-r--r--lib/pleroma/web/mastodon_api/mastodon_api.ex16
-rw-r--r--lib/pleroma/web/mastodon_api/views/account_view.ex219
-rw-r--r--lib/pleroma/web/mastodon_api/views/app_view.ex21
-rw-r--r--lib/pleroma/web/mastodon_api/views/conversation_view.ex13
-rw-r--r--lib/pleroma/web/mastodon_api/views/filter_view.ex8
-rw-r--r--lib/pleroma/web/mastodon_api/views/instance_view.ex77
-rw-r--r--lib/pleroma/web/mastodon_api/views/marker_view.ex16
-rw-r--r--lib/pleroma/web/mastodon_api/views/notification_view.ex162
-rw-r--r--lib/pleroma/web/mastodon_api/views/poll_view.ex25
-rw-r--r--lib/pleroma/web/mastodon_api/views/scheduled_activity_view.ex8
-rw-r--r--lib/pleroma/web/mastodon_api/views/status_view.ex186
-rw-r--r--lib/pleroma/web/mastodon_api/views/subscription_view.ex (renamed from lib/pleroma/web/mastodon_api/views/push_subscription_view.ex)4
-rw-r--r--lib/pleroma/web/mastodon_api/websocket_handler.ex67
-rw-r--r--lib/pleroma/web/media_proxy/invalidation.ex38
-rw-r--r--lib/pleroma/web/media_proxy/invalidations/http.ex40
-rw-r--r--lib/pleroma/web/media_proxy/invalidations/script.ex43
-rw-r--r--lib/pleroma/web/media_proxy/media_proxy.ex64
-rw-r--r--lib/pleroma/web/media_proxy/media_proxy_controller.ex4
-rw-r--r--lib/pleroma/web/metadata.ex7
-rw-r--r--lib/pleroma/web/metadata/restrict_indexing.ex25
-rw-r--r--lib/pleroma/web/mongooseim/mongoose_im_controller.ex8
-rw-r--r--lib/pleroma/web/nodeinfo/nodeinfo.ex91
-rw-r--r--lib/pleroma/web/nodeinfo/nodeinfo_controller.ex151
-rw-r--r--lib/pleroma/web/oauth/app.ex85
-rw-r--r--lib/pleroma/web/oauth/mfa_controller.ex98
-rw-r--r--lib/pleroma/web/oauth/mfa_view.ex17
-rw-r--r--lib/pleroma/web/oauth/oauth_controller.ex131
-rw-r--r--lib/pleroma/web/oauth/oauth_view.ex22
-rw-r--r--lib/pleroma/web/oauth/scopes.ex5
-rw-r--r--lib/pleroma/web/oauth/token/clean_worker.ex38
-rw-r--r--lib/pleroma/web/oauth/token/response.ex36
-rw-r--r--lib/pleroma/web/ostatus/ostatus_controller.ex22
-rw-r--r--lib/pleroma/web/pleroma_api/controllers/account_controller.ex102
-rw-r--r--lib/pleroma/web/pleroma_api/controllers/chat_controller.ex179
-rw-r--r--lib/pleroma/web/pleroma_api/controllers/conversation_controller.ex94
-rw-r--r--lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex643
-rw-r--r--lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex304
-rw-r--r--lib/pleroma/web/pleroma_api/controllers/emoji_reaction_controller.ex64
-rw-r--r--lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex5
-rw-r--r--lib/pleroma/web/pleroma_api/controllers/notification_controller.ex36
-rw-r--r--lib/pleroma/web/pleroma_api/controllers/pleroma_api_controller.ex199
-rw-r--r--lib/pleroma/web/pleroma_api/controllers/scrobble_controller.ex36
-rw-r--r--lib/pleroma/web/pleroma_api/controllers/two_factor_authentication_controller.ex133
-rw-r--r--lib/pleroma/web/pleroma_api/views/chat/message_reference_view.ex50
-rw-r--r--lib/pleroma/web/pleroma_api/views/chat_view.ex44
-rw-r--r--lib/pleroma/web/pleroma_api/views/emoji_reaction_view.ex33
-rw-r--r--lib/pleroma/web/pleroma_api/views/scrobble_view.ex37
-rw-r--r--lib/pleroma/web/preload.ex36
-rw-r--r--lib/pleroma/web/preload/instance.ex50
-rw-r--r--lib/pleroma/web/preload/provider.ex7
-rw-r--r--lib/pleroma/web/preload/timelines.ex39
-rw-r--r--lib/pleroma/web/preload/user.ex26
-rw-r--r--lib/pleroma/web/push/impl.ex38
-rw-r--r--lib/pleroma/web/push/subscription.ex10
-rw-r--r--lib/pleroma/web/rel_me.ex18
-rw-r--r--lib/pleroma/web/rich_media/helpers.ex40
-rw-r--r--lib/pleroma/web/rich_media/parser.ex13
-rw-r--r--lib/pleroma/web/rich_media/parsers/meta_tags_parser.ex25
-rw-r--r--lib/pleroma/web/rich_media/parsers/oembed_parser.ex6
-rw-r--r--lib/pleroma/web/rich_media/parsers/ogp.ex11
-rw-r--r--lib/pleroma/web/rich_media/parsers/twitter_card.ex15
-rw-r--r--lib/pleroma/web/router.ex437
-rw-r--r--lib/pleroma/web/static_fe/static_fe_controller.ex32
-rw-r--r--lib/pleroma/web/static_fe/static_fe_view.ex9
-rw-r--r--lib/pleroma/web/streamer/ping.ex37
-rw-r--r--lib/pleroma/web/streamer/state.ex71
-rw-r--r--lib/pleroma/web/streamer/streamer.ex261
-rw-r--r--lib/pleroma/web/streamer/streamer_socket.ex35
-rw-r--r--lib/pleroma/web/streamer/supervisor.ex37
-rw-r--r--lib/pleroma/web/streamer/worker.ex226
-rw-r--r--lib/pleroma/web/templates/embed/_attachment.html.eex8
-rw-r--r--lib/pleroma/web/templates/embed/show.html.eex76
-rw-r--r--lib/pleroma/web/templates/feed/feed/_activity.atom.eex (renamed from lib/pleroma/web/templates/feed/feed/_activity.xml.eex)8
-rw-r--r--lib/pleroma/web/templates/feed/feed/_activity.rss.eex49
-rw-r--r--lib/pleroma/web/templates/feed/feed/_author.atom.eex (renamed from lib/pleroma/web/templates/feed/feed/_author.xml.eex)0
-rw-r--r--lib/pleroma/web/templates/feed/feed/_author.rss.eex17
-rw-r--r--lib/pleroma/web/templates/feed/feed/_tag_activity.atom.eex16
-rw-r--r--lib/pleroma/web/templates/feed/feed/_tag_activity.xml.eex15
-rw-r--r--lib/pleroma/web/templates/feed/feed/user.atom.eex (renamed from lib/pleroma/web/templates/feed/feed/user.xml.eex)4
-rw-r--r--lib/pleroma/web/templates/feed/feed/user.rss.eex20
-rw-r--r--lib/pleroma/web/templates/layout/app.html.eex2
-rw-r--r--lib/pleroma/web/templates/layout/embed.html.eex15
-rw-r--r--lib/pleroma/web/templates/o_auth/mfa/recovery.html.eex24
-rw-r--r--lib/pleroma/web/templates/o_auth/mfa/totp.html.eex24
-rw-r--r--lib/pleroma/web/templates/static_fe/static_fe/_attachment.html.eex6
-rw-r--r--lib/pleroma/web/templates/static_fe/static_fe/_notice.html.eex10
-rw-r--r--lib/pleroma/web/templates/static_fe/static_fe/_user_card.html.eex4
-rw-r--r--lib/pleroma/web/templates/static_fe/static_fe/profile.html.eex2
-rw-r--r--lib/pleroma/web/templates/twitter_api/remote_follow/follow_mfa.html.eex13
-rw-r--r--lib/pleroma/web/twitter_api/controllers/remote_follow_controller.ex49
-rw-r--r--lib/pleroma/web/twitter_api/controllers/util_controller.ex94
-rw-r--r--lib/pleroma/web/twitter_api/twitter_api.ex161
-rw-r--r--lib/pleroma/web/twitter_api/twitter_api_controller.ex24
-rw-r--r--lib/pleroma/web/twitter_api/views/util_view.ex14
-rw-r--r--lib/pleroma/web/views/embed_view.ex74
-rw-r--r--lib/pleroma/web/views/masto_fe_view.ex32
-rw-r--r--lib/pleroma/web/views/streamer_view.ex25
-rw-r--r--lib/pleroma/web/web.ex105
-rw-r--r--lib/pleroma/web/web_finger/web_finger.ex90
-rw-r--r--lib/pleroma/workers/attachments_cleanup_worker.ex158
-rw-r--r--lib/pleroma/workers/background_worker.ex34
-rw-r--r--lib/pleroma/workers/cron/clear_oauth_token_worker.ex4
-rw-r--r--lib/pleroma/workers/cron/digest_emails_worker.ex4
-rw-r--r--lib/pleroma/workers/cron/new_users_digest_worker.ex4
-rw-r--r--lib/pleroma/workers/cron/purge_expired_activities_worker.ex6
-rw-r--r--lib/pleroma/workers/cron/stats_worker.ex3
-rw-r--r--lib/pleroma/workers/mailer_worker.ex2
-rw-r--r--lib/pleroma/workers/publisher_worker.ex6
-rw-r--r--lib/pleroma/workers/receiver_worker.ex2
-rw-r--r--lib/pleroma/workers/remote_fetcher_worker.ex8
-rw-r--r--lib/pleroma/workers/scheduled_activity_worker.ex4
-rw-r--r--lib/pleroma/workers/transmogrifier_worker.ex2
-rw-r--r--lib/pleroma/workers/web_pusher_worker.ex2
-rw-r--r--lib/pleroma/workers/worker_helper.ex4
-rw-r--r--mix.exs149
-rw-r--r--mix.lock101
-rw-r--r--priv/gettext/en/LC_MESSAGES/errors.po465
-rw-r--r--priv/gettext/errors.pot316
-rw-r--r--priv/gettext/fr/LC_MESSAGES/errors.po164
-rw-r--r--priv/gettext/it/LC_MESSAGES/errors.po585
-rw-r--r--priv/gettext/nl/LC_MESSAGES/errors.po580
-rw-r--r--priv/gettext/pl/LC_MESSAGES/errors.po587
-rw-r--r--priv/repo/migrations/20190408123347_create_conversations.exs2
-rw-r--r--priv/repo/migrations/20190414125034_migrate_old_bookmarks.exs1
-rw-r--r--priv/repo/migrations/20190506054542_add_multi_factor_authentication_settings_to_user.exs9
-rw-r--r--priv/repo/migrations/20190508193213_create_mfa_tokens.exs16
-rw-r--r--priv/repo/migrations/20190711042021_create_safe_jsonb_set.exs1
-rw-r--r--priv/repo/migrations/20200227122417_add_trusted_to_apps.exs9
-rw-r--r--priv/repo/migrations/20200309123730_create_chats.exs16
-rw-r--r--priv/repo/migrations/20200322174133_user_raw_bio.exs9
-rw-r--r--priv/repo/migrations/20200323122421_mrf_config_move_from_instance_namespace.exs39
-rw-r--r--priv/repo/migrations/20200328193433_populate_user_raw_bio.exs25
-rw-r--r--priv/repo/migrations/20200401030751_users_add_public_key.exs17
-rw-r--r--priv/repo/migrations/20200401072456_users_add_inboxes.exs20
-rw-r--r--priv/repo/migrations/20200402063221_update_oban_jobs_table.exs11
-rw-r--r--priv/repo/migrations/20200406100225_users_add_emoji.exs38
-rw-r--r--priv/repo/migrations/20200406105422_users_remove_source_data.exs15
-rw-r--r--priv/repo/migrations/20200415181818_update_markers.exs44
-rw-r--r--priv/repo/migrations/20200505072231_remove_magic_key_field.exs9
-rw-r--r--priv/repo/migrations/20200508092434_update_counter_cache_table.exs143
-rw-r--r--priv/repo/migrations/20200520155351_add_recipients_contain_blocked_domains_function.exs33
-rw-r--r--priv/repo/migrations/20200527163635_delete_notifications_from_invisible_users.exs18
-rw-r--r--priv/repo/migrations/20200602094828_add_type_to_notifications.exs9
-rw-r--r--priv/repo/migrations/20200602125218_backfill_notification_types.exs10
-rw-r--r--priv/repo/migrations/20200602150528_create_chat_message_reference.exs20
-rw-r--r--priv/repo/migrations/20200603105113_add_unique_index_to_chat_message_references.exs7
-rw-r--r--priv/repo/migrations/20200603120448_remove_unread_from_chats.exs9
-rw-r--r--priv/repo/migrations/20200603122732_add_seen_index_to_chat_message_references.exs12
-rw-r--r--priv/repo/migrations/20200604150318_migrate_seen_to_unread_in_chat_message_references.exs30
-rw-r--r--priv/repo/migrations/20200606105430_change_type_to_enum_for_notifications.exs36
-rw-r--r--priv/repo/migrations/20200607112923_change_chat_id_to_flake.exs23
-rw-r--r--priv/repo/migrations/20200626163359_rename_notification_privacy_option.exs19
-rw-r--r--priv/repo/migrations/20200630162024_rename_user_settings_col.exs11
-rw-r--r--priv/repo/migrations/20200703101031_add_chat_acceptance_to_users.exs17
-rw-r--r--priv/repo/migrations/20200706060258_remove_tesla_from_config.exs10
-rw-r--r--priv/repo/migrations/20200707112859_instances_add_favicon.exs10
-rw-r--r--priv/repo/migrations/20200708193702_drop_user_trigram_index.exs18
-rw-r--r--priv/repo/migrations/20200712234852_add_approval_fields_to_users.exs10
-rw-r--r--priv/repo/migrations/20200714081657_oban_2_0_config_changes.exs27
-rw-r--r--priv/repo/migrations/20200716195806_autolinker_to_linkify.exs36
-rw-r--r--priv/repo/migrations/20200722185515_fix_malformed_formatter_config.exs26
-rw-r--r--priv/repo/migrations/20200724133313_move_welcome_settings.exs94
-rw-r--r--priv/repo/migrations/20200802170532_fix_legacy_tags.exs40
-rw-r--r--priv/repo/migrations/20200804180322_remove_nonlocal_expirations.exs19
-rw-r--r--priv/repo/migrations/20200804183107_add_unique_index_to_app_client_id.exs7
-rw-r--r--priv/repo/migrations/20200808173046_only_expire_creates.exs19
-rw-r--r--priv/repo/migrations/20200811125613_set_defaults_to_user_approval_pending.exs15
-rw-r--r--priv/repo/migrations/20200811143147_ap_id_not_null.exs19
-rw-r--r--priv/repo/migrations/20200817120935_add_invisible_index_to_users.exs7
-rw-r--r--priv/repo/optional_migrations/rum_indexing/20190510135645_add_fts_index_to_objects_two.exs4
-rw-r--r--priv/static/READ_THIS_BEFORE_TOUCHING_FILES_HERE1
-rw-r--r--priv/static/adminfe/app.07a1f8db.css (renamed from priv/static/adminfe/app.796ca6d4.css)2
-rw-r--r--priv/static/adminfe/chunk-0171.aa11eafe.css1
-rw-r--r--priv/static/adminfe/chunk-0598.d8f2b478.css1
-rw-r--r--priv/static/adminfe/chunk-0778.29be65e2.css (renamed from priv/static/adminfe/chunk-0778.d9e7180a.css)0
-rw-r--r--priv/static/adminfe/chunk-0f09.66ca2a61.css1
-rw-r--r--priv/static/adminfe/chunk-176e.b7aa5351.css1
-rw-r--r--priv/static/adminfe/chunk-19e2.934ad654.css1
-rw-r--r--priv/static/adminfe/chunk-22d2.813009b9.css1
-rw-r--r--priv/static/adminfe/chunk-28f8.0aae6427.css1
-rw-r--r--priv/static/adminfe/chunk-2d97.82cbb623.css1
-rw-r--r--priv/static/adminfe/chunk-3221.0ef79c67.css1
-rw-r--r--priv/static/adminfe/chunk-3384.2278f87c.css1
-rw-r--r--priv/static/adminfe/chunk-39ad.ba67c97f.css1
-rw-r--r--priv/static/adminfe/chunk-3ba2.63b1228d.css1
-rw-r--r--priv/static/adminfe/chunk-4011.c4799067.css1
-rw-r--r--priv/static/adminfe/chunk-40a4.665332db.css1
-rw-r--r--priv/static/adminfe/chunk-4eb4.b72d16c3.css1
-rw-r--r--priv/static/adminfe/chunk-565e.8c036a6e.css1
-rw-r--r--priv/static/adminfe/chunk-60a9.7b5b9559.css1
-rw-r--r--priv/static/adminfe/chunk-6198.3c37d6af.css (renamed from priv/static/adminfe/chunk-0961.d3692214.css)0
-rw-r--r--priv/static/adminfe/chunk-654e.b2e16b59.css1
-rw-r--r--priv/static/adminfe/chunk-68ea.7633295f.css (renamed from priv/static/adminfe/chunk-0558.af0d89cd.css)0
-rw-r--r--priv/static/adminfe/chunk-68ea.81e11186.css1
-rw-r--r--priv/static/adminfe/chunk-6b68.0cc00484.css1
-rw-r--r--priv/static/adminfe/chunk-6e81.0e9e6d27.css (renamed from priv/static/adminfe/chunk-6e81.0e80d020.css)0
-rw-r--r--priv/static/adminfe/chunk-6e81.7e5babfc.css1
-rw-r--r--priv/static/adminfe/chunk-6e8c.ef26acfd.css1
-rw-r--r--priv/static/adminfe/chunk-7503.cc089ee4.css1
-rw-r--r--priv/static/adminfe/chunk-7637.941c4edb.css1
-rw-r--r--priv/static/adminfe/chunk-7c6b.b529c720.css1
-rw-r--r--priv/static/adminfe/chunk-9043.3f527a93.css1
-rw-r--r--priv/static/adminfe/chunk-970d.f59cca8c.css1
-rw-r--r--priv/static/adminfe/chunk-97e2.9f9fab0f.css1
-rw-r--r--priv/static/adminfe/chunk-9a72.786caeb3.css1
-rw-r--r--priv/static/adminfe/chunk-commons.a343b725.css1
-rw-r--r--priv/static/adminfe/chunk-d38a.cabdc22e.css1
-rw-r--r--priv/static/adminfe/chunk-d892.56863b19.css1
-rw-r--r--priv/static/adminfe/chunk-e458.f88bafea.css1
-rw-r--r--priv/static/adminfe/chunk-elementUI.40545a1f.css (renamed from priv/static/adminfe/chunk-elementUI.1abbc9b8.css)0
-rw-r--r--priv/static/adminfe/chunk-libs.0380664d.css (renamed from priv/static/adminfe/chunk-libs.686b5876.css)0
-rw-r--r--priv/static/adminfe/index.html2
-rw-r--r--priv/static/adminfe/static/js/ZhIB.861df339.js9
-rw-r--r--priv/static/adminfe/static/js/ZhIB.861df339.js.map1
-rw-r--r--priv/static/adminfe/static/js/app.1df22cde.js2
-rw-r--r--priv/static/adminfe/static/js/app.1df22cde.js.map1
-rw-r--r--priv/static/adminfe/static/js/app.203f69f8.js2
-rw-r--r--priv/static/adminfe/static/js/app.203f69f8.js.map1
-rw-r--r--priv/static/adminfe/static/js/chunk-0171.9e927b8a.js2
-rw-r--r--priv/static/adminfe/static/js/chunk-0171.9e927b8a.js.map1
-rw-r--r--priv/static/adminfe/static/js/chunk-0778.b17650df.js.map1
-rw-r--r--priv/static/adminfe/static/js/chunk-176e.5c19378d.js2
-rw-r--r--priv/static/adminfe/static/js/chunk-176e.5c19378d.js.map1
-rw-r--r--priv/static/adminfe/static/js/chunk-22d2.a0cf7976.js2
-rw-r--r--priv/static/adminfe/static/js/chunk-22d2.a0cf7976.js.map1
-rw-r--r--priv/static/adminfe/static/js/chunk-2d97.079e9e64.js2
-rw-r--r--priv/static/adminfe/static/js/chunk-2d97.079e9e64.js.map1
-rw-r--r--priv/static/adminfe/static/js/chunk-3384.458ffaf1.js2
-rw-r--r--priv/static/adminfe/static/js/chunk-3384.458ffaf1.js.map1
-rw-r--r--priv/static/adminfe/static/js/chunk-4011.67fb1692.js2
-rw-r--r--priv/static/adminfe/static/js/chunk-4011.67fb1692.js.map1
-rw-r--r--priv/static/adminfe/static/js/chunk-40a4.5dc0e299.js2
-rw-r--r--priv/static/adminfe/static/js/chunk-40a4.5dc0e299.js.map1
-rw-r--r--priv/static/adminfe/static/js/chunk-5118.7c48ad58.js (renamed from priv/static/adminfe/static/js/chunk-7f9e.c49aa694.js)4
-rw-r--r--priv/static/adminfe/static/js/chunk-5118.7c48ad58.js.map (renamed from priv/static/adminfe/static/js/chunk-7f9e.c49aa694.js.map)2
-rw-r--r--priv/static/adminfe/static/js/chunk-565e.e1555105.js2
-rw-r--r--priv/static/adminfe/static/js/chunk-565e.e1555105.js.map1
-rw-r--r--priv/static/adminfe/static/js/chunk-60a9.22fe45f3.js2
-rw-r--r--priv/static/adminfe/static/js/chunk-60a9.22fe45f3.js.map1
-rw-r--r--priv/static/adminfe/static/js/chunk-654e.38dd4b85.js2
-rw-r--r--priv/static/adminfe/static/js/chunk-654e.38dd4b85.js.map1
-rw-r--r--priv/static/adminfe/static/js/chunk-68ea.0dae7e55.js (renamed from priv/static/adminfe/static/js/chunk-0558.75954137.js)4
-rw-r--r--priv/static/adminfe/static/js/chunk-68ea.0dae7e55.js.map (renamed from priv/static/adminfe/static/js/chunk-0558.75954137.js.map)2
-rw-r--r--priv/static/adminfe/static/js/chunk-6b68.fbc0f684.js2
-rw-r--r--priv/static/adminfe/static/js/chunk-6b68.fbc0f684.js.map1
-rw-r--r--priv/static/adminfe/static/js/chunk-6e81.6043af74.js (renamed from priv/static/adminfe/static/js/chunk-6e81.3733ace2.js)2
-rw-r--r--priv/static/adminfe/static/js/chunk-6e81.6043af74.js.map (renamed from priv/static/adminfe/static/js/chunk-6e81.3733ace2.js.map)2
-rw-r--r--priv/static/adminfe/static/js/chunk-6e8c.2aa335e0.js2
-rw-r--r--priv/static/adminfe/static/js/chunk-6e8c.2aa335e0.js.map1
-rw-r--r--priv/static/adminfe/static/js/chunk-7503.278e0031.js2
-rw-r--r--priv/static/adminfe/static/js/chunk-7503.278e0031.js.map1
-rw-r--r--priv/static/adminfe/static/js/chunk-7637.8f5fb36e.js2
-rw-r--r--priv/static/adminfe/static/js/chunk-7637.8f5fb36e.js.map1
-rw-r--r--priv/static/adminfe/static/js/chunk-7c6b.1ebeb0e4.js (renamed from priv/static/adminfe/static/js/chunk-0778.b17650df.js)4
-rw-r--r--priv/static/adminfe/static/js/chunk-7c6b.1ebeb0e4.js.map1
-rw-r--r--priv/static/adminfe/static/js/chunk-970d.2457e066.js2
-rw-r--r--priv/static/adminfe/static/js/chunk-970d.2457e066.js.map1
-rw-r--r--priv/static/adminfe/static/js/chunk-97e2.c51fe6b0.js2
-rw-r--r--priv/static/adminfe/static/js/chunk-97e2.c51fe6b0.js.map1
-rw-r--r--priv/static/adminfe/static/js/chunk-9a72.41e843cd.js (renamed from priv/static/adminfe/static/js/chunk-0961.ef33e81b.js)4
-rw-r--r--priv/static/adminfe/static/js/chunk-9a72.41e843cd.js.map (renamed from priv/static/adminfe/static/js/chunk-0961.ef33e81b.js.map)2
-rw-r--r--priv/static/adminfe/static/js/chunk-commons.51fe2926.js2
-rw-r--r--priv/static/adminfe/static/js/chunk-commons.51fe2926.js.map1
-rw-r--r--priv/static/adminfe/static/js/chunk-d38a.a851004a.js2
-rw-r--r--priv/static/adminfe/static/js/chunk-d38a.a851004a.js.map1
-rw-r--r--priv/static/adminfe/static/js/chunk-e458.4e5aad44.js2
-rw-r--r--priv/static/adminfe/static/js/chunk-e458.4e5aad44.js.map1
-rw-r--r--priv/static/adminfe/static/js/chunk-elementUI.8e5c404c.js (renamed from priv/static/adminfe/static/js/chunk-elementUI.fba0efec.js)2
-rw-r--r--priv/static/adminfe/static/js/chunk-elementUI.8e5c404c.js.map (renamed from priv/static/adminfe/static/js/chunk-elementUI.fba0efec.js.map)2
-rw-r--r--priv/static/adminfe/static/js/chunk-libs.b8c453ab.js.map1
-rw-r--r--priv/static/adminfe/static/js/chunk-libs.f842b12e.js (renamed from priv/static/adminfe/static/js/chunk-libs.b8c453ab.js)25
-rw-r--r--priv/static/adminfe/static/js/chunk-libs.f842b12e.js.map1
-rw-r--r--priv/static/adminfe/static/js/runtime.04c4fa2f.js2
-rw-r--r--priv/static/adminfe/static/js/runtime.04c4fa2f.js.map1
-rw-r--r--priv/static/adminfe/static/js/runtime.1b4f6ce0.js2
-rw-r--r--priv/static/adminfe/static/js/runtime.1b4f6ce0.js.map1
-rw-r--r--priv/static/embed.css115
-rw-r--r--priv/static/embed.js43
-rw-r--r--priv/static/font/fontello.1575660578688.eotbin24628 -> 0 bytes
-rw-r--r--priv/static/font/fontello.1575660578688.svg126
-rw-r--r--priv/static/font/fontello.1575660578688.ttfbin24460 -> 0 bytes
-rw-r--r--priv/static/font/fontello.1575660578688.woffbin14832 -> 0 bytes
-rw-r--r--priv/static/font/fontello.1575660578688.woff2bin12664 -> 0 bytes
-rw-r--r--priv/static/font/fontello.1575662648966.eotbin24628 -> 0 bytes
-rw-r--r--priv/static/font/fontello.1575662648966.svg126
-rw-r--r--priv/static/font/fontello.1575662648966.ttfbin24460 -> 0 bytes
-rw-r--r--priv/static/font/fontello.1575662648966.woffbin14832 -> 0 bytes
-rw-r--r--priv/static/font/fontello.1575662648966.woff2bin12628 -> 0 bytes
-rw-r--r--priv/static/fontello.1575660578688.css146
-rw-r--r--priv/static/fontello.1575662648966.css146
-rw-r--r--priv/static/index.html2
-rw-r--r--priv/static/packs/arrow-key-navigation.js2
-rw-r--r--priv/static/packs/base_polyfills.js4
-rw-r--r--priv/static/packs/base_polyfills.js.LICENSE.txt (renamed from priv/static/packs/base_polyfills.js.LICENSE)0
-rw-r--r--priv/static/packs/base_polyfills.js.map2
-rw-r--r--priv/static/packs/common.js4
-rw-r--r--priv/static/packs/common.js.LICENSE.txt (renamed from priv/static/packs/common.js.LICENSE)0
-rw-r--r--priv/static/packs/common.js.map2
-rw-r--r--priv/static/packs/containers/media_container.js4
-rw-r--r--priv/static/packs/containers/media_container.js.LICENSE.txt (renamed from priv/static/packs/containers/media_container.js.LICENSE)172
-rw-r--r--priv/static/packs/containers/media_container.js.map2
-rw-r--r--priv/static/packs/core/admin.js2
-rw-r--r--priv/static/packs/core/admin.js.map2
-rw-r--r--priv/static/packs/core/auth.js4
-rw-r--r--priv/static/packs/core/auth.js.LICENSE.txt (renamed from priv/static/packs/core/auth.js.LICENSE)0
-rw-r--r--priv/static/packs/core/auth.js.map2
-rw-r--r--priv/static/packs/core/common.js2
-rw-r--r--priv/static/packs/core/common.js.map2
-rw-r--r--priv/static/packs/core/embed.js2
-rw-r--r--priv/static/packs/core/mailer.js2
-rw-r--r--priv/static/packs/core/modal.js2
-rw-r--r--priv/static/packs/core/modal.js.map2
-rw-r--r--priv/static/packs/core/public.js2
-rw-r--r--priv/static/packs/core/public.js.map2
-rw-r--r--priv/static/packs/core/settings.js4
-rw-r--r--priv/static/packs/core/settings.js.LICENSE.txt (renamed from priv/static/packs/core/settings.js.LICENSE)0
-rw-r--r--priv/static/packs/core/settings.js.map2
-rw-r--r--priv/static/packs/emoji_picker.js2
-rw-r--r--priv/static/packs/extra_polyfills.js4
-rw-r--r--priv/static/packs/extra_polyfills.js.LICENSE.txt (renamed from priv/static/packs/extra_polyfills.js.LICENSE)0
-rw-r--r--priv/static/packs/extra_polyfills.js.map2
-rw-r--r--priv/static/packs/features/account_gallery.js2
-rw-r--r--priv/static/packs/features/account_gallery.js.map2
-rw-r--r--priv/static/packs/features/account_timeline.js2
-rw-r--r--priv/static/packs/features/account_timeline.js.map2
-rw-r--r--priv/static/packs/features/blocks.js2
-rw-r--r--priv/static/packs/features/blocks.js.map2
-rw-r--r--priv/static/packs/features/bookmarked_statuses.js2
-rw-r--r--priv/static/packs/features/bookmarked_statuses.js.map2
-rw-r--r--priv/static/packs/features/community_timeline.js2
-rw-r--r--priv/static/packs/features/community_timeline.js.map2
-rw-r--r--priv/static/packs/features/compose.js2
-rw-r--r--priv/static/packs/features/compose.js.map2
-rw-r--r--priv/static/packs/features/direct_timeline.js2
-rw-r--r--priv/static/packs/features/direct_timeline.js.map2
-rw-r--r--priv/static/packs/features/directory.js2
-rw-r--r--priv/static/packs/features/directory.js.map2
-rw-r--r--priv/static/packs/features/domain_blocks.js2
-rw-r--r--priv/static/packs/features/domain_blocks.js.map2
-rw-r--r--priv/static/packs/features/favourited_statuses.js2
-rw-r--r--priv/static/packs/features/favourited_statuses.js.map2
-rw-r--r--priv/static/packs/features/favourites.js2
-rw-r--r--priv/static/packs/features/favourites.js.map2
-rw-r--r--priv/static/packs/features/follow_requests.js2
-rw-r--r--priv/static/packs/features/follow_requests.js.map2
-rw-r--r--priv/static/packs/features/followers.js2
-rw-r--r--priv/static/packs/features/followers.js.map2
-rw-r--r--priv/static/packs/features/following.js2
-rw-r--r--priv/static/packs/features/following.js.map2
-rw-r--r--priv/static/packs/features/generic_not_found.js2
-rw-r--r--priv/static/packs/features/getting_started.js2
-rw-r--r--priv/static/packs/features/getting_started.js.map2
-rw-r--r--priv/static/packs/features/glitch/async/directory.js2
-rw-r--r--priv/static/packs/features/glitch/async/directory.js.map2
-rw-r--r--priv/static/packs/features/glitch/async/list_adder.js2
-rw-r--r--priv/static/packs/features/glitch/async/list_adder.js.map2
-rw-r--r--priv/static/packs/features/glitch/async/search.js2
-rw-r--r--priv/static/packs/features/hashtag_timeline.js2
-rw-r--r--priv/static/packs/features/hashtag_timeline.js.map2
-rw-r--r--priv/static/packs/features/home_timeline.js2
-rw-r--r--priv/static/packs/features/home_timeline.js.map2
-rw-r--r--priv/static/packs/features/keyboard_shortcuts.js2
-rw-r--r--priv/static/packs/features/keyboard_shortcuts.js.map2
-rw-r--r--priv/static/packs/features/list_adder.js2
-rw-r--r--priv/static/packs/features/list_adder.js.map2
-rw-r--r--priv/static/packs/features/list_editor.js2
-rw-r--r--priv/static/packs/features/list_editor.js.map2
-rw-r--r--priv/static/packs/features/list_timeline.js2
-rw-r--r--priv/static/packs/features/list_timeline.js.map2
-rw-r--r--priv/static/packs/features/lists.js2
-rw-r--r--priv/static/packs/features/lists.js.map2
-rw-r--r--priv/static/packs/features/mutes.js2
-rw-r--r--priv/static/packs/features/mutes.js.map2
-rw-r--r--priv/static/packs/features/notifications.js2
-rw-r--r--priv/static/packs/features/notifications.js.map2
-rw-r--r--priv/static/packs/features/pinned_statuses.js2
-rw-r--r--priv/static/packs/features/pinned_statuses.js.map2
-rw-r--r--priv/static/packs/features/public_timeline.js2
-rw-r--r--priv/static/packs/features/public_timeline.js.map2
-rw-r--r--priv/static/packs/features/reblogs.js2
-rw-r--r--priv/static/packs/features/reblogs.js.map2
-rw-r--r--priv/static/packs/features/search.js2
-rw-r--r--priv/static/packs/features/status.js2
-rw-r--r--priv/static/packs/features/status.js.map2
-rw-r--r--priv/static/packs/flavours/glitch/about.js4
-rw-r--r--priv/static/packs/flavours/glitch/about.js.LICENSE.txt (renamed from priv/static/packs/flavours/vanilla/about.js.LICENSE)236
-rw-r--r--priv/static/packs/flavours/glitch/about.js.map2
-rw-r--r--priv/static/packs/flavours/glitch/admin.js4
-rw-r--r--priv/static/packs/flavours/glitch/admin.js.LICENSE.txt (renamed from priv/static/packs/flavours/vanilla/admin.js.LICENSE)14
-rw-r--r--priv/static/packs/flavours/glitch/admin.js.map2
-rw-r--r--priv/static/packs/flavours/glitch/async/account_gallery.js2
-rw-r--r--priv/static/packs/flavours/glitch/async/account_gallery.js.map2
-rw-r--r--priv/static/packs/flavours/glitch/async/account_timeline.js2
-rw-r--r--priv/static/packs/flavours/glitch/async/account_timeline.js.map2
-rw-r--r--priv/static/packs/flavours/glitch/async/block_modal.js2
-rw-r--r--priv/static/packs/flavours/glitch/async/block_modal.js.map2
-rw-r--r--priv/static/packs/flavours/glitch/async/blocks.js2
-rw-r--r--priv/static/packs/flavours/glitch/async/blocks.js.map2
-rw-r--r--priv/static/packs/flavours/glitch/async/bookmarked_statuses.js2
-rw-r--r--priv/static/packs/flavours/glitch/async/bookmarked_statuses.js.map2
-rw-r--r--priv/static/packs/flavours/glitch/async/community_timeline.js2
-rw-r--r--priv/static/packs/flavours/glitch/async/community_timeline.js.map2
-rw-r--r--priv/static/packs/flavours/glitch/async/compose.js2
-rw-r--r--priv/static/packs/flavours/glitch/async/compose.js.map2
-rw-r--r--priv/static/packs/flavours/glitch/async/direct_timeline.js2
-rw-r--r--priv/static/packs/flavours/glitch/async/direct_timeline.js.map2
-rw-r--r--priv/static/packs/flavours/glitch/async/domain_blocks.js2
-rw-r--r--priv/static/packs/flavours/glitch/async/domain_blocks.js.map2
-rw-r--r--priv/static/packs/flavours/glitch/async/embed_modal.js2
-rw-r--r--priv/static/packs/flavours/glitch/async/embed_modal.js.map2
-rw-r--r--priv/static/packs/flavours/glitch/async/emoji_picker.js2
-rw-r--r--priv/static/packs/flavours/glitch/async/favourited_statuses.js2
-rw-r--r--priv/static/packs/flavours/glitch/async/favourited_statuses.js.map2
-rw-r--r--priv/static/packs/flavours/glitch/async/favourites.js2
-rw-r--r--priv/static/packs/flavours/glitch/async/favourites.js.map2
-rw-r--r--priv/static/packs/flavours/glitch/async/follow_requests.js2
-rw-r--r--priv/static/packs/flavours/glitch/async/follow_requests.js.map2
-rw-r--r--priv/static/packs/flavours/glitch/async/followers.js2
-rw-r--r--priv/static/packs/flavours/glitch/async/followers.js.map2
-rw-r--r--priv/static/packs/flavours/glitch/async/following.js2
-rw-r--r--priv/static/packs/flavours/glitch/async/following.js.map2
-rw-r--r--priv/static/packs/flavours/glitch/async/generic_not_found.js2
-rw-r--r--priv/static/packs/flavours/glitch/async/getting_started.js2
-rw-r--r--priv/static/packs/flavours/glitch/async/getting_started.js.map2
-rw-r--r--priv/static/packs/flavours/glitch/async/getting_started_misc.js2
-rw-r--r--priv/static/packs/flavours/glitch/async/getting_started_misc.js.map2
-rw-r--r--priv/static/packs/flavours/glitch/async/hashtag_timeline.js2
-rw-r--r--priv/static/packs/flavours/glitch/async/hashtag_timeline.js.map2
-rw-r--r--priv/static/packs/flavours/glitch/async/home_timeline.js2
-rw-r--r--priv/static/packs/flavours/glitch/async/home_timeline.js.map2
-rw-r--r--priv/static/packs/flavours/glitch/async/keyboard_shortcuts.js2
-rw-r--r--priv/static/packs/flavours/glitch/async/keyboard_shortcuts.js.map2
-rw-r--r--priv/static/packs/flavours/glitch/async/list_editor.js2
-rw-r--r--priv/static/packs/flavours/glitch/async/list_editor.js.map2
-rw-r--r--priv/static/packs/flavours/glitch/async/list_timeline.js2
-rw-r--r--priv/static/packs/flavours/glitch/async/list_timeline.js.map2
-rw-r--r--priv/static/packs/flavours/glitch/async/lists.js2
-rw-r--r--priv/static/packs/flavours/glitch/async/lists.js.map2
-rw-r--r--priv/static/packs/flavours/glitch/async/mute_modal.js2
-rw-r--r--priv/static/packs/flavours/glitch/async/mute_modal.js.map2
-rw-r--r--priv/static/packs/flavours/glitch/async/mutes.js2
-rw-r--r--priv/static/packs/flavours/glitch/async/mutes.js.map2
-rw-r--r--priv/static/packs/flavours/glitch/async/notifications.js2
-rw-r--r--priv/static/packs/flavours/glitch/async/notifications.js.map2
-rw-r--r--priv/static/packs/flavours/glitch/async/onboarding_modal.js2
-rw-r--r--priv/static/packs/flavours/glitch/async/onboarding_modal.js.map2
-rw-r--r--priv/static/packs/flavours/glitch/async/pinned_accounts_editor.js2
-rw-r--r--priv/static/packs/flavours/glitch/async/pinned_accounts_editor.js.map2
-rw-r--r--priv/static/packs/flavours/glitch/async/pinned_statuses.js2
-rw-r--r--priv/static/packs/flavours/glitch/async/pinned_statuses.js.map2
-rw-r--r--priv/static/packs/flavours/glitch/async/public_timeline.js2
-rw-r--r--priv/static/packs/flavours/glitch/async/public_timeline.js.map2
-rw-r--r--priv/static/packs/flavours/glitch/async/reblogs.js2
-rw-r--r--priv/static/packs/flavours/glitch/async/reblogs.js.map2
-rw-r--r--priv/static/packs/flavours/glitch/async/report_modal.js2
-rw-r--r--priv/static/packs/flavours/glitch/async/report_modal.js.map2
-rw-r--r--priv/static/packs/flavours/glitch/async/settings_modal.js2
-rw-r--r--priv/static/packs/flavours/glitch/async/settings_modal.js.map2
-rw-r--r--priv/static/packs/flavours/glitch/async/status.js2
-rw-r--r--priv/static/packs/flavours/glitch/async/status.js.map2
-rw-r--r--priv/static/packs/flavours/glitch/common.css2
-rw-r--r--priv/static/packs/flavours/glitch/common.css.map2
-rw-r--r--priv/static/packs/flavours/glitch/common.js2
-rw-r--r--priv/static/packs/flavours/glitch/common.js.map2
-rw-r--r--priv/static/packs/flavours/glitch/embed.js4
-rw-r--r--priv/static/packs/flavours/glitch/embed.js.LICENSE.txt (renamed from priv/static/packs/flavours/glitch/admin.js.LICENSE)26
-rw-r--r--priv/static/packs/flavours/glitch/embed.js.map2
-rw-r--r--priv/static/packs/flavours/glitch/error.js2
-rw-r--r--priv/static/packs/flavours/glitch/home.js4
-rw-r--r--priv/static/packs/flavours/glitch/home.js.LICENSE.txt (renamed from priv/static/packs/flavours/glitch/home.js.LICENSE)244
-rw-r--r--priv/static/packs/flavours/glitch/home.js.map2
-rw-r--r--priv/static/packs/flavours/glitch/public.js4
-rw-r--r--priv/static/packs/flavours/glitch/public.js.LICENSE.txt (renamed from priv/static/packs/flavours/glitch/embed.js.LICENSE)26
-rw-r--r--priv/static/packs/flavours/glitch/public.js.map2
-rw-r--r--priv/static/packs/flavours/glitch/settings.js2
-rw-r--r--priv/static/packs/flavours/glitch/settings.js.map2
-rw-r--r--priv/static/packs/flavours/glitch/share.js4
-rw-r--r--priv/static/packs/flavours/glitch/share.js.LICENSE.txt (renamed from priv/static/packs/flavours/vanilla/home.js.LICENSE)236
-rw-r--r--priv/static/packs/flavours/glitch/share.js.map2
-rw-r--r--priv/static/packs/flavours/vanilla/about.js4
-rw-r--r--priv/static/packs/flavours/vanilla/about.js.LICENSE.txt (renamed from priv/static/packs/flavours/glitch/about.js.LICENSE)236
-rw-r--r--priv/static/packs/flavours/vanilla/about.js.map2
-rw-r--r--priv/static/packs/flavours/vanilla/admin.js4
-rw-r--r--priv/static/packs/flavours/vanilla/admin.js.LICENSE.txt (renamed from priv/static/packs/flavours/glitch/public.js.LICENSE)26
-rw-r--r--priv/static/packs/flavours/vanilla/admin.js.map2
-rw-r--r--priv/static/packs/flavours/vanilla/common.css2
-rw-r--r--priv/static/packs/flavours/vanilla/common.css.map2
-rw-r--r--priv/static/packs/flavours/vanilla/common.js2
-rw-r--r--priv/static/packs/flavours/vanilla/embed.js4
-rw-r--r--priv/static/packs/flavours/vanilla/embed.js.LICENSE41
-rw-r--r--priv/static/packs/flavours/vanilla/embed.js.LICENSE.txt41
-rw-r--r--priv/static/packs/flavours/vanilla/embed.js.map2
-rw-r--r--priv/static/packs/flavours/vanilla/error.js2
-rw-r--r--priv/static/packs/flavours/vanilla/home.js4
-rw-r--r--priv/static/packs/flavours/vanilla/home.js.LICENSE.txt (renamed from priv/static/packs/flavours/glitch/share.js.LICENSE)236
-rw-r--r--priv/static/packs/flavours/vanilla/home.js.map2
-rw-r--r--priv/static/packs/flavours/vanilla/public.js4
-rw-r--r--priv/static/packs/flavours/vanilla/public.js.LICENSE41
-rw-r--r--priv/static/packs/flavours/vanilla/public.js.LICENSE.txt41
-rw-r--r--priv/static/packs/flavours/vanilla/public.js.map2
-rw-r--r--priv/static/packs/flavours/vanilla/settings.js4
-rw-r--r--priv/static/packs/flavours/vanilla/settings.js.LICENSE41
-rw-r--r--priv/static/packs/flavours/vanilla/settings.js.LICENSE.txt41
-rw-r--r--priv/static/packs/flavours/vanilla/settings.js.map2
-rw-r--r--priv/static/packs/flavours/vanilla/share.js4
-rw-r--r--priv/static/packs/flavours/vanilla/share.js.LICENSE.txt (renamed from priv/static/packs/flavours/vanilla/share.js.LICENSE)232
-rw-r--r--priv/static/packs/flavours/vanilla/share.js.map2
-rw-r--r--priv/static/packs/locales.js2
-rw-r--r--priv/static/packs/locales.js.map2
-rw-r--r--priv/static/packs/locales/glitch/ar.js2
-rw-r--r--priv/static/packs/locales/glitch/ar.js.map2
-rw-r--r--priv/static/packs/locales/glitch/ast.js2
-rw-r--r--priv/static/packs/locales/glitch/ast.js.map2
-rw-r--r--priv/static/packs/locales/glitch/bg.js2
-rw-r--r--priv/static/packs/locales/glitch/bg.js.map2
-rw-r--r--priv/static/packs/locales/glitch/bn.js2
-rw-r--r--priv/static/packs/locales/glitch/bn.js.map2
-rw-r--r--priv/static/packs/locales/glitch/br.js2
-rw-r--r--priv/static/packs/locales/glitch/br.js.map2
-rw-r--r--priv/static/packs/locales/glitch/ca.js2
-rw-r--r--priv/static/packs/locales/glitch/ca.js.map2
-rw-r--r--priv/static/packs/locales/glitch/co.js2
-rw-r--r--priv/static/packs/locales/glitch/co.js.map2
-rw-r--r--priv/static/packs/locales/glitch/cs.js2
-rw-r--r--priv/static/packs/locales/glitch/cs.js.map2
-rw-r--r--priv/static/packs/locales/glitch/cy.js2
-rw-r--r--priv/static/packs/locales/glitch/cy.js.map2
-rw-r--r--priv/static/packs/locales/glitch/da.js2
-rw-r--r--priv/static/packs/locales/glitch/da.js.map2
-rw-r--r--priv/static/packs/locales/glitch/de.js2
-rw-r--r--priv/static/packs/locales/glitch/de.js.map2
-rw-r--r--priv/static/packs/locales/glitch/el.js2
-rw-r--r--priv/static/packs/locales/glitch/el.js.map2
-rw-r--r--priv/static/packs/locales/glitch/en.js2
-rw-r--r--priv/static/packs/locales/glitch/en.js.map2
-rw-r--r--priv/static/packs/locales/glitch/eo.js2
-rw-r--r--priv/static/packs/locales/glitch/eo.js.map2
-rw-r--r--priv/static/packs/locales/glitch/es-AR.js2
-rw-r--r--priv/static/packs/locales/glitch/es-AR.js.map2
-rw-r--r--priv/static/packs/locales/glitch/es.js2
-rw-r--r--priv/static/packs/locales/glitch/es.js.map2
-rw-r--r--priv/static/packs/locales/glitch/et.js2
-rw-r--r--priv/static/packs/locales/glitch/et.js.map2
-rw-r--r--priv/static/packs/locales/glitch/eu.js2
-rw-r--r--priv/static/packs/locales/glitch/eu.js.map2
-rw-r--r--priv/static/packs/locales/glitch/fa.js2
-rw-r--r--priv/static/packs/locales/glitch/fa.js.map2
-rw-r--r--priv/static/packs/locales/glitch/fi.js2
-rw-r--r--priv/static/packs/locales/glitch/fi.js.map2
-rw-r--r--priv/static/packs/locales/glitch/fr.js2
-rw-r--r--priv/static/packs/locales/glitch/fr.js.map2
-rw-r--r--priv/static/packs/locales/glitch/ga.js2
-rw-r--r--priv/static/packs/locales/glitch/ga.js.map2
-rw-r--r--priv/static/packs/locales/glitch/gl.js2
-rw-r--r--priv/static/packs/locales/glitch/gl.js.map2
-rw-r--r--priv/static/packs/locales/glitch/he.js2
-rw-r--r--priv/static/packs/locales/glitch/he.js.map2
-rw-r--r--priv/static/packs/locales/glitch/hi.js2
-rw-r--r--priv/static/packs/locales/glitch/hi.js.map2
-rw-r--r--priv/static/packs/locales/glitch/hr.js2
-rw-r--r--priv/static/packs/locales/glitch/hr.js.map2
-rw-r--r--priv/static/packs/locales/glitch/hu.js2
-rw-r--r--priv/static/packs/locales/glitch/hu.js.map2
-rw-r--r--priv/static/packs/locales/glitch/hy.js2
-rw-r--r--priv/static/packs/locales/glitch/hy.js.map2
-rw-r--r--priv/static/packs/locales/glitch/id.js2
-rw-r--r--priv/static/packs/locales/glitch/id.js.map2
-rw-r--r--priv/static/packs/locales/glitch/io.js2
-rw-r--r--priv/static/packs/locales/glitch/io.js.map2
-rw-r--r--priv/static/packs/locales/glitch/is.js2
-rw-r--r--priv/static/packs/locales/glitch/is.js.map2
-rw-r--r--priv/static/packs/locales/glitch/it.js2
-rw-r--r--priv/static/packs/locales/glitch/it.js.map2
-rw-r--r--priv/static/packs/locales/glitch/ja.js2
-rw-r--r--priv/static/packs/locales/glitch/ja.js.map2
-rw-r--r--priv/static/packs/locales/glitch/ka.js2
-rw-r--r--priv/static/packs/locales/glitch/ka.js.map2
-rw-r--r--priv/static/packs/locales/glitch/kab.js2
-rw-r--r--priv/static/packs/locales/glitch/kab.js.map2
-rw-r--r--priv/static/packs/locales/glitch/kk.js2
-rw-r--r--priv/static/packs/locales/glitch/kk.js.map2
-rw-r--r--priv/static/packs/locales/glitch/kn.js2
-rw-r--r--priv/static/packs/locales/glitch/kn.js.map2
-rw-r--r--priv/static/packs/locales/glitch/ko.js2
-rw-r--r--priv/static/packs/locales/glitch/ko.js.map2
-rw-r--r--priv/static/packs/locales/glitch/lt.js2
-rw-r--r--priv/static/packs/locales/glitch/lt.js.map2
-rw-r--r--priv/static/packs/locales/glitch/lv.js2
-rw-r--r--priv/static/packs/locales/glitch/lv.js.map2
-rw-r--r--priv/static/packs/locales/glitch/mk.js2
-rw-r--r--priv/static/packs/locales/glitch/mk.js.map2
-rw-r--r--priv/static/packs/locales/glitch/ml.js2
-rw-r--r--priv/static/packs/locales/glitch/ml.js.map2
-rw-r--r--priv/static/packs/locales/glitch/mr.js2
-rw-r--r--priv/static/packs/locales/glitch/mr.js.map2
-rw-r--r--priv/static/packs/locales/glitch/ms.js2
-rw-r--r--priv/static/packs/locales/glitch/ms.js.map2
-rw-r--r--priv/static/packs/locales/glitch/nl.js2
-rw-r--r--priv/static/packs/locales/glitch/nl.js.map2
-rw-r--r--priv/static/packs/locales/glitch/nn.js2
-rw-r--r--priv/static/packs/locales/glitch/nn.js.map2
-rw-r--r--priv/static/packs/locales/glitch/no.js2
-rw-r--r--priv/static/packs/locales/glitch/no.js.map2
-rw-r--r--priv/static/packs/locales/glitch/oc.js2
-rw-r--r--priv/static/packs/locales/glitch/oc.js.map2
-rw-r--r--priv/static/packs/locales/glitch/pl.js2
-rw-r--r--priv/static/packs/locales/glitch/pl.js.map2
-rw-r--r--priv/static/packs/locales/glitch/pt-BR.js2
-rw-r--r--priv/static/packs/locales/glitch/pt-BR.js.map2
-rw-r--r--priv/static/packs/locales/glitch/pt-PT.js2
-rw-r--r--priv/static/packs/locales/glitch/pt-PT.js.map2
-rw-r--r--priv/static/packs/locales/glitch/ro.js2
-rw-r--r--priv/static/packs/locales/glitch/ro.js.map2
-rw-r--r--priv/static/packs/locales/glitch/ru.js2
-rw-r--r--priv/static/packs/locales/glitch/ru.js.map2
-rw-r--r--priv/static/packs/locales/glitch/sk.js2
-rw-r--r--priv/static/packs/locales/glitch/sk.js.map2
-rw-r--r--priv/static/packs/locales/glitch/sl.js2
-rw-r--r--priv/static/packs/locales/glitch/sl.js.map2
-rw-r--r--priv/static/packs/locales/glitch/sq.js2
-rw-r--r--priv/static/packs/locales/glitch/sq.js.map2
-rw-r--r--priv/static/packs/locales/glitch/sr-Latn.js2
-rw-r--r--priv/static/packs/locales/glitch/sr-Latn.js.map2
-rw-r--r--priv/static/packs/locales/glitch/sr.js2
-rw-r--r--priv/static/packs/locales/glitch/sr.js.map2
-rw-r--r--priv/static/packs/locales/glitch/sv.js2
-rw-r--r--priv/static/packs/locales/glitch/sv.js.map2
-rw-r--r--priv/static/packs/locales/glitch/ta.js2
-rw-r--r--priv/static/packs/locales/glitch/ta.js.map2
-rw-r--r--priv/static/packs/locales/glitch/te.js2
-rw-r--r--priv/static/packs/locales/glitch/te.js.map2
-rw-r--r--priv/static/packs/locales/glitch/th.js2
-rw-r--r--priv/static/packs/locales/glitch/th.js.map2
-rw-r--r--priv/static/packs/locales/glitch/tr.js2
-rw-r--r--priv/static/packs/locales/glitch/tr.js.map2
-rw-r--r--priv/static/packs/locales/glitch/uk.js2
-rw-r--r--priv/static/packs/locales/glitch/uk.js.map2
-rw-r--r--priv/static/packs/locales/glitch/ur.js2
-rw-r--r--priv/static/packs/locales/glitch/ur.js.map2
-rw-r--r--priv/static/packs/locales/glitch/vi.js2
-rw-r--r--priv/static/packs/locales/glitch/vi.js.map2
-rw-r--r--priv/static/packs/locales/glitch/zh-CN.js2
-rw-r--r--priv/static/packs/locales/glitch/zh-CN.js.map2
-rw-r--r--priv/static/packs/locales/glitch/zh-HK.js2
-rw-r--r--priv/static/packs/locales/glitch/zh-HK.js.map2
-rw-r--r--priv/static/packs/locales/glitch/zh-TW.js2
-rw-r--r--priv/static/packs/locales/glitch/zh-TW.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/ar.js2
-rw-r--r--priv/static/packs/locales/vanilla/ar.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/ast.js2
-rw-r--r--priv/static/packs/locales/vanilla/ast.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/bg.js2
-rw-r--r--priv/static/packs/locales/vanilla/bg.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/bn.js2
-rw-r--r--priv/static/packs/locales/vanilla/bn.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/br.js2
-rw-r--r--priv/static/packs/locales/vanilla/br.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/ca.js2
-rw-r--r--priv/static/packs/locales/vanilla/ca.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/co.js2
-rw-r--r--priv/static/packs/locales/vanilla/co.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/cs.js2
-rw-r--r--priv/static/packs/locales/vanilla/cs.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/cy.js2
-rw-r--r--priv/static/packs/locales/vanilla/cy.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/da.js2
-rw-r--r--priv/static/packs/locales/vanilla/da.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/de.js2
-rw-r--r--priv/static/packs/locales/vanilla/de.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/el.js2
-rw-r--r--priv/static/packs/locales/vanilla/el.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/en.js2
-rw-r--r--priv/static/packs/locales/vanilla/en.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/eo.js2
-rw-r--r--priv/static/packs/locales/vanilla/eo.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/es-AR.js2
-rw-r--r--priv/static/packs/locales/vanilla/es-AR.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/es.js2
-rw-r--r--priv/static/packs/locales/vanilla/es.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/et.js2
-rw-r--r--priv/static/packs/locales/vanilla/et.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/eu.js2
-rw-r--r--priv/static/packs/locales/vanilla/eu.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/fa.js2
-rw-r--r--priv/static/packs/locales/vanilla/fa.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/fi.js2
-rw-r--r--priv/static/packs/locales/vanilla/fi.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/fr.js2
-rw-r--r--priv/static/packs/locales/vanilla/fr.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/ga.js2
-rw-r--r--priv/static/packs/locales/vanilla/ga.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/gl.js2
-rw-r--r--priv/static/packs/locales/vanilla/gl.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/he.js2
-rw-r--r--priv/static/packs/locales/vanilla/he.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/hi.js2
-rw-r--r--priv/static/packs/locales/vanilla/hi.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/hr.js2
-rw-r--r--priv/static/packs/locales/vanilla/hr.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/hu.js2
-rw-r--r--priv/static/packs/locales/vanilla/hu.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/hy.js2
-rw-r--r--priv/static/packs/locales/vanilla/hy.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/id.js2
-rw-r--r--priv/static/packs/locales/vanilla/id.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/io.js2
-rw-r--r--priv/static/packs/locales/vanilla/io.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/is.js2
-rw-r--r--priv/static/packs/locales/vanilla/is.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/it.js2
-rw-r--r--priv/static/packs/locales/vanilla/it.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/ja.js2
-rw-r--r--priv/static/packs/locales/vanilla/ja.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/ka.js2
-rw-r--r--priv/static/packs/locales/vanilla/ka.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/kab.js2
-rw-r--r--priv/static/packs/locales/vanilla/kab.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/kk.js2
-rw-r--r--priv/static/packs/locales/vanilla/kk.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/kn.js2
-rw-r--r--priv/static/packs/locales/vanilla/kn.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/ko.js2
-rw-r--r--priv/static/packs/locales/vanilla/ko.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/lt.js2
-rw-r--r--priv/static/packs/locales/vanilla/lt.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/lv.js2
-rw-r--r--priv/static/packs/locales/vanilla/lv.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/mk.js2
-rw-r--r--priv/static/packs/locales/vanilla/mk.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/ml.js2
-rw-r--r--priv/static/packs/locales/vanilla/ml.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/mr.js2
-rw-r--r--priv/static/packs/locales/vanilla/mr.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/ms.js2
-rw-r--r--priv/static/packs/locales/vanilla/ms.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/nl.js2
-rw-r--r--priv/static/packs/locales/vanilla/nl.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/nn.js2
-rw-r--r--priv/static/packs/locales/vanilla/nn.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/no.js2
-rw-r--r--priv/static/packs/locales/vanilla/no.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/oc.js2
-rw-r--r--priv/static/packs/locales/vanilla/oc.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/pl.js2
-rw-r--r--priv/static/packs/locales/vanilla/pl.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/pt-BR.js2
-rw-r--r--priv/static/packs/locales/vanilla/pt-BR.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/pt-PT.js2
-rw-r--r--priv/static/packs/locales/vanilla/pt-PT.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/ro.js2
-rw-r--r--priv/static/packs/locales/vanilla/ro.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/ru.js2
-rw-r--r--priv/static/packs/locales/vanilla/ru.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/sk.js2
-rw-r--r--priv/static/packs/locales/vanilla/sk.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/sl.js2
-rw-r--r--priv/static/packs/locales/vanilla/sl.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/sq.js2
-rw-r--r--priv/static/packs/locales/vanilla/sq.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/sr-Latn.js2
-rw-r--r--priv/static/packs/locales/vanilla/sr-Latn.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/sr.js2
-rw-r--r--priv/static/packs/locales/vanilla/sr.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/sv.js2
-rw-r--r--priv/static/packs/locales/vanilla/sv.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/ta.js2
-rw-r--r--priv/static/packs/locales/vanilla/ta.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/te.js2
-rw-r--r--priv/static/packs/locales/vanilla/te.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/th.js2
-rw-r--r--priv/static/packs/locales/vanilla/th.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/tr.js2
-rw-r--r--priv/static/packs/locales/vanilla/tr.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/uk.js2
-rw-r--r--priv/static/packs/locales/vanilla/uk.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/ur.js2
-rw-r--r--priv/static/packs/locales/vanilla/ur.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/vi.js2
-rw-r--r--priv/static/packs/locales/vanilla/vi.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/zh-CN.js2
-rw-r--r--priv/static/packs/locales/vanilla/zh-CN.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/zh-HK.js2
-rw-r--r--priv/static/packs/locales/vanilla/zh-HK.js.map2
-rw-r--r--priv/static/packs/locales/vanilla/zh-TW.js2
-rw-r--r--priv/static/packs/locales/vanilla/zh-TW.js.map2
-rw-r--r--priv/static/packs/modals/block_modal.js2
-rw-r--r--priv/static/packs/modals/block_modal.js.map2
-rw-r--r--priv/static/packs/modals/embed_modal.js2
-rw-r--r--priv/static/packs/modals/embed_modal.js.map2
-rw-r--r--priv/static/packs/modals/mute_modal.js2
-rw-r--r--priv/static/packs/modals/mute_modal.js.map2
-rw-r--r--priv/static/packs/modals/report_modal.js2
-rw-r--r--priv/static/packs/modals/report_modal.js.map2
-rw-r--r--priv/static/packs/skins/glitch/contrast/common.css2
-rw-r--r--priv/static/packs/skins/glitch/contrast/common.css.map2
-rw-r--r--priv/static/packs/skins/glitch/contrast/common.js2
-rw-r--r--priv/static/packs/skins/glitch/mastodon-light/common.css2
-rw-r--r--priv/static/packs/skins/glitch/mastodon-light/common.css.map2
-rw-r--r--priv/static/packs/skins/glitch/mastodon-light/common.js2
-rw-r--r--priv/static/packs/skins/vanilla/contrast/common.css2
-rw-r--r--priv/static/packs/skins/vanilla/contrast/common.css.map2
-rw-r--r--priv/static/packs/skins/vanilla/contrast/common.js2
-rw-r--r--priv/static/packs/skins/vanilla/mastodon-light/common.css2
-rw-r--r--priv/static/packs/skins/vanilla/mastodon-light/common.css.map2
-rw-r--r--priv/static/packs/skins/vanilla/mastodon-light/common.js2
-rw-r--r--priv/static/packs/skins/vanilla/win95/common.css2
-rw-r--r--priv/static/packs/skins/vanilla/win95/common.css.map2
-rw-r--r--priv/static/packs/skins/vanilla/win95/common.js2
-rw-r--r--priv/static/packs/tesseract.js4
-rw-r--r--priv/static/packs/tesseract.js.LICENSE.txt (renamed from priv/static/packs/tesseract.js.LICENSE)0
-rw-r--r--priv/static/packs/tesseract.js.map2
-rw-r--r--priv/static/schemas/litepub-0.1.jsonld2
-rw-r--r--priv/static/static-fe/static-fe.css1
-rw-r--r--priv/static/static/config.json33
-rw-r--r--priv/static/static/css/2.0778a6a864a1307a6c41.css9
-rw-r--r--priv/static/static/css/2.0778a6a864a1307a6c41.css.map1
-rw-r--r--priv/static/static/css/3.b2603a50868c68a1c192.css (renamed from priv/static/static/css/vendors~app.b2603a50868c68a1c192.css)2
-rw-r--r--priv/static/static/css/3.b2603a50868c68a1c192.css.map1
-rw-r--r--priv/static/static/css/app.1055039ce3f2fe4dd110.css108
-rw-r--r--priv/static/static/css/app.1055039ce3f2fe4dd110.css.map1
-rw-r--r--priv/static/static/css/app.77b1644622e3bae24b6b.css246
-rw-r--r--priv/static/static/css/app.77b1644622e3bae24b6b.css.map1
-rw-r--r--priv/static/static/css/vendors~app.b2603a50868c68a1c192.css.map1
-rw-r--r--priv/static/static/font/fontello.1589314090288.woffbin13988 -> 0 bytes
-rw-r--r--priv/static/static/font/fontello.1589314090288.woff2bin11816 -> 0 bytes
-rw-r--r--priv/static/static/font/fontello.1598361006087.eot (renamed from priv/static/static/font/fontello.1589314090288.ttf)bin22808 -> 24524 bytes
-rw-r--r--priv/static/static/font/fontello.1598361006087.svg (renamed from priv/static/static/font/fontello.1589314090288.svg)14
-rw-r--r--priv/static/static/font/fontello.1598361006087.ttf (renamed from priv/static/static/font/fontello.1589314090288.eot)bin22976 -> 24356 bytes
-rw-r--r--priv/static/static/font/fontello.1598361006087.woffbin0 -> 14912 bytes
-rw-r--r--priv/static/static/font/fontello.1598361006087.woff2bin0 -> 12536 bytes
-rw-r--r--priv/static/static/fontello.1598361006087.css (renamed from priv/static/static/fontello.1589314090288.css)26
-rw-r--r--[-rwxr-xr-x]priv/static/static/fontello.json42
-rw-r--r--priv/static/static/js/10.1c5cd5fbe554eca63dfe.js2
-rw-r--r--priv/static/static/js/10.1c5cd5fbe554eca63dfe.js.map1
-rw-r--r--priv/static/static/js/11.708cc2513c53879a92cc.js2
-rw-r--r--priv/static/static/js/11.708cc2513c53879a92cc.js.map1
-rw-r--r--priv/static/static/js/12.6619e0b2f854637e76d4.js2
-rw-r--r--priv/static/static/js/12.6619e0b2f854637e76d4.js.map1
-rw-r--r--priv/static/static/js/13.c843797f3e374f0e3e1a.js2
-rw-r--r--priv/static/static/js/13.c843797f3e374f0e3e1a.js.map1
-rw-r--r--priv/static/static/js/14.71f8caca49093a99e871.js2
-rw-r--r--priv/static/static/js/14.71f8caca49093a99e871.js.map1
-rw-r--r--priv/static/static/js/15.19866e6a366ccf982284.js2
-rw-r--r--priv/static/static/js/15.19866e6a366ccf982284.js.map1
-rw-r--r--priv/static/static/js/16.38a984effd54736f6a2c.js2
-rw-r--r--priv/static/static/js/16.38a984effd54736f6a2c.js.map1
-rw-r--r--priv/static/static/js/17.9c25507194320db2e85b.js2
-rw-r--r--priv/static/static/js/17.9c25507194320db2e85b.js.map1
-rw-r--r--priv/static/static/js/18.b29eedabe76445fe94b8.js2
-rw-r--r--priv/static/static/js/18.b29eedabe76445fe94b8.js.map1
-rw-r--r--priv/static/static/js/19.ed1cd5db596618779f03.js2
-rw-r--r--priv/static/static/js/19.ed1cd5db596618779f03.js.map1
-rw-r--r--priv/static/static/js/2.f9a5c4aba770b3f9f9e0.js2
-rw-r--r--priv/static/static/js/2.f9a5c4aba770b3f9f9e0.js.map1
-rw-r--r--priv/static/static/js/2.fb3f90b584362209a143.js2
-rw-r--r--priv/static/static/js/2.fb3f90b584362209a143.js.map1
-rw-r--r--priv/static/static/js/20.6d311b830d8ac672729f.js2
-rw-r--r--priv/static/static/js/20.6d311b830d8ac672729f.js.map1
-rw-r--r--priv/static/static/js/21.ce4cda179d888ca6bc2a.js2
-rw-r--r--priv/static/static/js/21.ce4cda179d888ca6bc2a.js.map1
-rw-r--r--priv/static/static/js/22.2ea93c6cc569ef0256ab.js2
-rw-r--r--priv/static/static/js/22.2ea93c6cc569ef0256ab.js.map1
-rw-r--r--priv/static/static/js/23.2c5f0fd2f2acd04592e8.js2
-rw-r--r--priv/static/static/js/23.2c5f0fd2f2acd04592e8.js.map1
-rw-r--r--priv/static/static/js/24.35eb55a657b5485f8491.js2
-rw-r--r--priv/static/static/js/24.35eb55a657b5485f8491.js.map1
-rw-r--r--priv/static/static/js/25.365514e44606a895ab50.js2
-rw-r--r--priv/static/static/js/25.365514e44606a895ab50.js.map1
-rw-r--r--priv/static/static/js/26.cf13231d524e5ca3b3e6.js2
-rw-r--r--priv/static/static/js/26.cf13231d524e5ca3b3e6.js.map1
-rw-r--r--priv/static/static/js/27.fca8d4f6e444bd14f376.js2
-rw-r--r--priv/static/static/js/27.fca8d4f6e444bd14f376.js.map1
-rw-r--r--priv/static/static/js/28.9eb3e783aeba24c84f0a.js2
-rw-r--r--priv/static/static/js/28.9eb3e783aeba24c84f0a.js.map1
-rw-r--r--priv/static/static/js/29.0b69359f0fe5c0785746.js2
-rw-r--r--priv/static/static/js/29.0b69359f0fe5c0785746.js.map1
-rw-r--r--priv/static/static/js/3.7d21accf4e5bd07e3ebf.js21
-rw-r--r--priv/static/static/js/3.7d21accf4e5bd07e3ebf.js.map1
-rw-r--r--priv/static/static/js/30.a9377272337674f2dd05.js2
-rw-r--r--priv/static/static/js/30.a9377272337674f2dd05.js.map1
-rw-r--r--priv/static/static/js/4.5719922a4e807145346d.js2
-rw-r--r--priv/static/static/js/4.5719922a4e807145346d.js.map1
-rw-r--r--priv/static/static/js/5.cf05c5ddbdbac890ae35.js2
-rw-r--r--priv/static/static/js/5.cf05c5ddbdbac890ae35.js.map1
-rw-r--r--priv/static/static/js/6.ecfd3302a692de148391.js2
-rw-r--r--priv/static/static/js/6.ecfd3302a692de148391.js.map1
-rw-r--r--priv/static/static/js/7.dd44c3d58fb9dced093d.js2
-rw-r--r--priv/static/static/js/7.dd44c3d58fb9dced093d.js.map1
-rw-r--r--priv/static/static/js/8.5f48d6f0cbed548baf0f.js2
-rw-r--r--priv/static/static/js/8.5f48d6f0cbed548baf0f.js.map1
-rw-r--r--priv/static/static/js/9.a95fcd286ba2c9050c4d.js2
-rw-r--r--priv/static/static/js/9.a95fcd286ba2c9050c4d.js.map1
-rw-r--r--priv/static/static/js/app.154c25316542278028a6.js2
-rw-r--r--priv/static/static/js/app.154c25316542278028a6.js.map1
-rw-r--r--priv/static/static/js/app.82334f8362acc4bbcb6f.js2
-rw-r--r--priv/static/static/js/app.82334f8362acc4bbcb6f.js.map1
-rw-r--r--priv/static/static/js/vendors~app.a516afd698489b59a809.js68
-rw-r--r--priv/static/static/js/vendors~app.a516afd698489b59a809.js.map1
-rw-r--r--priv/static/static/js/vendors~app.bc5812c087f5dbcb914d.js49
-rw-r--r--priv/static/static/js/vendors~app.bc5812c087f5dbcb914d.js.map1
-rw-r--r--priv/static/static/terms-of-service.html7
-rw-r--r--priv/static/static/themes/redmond-xx-se.json4
-rw-r--r--priv/static/static/themes/redmond-xx.json4
-rw-r--r--priv/static/static/themes/redmond-xxi.json4
-rw-r--r--priv/static/sw-pleroma.js25
-rw-r--r--priv/static/sw-pleroma.js.map2
-rw-r--r--priv/static/sw.js13
-rw-r--r--restarter/lib/pleroma.ex4
-rw-r--r--test/activity/ir/topics_test.exs2
-rw-r--r--test/activity_expiration_test.exs9
-rw-r--r--test/activity_test.exs17
-rw-r--r--test/application_requirements_test.exs146
-rw-r--r--test/bbs/handler_test.exs6
-rw-r--r--test/bookmark_test.exs6
-rw-r--r--test/captcha_test.exs16
-rw-r--r--test/chat/message_reference_test.exs29
-rw-r--r--test/chat_test.exs61
-rw-r--r--test/config/config_db_test.exs599
-rw-r--r--test/config/deprecation_warnings_test.exs65
-rw-r--r--test/config/holder_test.exs5
-rw-r--r--test/config/transfer_task_test.exs125
-rw-r--r--test/config_test.exs46
-rw-r--r--test/conversation/participation_test.exs72
-rw-r--r--test/conversation_test.exs26
-rw-r--r--test/docs/generator_test.exs12
-rw-r--r--test/emails/admin_email_test.exs22
-rw-r--r--test/emails/mailer_test.exs8
-rw-r--r--test/emoji/formatter_test.exs24
-rw-r--r--test/filter_test.exs67
-rw-r--r--test/fixtures/DSCN0010.jpgbin0 -> 161713 bytes
-rw-r--r--test/fixtures/config/temp.secret.exs4
-rw-r--r--test/fixtures/create-chat-message.json31
-rw-r--r--test/fixtures/emoji/packs/blank.png.zipbin0 -> 284 bytes
-rw-r--r--test/fixtures/emoji/packs/default-manifest.json10
-rw-r--r--test/fixtures/emoji/packs/finmoji.json3
-rw-r--r--test/fixtures/emoji/packs/manifest.json10
-rw-r--r--test/fixtures/fetch_mocks/104410921027210069.json72
-rw-r--r--test/fixtures/fetch_mocks/9wTkLEnuq47B25EehM.json59
-rw-r--r--test/fixtures/fetch_mocks/eal.json43
-rw-r--r--test/fixtures/fetch_mocks/tuxcrafting.json59
-rw-r--r--test/fixtures/kroeg-announce-with-inline-actor.json89
-rw-r--r--test/fixtures/mastodon-note-object.json50
-rw-r--r--test/fixtures/mastodon-question-activity.json1
-rw-r--r--test/fixtures/preload_static/instance/panel.html1
-rw-r--r--test/fixtures/tesla_mock/admin@mastdon.example.org.json3
-rw-r--r--test/fixtures/tesla_mock/baptiste.gelex.xyz-article.json228
-rw-r--r--test/fixtures/tesla_mock/craigmaloney.json112
-rw-r--r--test/fixtures/tesla_mock/dist/test.txt1
-rw-r--r--test/fixtures/tesla_mock/framatube.org-video.json1
-rw-r--r--test/fixtures/tesla_mock/frontend.zipbin0 -> 186 bytes
-rw-r--r--test/fixtures/tesla_mock/frontend_dist.zipbin0 -> 334 bytes
-rw-r--r--test/fixtures/tesla_mock/funkwhale_create_audio.json58
-rw-r--r--test/fixtures/tesla_mock/https___framatube.org_accounts_framasoft.json1
-rw-r--r--test/fixtures/tesla_mock/https___osada.macgirvin.com.html301
-rw-r--r--test/fixtures/tesla_mock/peertube-social.json234
-rw-r--r--test/fixtures/tesla_mock/peertube.moe-vid.json188
-rw-r--r--test/fixtures/tesla_mock/poll_attachment.json99
-rw-r--r--test/fixtures/users_mock/localhost.json41
-rw-r--r--test/fixtures/warnings/otp_version/21.11
-rw-r--r--test/fixtures/warnings/otp_version/22.11
-rw-r--r--test/fixtures/warnings/otp_version/22.41
-rw-r--r--test/fixtures/warnings/otp_version/23.01
-rw-r--r--test/formatter_test.exs57
-rw-r--r--test/gun/conneciton_pool_test.exs101
-rw-r--r--test/html_test.exs26
-rw-r--r--test/http/adapter_helper/gun_test.exs84
-rw-r--r--test/http/adapter_helper/hackney_test.exs35
-rw-r--r--test/http/adapter_helper_test.exs28
-rw-r--r--test/http/ex_aws_test.exs54
-rw-r--r--test/http/request_builder_test.exs47
-rw-r--r--test/http/tzdata_test.exs35
-rw-r--r--test/http_test.exs19
-rw-r--r--test/instance_static/add/shortcode.pngbin0 -> 95 bytes
-rw-r--r--test/instance_static/emoji/pack_bad_sha/blank.pngbin0 -> 95 bytes
-rw-r--r--test/instance_static/emoji/pack_bad_sha/pack.json13
-rw-r--r--test/instance_static/emoji/pack_bad_sha/pack_bad_sha.zipbin0 -> 256 bytes
-rw-r--r--test/instance_static/emoji/test_pack/blank2.pngbin0 -> 95 bytes
-rw-r--r--test/instance_static/emoji/test_pack/pack.json15
-rw-r--r--test/instance_static/emoji/test_pack_nonshared/nonshared.zipbin256 -> 548 bytes
-rw-r--r--test/instance_static/emoji/test_pack_nonshared/pack.json7
-rw-r--r--test/instance_static/local_pack/files.json3
-rw-r--r--test/instance_static/local_pack/manifest.json10
-rw-r--r--test/integration/mastodon_websocket_test.exs9
-rw-r--r--test/marker_test.exs29
-rw-r--r--test/mfa/backup_codes_test.exs11
-rw-r--r--test/mfa/totp_test.exs17
-rw-r--r--test/mfa_test.exs52
-rw-r--r--test/migration_helper/notification_backfill_test.exs56
-rw-r--r--test/migrations/20200716195806_autolinker_to_linkify_test.exs68
-rw-r--r--test/migrations/20200722185515_fix_malformed_formatter_config_test.exs66
-rw-r--r--test/migrations/20200724133313_move_welcome_settings_test.exs140
-rw-r--r--test/migrations/20200802170532_fix_legacy_tags_test.exs24
-rw-r--r--test/notification_test.exs432
-rw-r--r--test/object/fetcher_test.exs52
-rw-r--r--test/object_test.exs7
-rw-r--r--test/otp_version_test.exs42
-rw-r--r--test/pagination_test.exs26
-rw-r--r--test/plugs/admin_secret_authentication_plug_test.exs15
-rw-r--r--test/plugs/authentication_plug_test.exs44
-rw-r--r--test/plugs/ensure_authenticated_plug_test.exs79
-rw-r--r--test/plugs/ensure_public_or_authenticated_plug_test.exs6
-rw-r--r--test/plugs/frontend_static_test.exs57
-rw-r--r--test/plugs/http_security_plug_test.exs90
-rw-r--r--test/plugs/instance_static_test.exs30
-rw-r--r--test/plugs/oauth_plug_test.exs2
-rw-r--r--test/plugs/oauth_scopes_plug_test.exs38
-rw-r--r--test/plugs/rate_limiter_test.exs67
-rw-r--r--test/plugs/remote_ip_test.exs3
-rw-r--r--test/plugs/user_enabled_plug_test.exs2
-rw-r--r--test/plugs/user_is_admin_plug_test.exs118
-rw-r--r--test/repo_test.exs34
-rw-r--r--test/report_note_test.exs16
-rw-r--r--test/reverse_proxy/reverse_proxy_test.exs (renamed from test/reverse_proxy_test.exs)117
-rw-r--r--test/scheduled_activity_test.exs2
-rw-r--r--test/signature_test.exs13
-rw-r--r--test/stats_test.exs79
-rw-r--r--test/support/api_spec_helpers.ex57
-rw-r--r--test/support/builders/activity_builder.ex10
-rw-r--r--test/support/builders/user_builder.ex3
-rw-r--r--test/support/captcha_mock.ex9
-rw-r--r--test/support/cluster.ex2
-rw-r--r--test/support/conn_case.ex91
-rw-r--r--test/support/data_case.ex6
-rw-r--r--test/support/factory.ex71
-rw-r--r--test/support/helpers.ex55
-rw-r--r--test/support/http_request_mock.ex150
-rw-r--r--test/support/oban_helpers.ex2
-rw-r--r--test/tasks/app_test.exs65
-rw-r--r--test/tasks/config_test.exs56
-rw-r--r--test/tasks/count_statuses_test.exs6
-rw-r--r--test/tasks/database_test.exs47
-rw-r--r--test/tasks/digest_test.exs4
-rw-r--r--test/tasks/email_test.exs2
-rw-r--r--test/tasks/emoji_test.exs239
-rw-r--r--test/tasks/frontend_test.exs78
-rw-r--r--test/tasks/instance_test.exs3
-rw-r--r--test/tasks/refresh_counter_cache_test.exs16
-rw-r--r--test/tasks/relay_test.exs26
-rw-r--r--test/tasks/robots_txt_test.exs2
-rw-r--r--test/tasks/user_test.exs123
-rw-r--r--test/test_helper.exs3
-rw-r--r--test/upload/filter/anonymize_filename_test.exs4
-rw-r--r--test/upload/filter/exiftool_test.exs33
-rw-r--r--test/upload/filter/mogrify_test.exs8
-rw-r--r--test/upload/filter_test.exs2
-rw-r--r--test/upload_test.exs18
-rw-r--r--test/uploaders/local_test.exs2
-rw-r--r--test/uploaders/s3_test.exs13
-rw-r--r--test/user/notification_setting_test.exs4
-rw-r--r--test/user/welcome_chat_massage_test.exs35
-rw-r--r--test/user/welcome_email_test.exs61
-rw-r--r--test/user/welcome_message_test.exs34
-rw-r--r--test/user_invite_token_test.exs4
-rw-r--r--test/user_search_test.exs45
-rw-r--r--test/user_test.exs510
-rw-r--r--test/web/activity_pub/activity_pub_controller_test.exs471
-rw-r--r--test/web/activity_pub/activity_pub_test.exs1768
-rw-r--r--test/web/activity_pub/mrf/activity_expiration_policy_test.exs84
-rw-r--r--test/web/activity_pub/mrf/anti_followbot_policy_test.exs6
-rw-r--r--test/web/activity_pub/mrf/anti_link_spam_policy_test.exs27
-rw-r--r--test/web/activity_pub/mrf/ensure_re_prepended_test.exs12
-rw-r--r--test/web/activity_pub/mrf/hellthread_policy_test.exs23
-rw-r--r--test/web/activity_pub/mrf/keyword_policy_test.exs14
-rw-r--r--test/web/activity_pub/mrf/mention_policy_test.exs8
-rw-r--r--test/web/activity_pub/mrf/mrf_test.exs4
-rw-r--r--test/web/activity_pub/mrf/no_placeholder_text_policy_test.exs2
-rw-r--r--test/web/activity_pub/mrf/normalize_markup_test.exs2
-rw-r--r--test/web/activity_pub/mrf/object_age_policy_test.exs55
-rw-r--r--test/web/activity_pub/mrf/reject_non_public_test.exs8
-rw-r--r--test/web/activity_pub/mrf/simple_policy_test.exs167
-rw-r--r--test/web/activity_pub/mrf/steal_emoji_policy_test.exs68
-rw-r--r--test/web/activity_pub/mrf/subchain_policy_test.exs3
-rw-r--r--test/web/activity_pub/mrf/tag_policy_test.exs6
-rw-r--r--test/web/activity_pub/mrf/user_allowlist_policy_test.exs4
-rw-r--r--test/web/activity_pub/mrf/vocabulary_policy_test.exs12
-rw-r--r--test/web/activity_pub/object_validators/accept_validation_test.exs56
-rw-r--r--test/web/activity_pub/object_validators/announce_validation_test.exs106
-rw-r--r--test/web/activity_pub/object_validators/attachment_validator_test.exs74
-rw-r--r--test/web/activity_pub/object_validators/block_validation_test.exs39
-rw-r--r--test/web/activity_pub/object_validators/chat_validation_test.exs211
-rw-r--r--test/web/activity_pub/object_validators/delete_validation_test.exs106
-rw-r--r--test/web/activity_pub/object_validators/emoji_react_validation_test.exs53
-rw-r--r--test/web/activity_pub/object_validators/follow_validation_test.exs26
-rw-r--r--test/web/activity_pub/object_validators/like_validation_test.exs113
-rw-r--r--test/web/activity_pub/object_validators/note_validator_test.exs35
-rw-r--r--test/web/activity_pub/object_validators/reject_validation_test.exs56
-rw-r--r--test/web/activity_pub/object_validators/types/date_time_test.exs32
-rw-r--r--test/web/activity_pub/object_validators/types/object_id_test.exs41
-rw-r--r--test/web/activity_pub/object_validators/types/recipients_test.exs27
-rw-r--r--test/web/activity_pub/object_validators/types/safe_text_test.exs30
-rw-r--r--test/web/activity_pub/object_validators/undo_validation_test.exs53
-rw-r--r--test/web/activity_pub/object_validators/update_validation_test.exs44
-rw-r--r--test/web/activity_pub/pipeline_test.exs179
-rw-r--r--test/web/activity_pub/publisher_test.exs88
-rw-r--r--test/web/activity_pub/relay_test.exs29
-rw-r--r--test/web/activity_pub/side_effects_test.exs639
-rw-r--r--test/web/activity_pub/transmogrifier/accept_handling_test.exs91
-rw-r--r--test/web/activity_pub/transmogrifier/announce_handling_test.exs172
-rw-r--r--test/web/activity_pub/transmogrifier/answer_handling_test.exs78
-rw-r--r--test/web/activity_pub/transmogrifier/audio_handling_test.exs83
-rw-r--r--test/web/activity_pub/transmogrifier/block_handling_test.exs63
-rw-r--r--test/web/activity_pub/transmogrifier/chat_message_test.exs171
-rw-r--r--test/web/activity_pub/transmogrifier/delete_handling_test.exs114
-rw-r--r--test/web/activity_pub/transmogrifier/emoji_react_handling_test.exs61
-rw-r--r--test/web/activity_pub/transmogrifier/event_handling_test.exs40
-rw-r--r--test/web/activity_pub/transmogrifier/follow_handling_test.exs48
-rw-r--r--test/web/activity_pub/transmogrifier/like_handling_test.exs78
-rw-r--r--test/web/activity_pub/transmogrifier/question_handling_test.exs125
-rw-r--r--test/web/activity_pub/transmogrifier/reject_handling_test.exs67
-rw-r--r--test/web/activity_pub/transmogrifier/undo_handling_test.exs185
-rw-r--r--test/web/activity_pub/transmogrifier/user_update_handling_test.exs159
-rw-r--r--test/web/activity_pub/transmogrifier_test.exs1259
-rw-r--r--test/web/activity_pub/utils_test.exs89
-rw-r--r--test/web/activity_pub/views/object_view_test.exs10
-rw-r--r--test/web/activity_pub/views/user_view_test.exs23
-rw-r--r--test/web/activity_pub/visibilty_test.exs12
-rw-r--r--test/web/admin_api/admin_api_controller_test.exs3727
-rw-r--r--test/web/admin_api/controllers/admin_api_controller_test.exs1979
-rw-r--r--test/web/admin_api/controllers/config_controller_test.exs1465
-rw-r--r--test/web/admin_api/controllers/invite_controller_test.exs281
-rw-r--r--test/web/admin_api/controllers/media_proxy_cache_controller_test.exs167
-rw-r--r--test/web/admin_api/controllers/oauth_app_controller_test.exs220
-rw-r--r--test/web/admin_api/controllers/relay_controller_test.exs99
-rw-r--r--test/web/admin_api/controllers/report_controller_test.exs372
-rw-r--r--test/web/admin_api/controllers/status_controller_test.exs202
-rw-r--r--test/web/admin_api/search_test.exs11
-rw-r--r--test/web/admin_api/views/report_view_test.exs47
-rw-r--r--test/web/api_spec/schema_examples_test.exs43
-rw-r--r--test/web/auth/auth_test_controller_test.exs242
-rw-r--r--test/web/auth/basic_auth_test.exs2
-rw-r--r--test/web/auth/oauth_test_controller_test.exs49
-rw-r--r--test/web/auth/pleroma_authenticator_test.exs48
-rw-r--r--test/web/auth/totp_authenticator_test.exs51
-rw-r--r--test/web/chat_channel_test.exs2
-rw-r--r--test/web/common_api/common_api_test.exs627
-rw-r--r--test/web/common_api/common_api_utils_test.exs103
-rw-r--r--test/web/fallback_test.exs68
-rw-r--r--test/web/federator_test.exs28
-rw-r--r--test/web/feed/tag_controller_test.exs70
-rw-r--r--test/web/feed/user_controller_test.exs362
-rw-r--r--test/web/instances/instance_test.exs4
-rw-r--r--test/web/instances/instances_test.exs4
-rw-r--r--test/web/masto_fe_controller_test.exs4
-rw-r--r--test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs271
-rw-r--r--test/web/mastodon_api/controllers/account_controller_test.exs1146
-rw-r--r--test/web/mastodon_api/controllers/app_controller_test.exs8
-rw-r--r--test/web/mastodon_api/controllers/conversation_controller_test.exs221
-rw-r--r--test/web/mastodon_api/controllers/custom_emoji_controller_test.exs9
-rw-r--r--test/web/mastodon_api/controllers/domain_block_controller_test.exs60
-rw-r--r--test/web/mastodon_api/controllers/filter_controller_test.exs51
-rw-r--r--test/web/mastodon_api/controllers/follow_request_controller_test.exs14
-rw-r--r--test/web/mastodon_api/controllers/instance_controller_test.exs20
-rw-r--r--test/web/mastodon_api/controllers/list_controller_test.exs60
-rw-r--r--test/web/mastodon_api/controllers/marker_controller_test.exs25
-rw-r--r--test/web/mastodon_api/controllers/media_controller_test.exs90
-rw-r--r--test/web/mastodon_api/controllers/notification_controller_test.exs388
-rw-r--r--test/web/mastodon_api/controllers/poll_controller_test.exs76
-rw-r--r--test/web/mastodon_api/controllers/report_controller_test.exs26
-rw-r--r--test/web/mastodon_api/controllers/scheduled_activity_controller_test.exs36
-rw-r--r--test/web/mastodon_api/controllers/search_controller_test.exs215
-rw-r--r--test/web/mastodon_api/controllers/status_controller_test.exs756
-rw-r--r--test/web/mastodon_api/controllers/subscription_controller_test.exs39
-rw-r--r--test/web/mastodon_api/controllers/suggestion_controller_test.exs2
-rw-r--r--test/web/mastodon_api/controllers/timeline_controller_test.exs421
-rw-r--r--test/web/mastodon_api/mastodon_api_controller_test.exs33
-rw-r--r--test/web/mastodon_api/mastodon_api_test.exs7
-rw-r--r--test/web/mastodon_api/views/account_view_test.exs345
-rw-r--r--test/web/mastodon_api/views/conversation_view_test.exs11
-rw-r--r--test/web/mastodon_api/views/marker_view_test.exs8
-rw-r--r--test/web/mastodon_api/views/notification_view_test.exs141
-rw-r--r--test/web/mastodon_api/views/poll_view_test.exs81
-rw-r--r--test/web/mastodon_api/views/scheduled_activity_view_test.exs4
-rw-r--r--test/web/mastodon_api/views/status_view_test.exs156
-rw-r--r--test/web/mastodon_api/views/subscription_view_test.exs (renamed from test/web/mastodon_api/views/push_subscription_view_test.exs)6
-rw-r--r--test/web/media_proxy/invalidation_test.exs64
-rw-r--r--test/web/media_proxy/invalidations/http_test.exs39
-rw-r--r--test/web/media_proxy/invalidations/script_test.exs26
-rw-r--r--test/web/media_proxy/media_proxy_controller_test.exs137
-rw-r--r--test/web/media_proxy/media_proxy_test.exs156
-rw-r--r--test/web/metadata/metadata_test.exs25
-rw-r--r--test/web/metadata/opengraph_test.exs2
-rw-r--r--test/web/metadata/rel_me_test.exs5
-rw-r--r--test/web/metadata/restrict_indexing_test.exs21
-rw-r--r--test/web/metadata/twitter_card_test.exs8
-rw-r--r--test/web/mongooseim/mongoose_im_controller_test.exs24
-rw-r--r--test/web/node_info_test.exs87
-rw-r--r--test/web/oauth/app_test.exs11
-rw-r--r--test/web/oauth/ldap_authorization_test.exs61
-rw-r--r--test/web/oauth/mfa_controller_test.exs306
-rw-r--r--test/web/oauth/oauth_controller_test.exs130
-rw-r--r--test/web/ostatus/ostatus_controller_test.exs132
-rw-r--r--test/web/pleroma_api/controllers/account_controller_test.exs178
-rw-r--r--test/web/pleroma_api/controllers/chat_controller_test.exs373
-rw-r--r--test/web/pleroma_api/controllers/conversation_controller_test.exs136
-rw-r--r--test/web/pleroma_api/controllers/emoji_api_controller_test.exs466
-rw-r--r--test/web/pleroma_api/controllers/emoji_pack_controller_test.exs861
-rw-r--r--test/web/pleroma_api/controllers/emoji_reaction_controller_test.exs149
-rw-r--r--test/web/pleroma_api/controllers/mascot_controller_test.exs25
-rw-r--r--test/web/pleroma_api/controllers/notification_controller_test.exs68
-rw-r--r--test/web/pleroma_api/controllers/pleroma_api_controller_test.exs279
-rw-r--r--test/web/pleroma_api/controllers/scrobble_controller_test.exs26
-rw-r--r--test/web/pleroma_api/controllers/two_factor_authentication_controller_test.exs260
-rw-r--r--test/web/pleroma_api/views/chat/message_reference_view_test.exs72
-rw-r--r--test/web/pleroma_api/views/chat_view_test.exs49
-rw-r--r--test/web/pleroma_api/views/scrobble_view_test.exs20
-rw-r--r--test/web/plugs/federating_plug_test.exs2
-rw-r--r--test/web/plugs/plug_test.exs91
-rw-r--r--test/web/preload/instance_test.exs48
-rw-r--r--test/web/preload/timeline_test.exs56
-rw-r--r--test/web/preload/user_test.exs33
-rw-r--r--test/web/push/impl_test.exs164
-rw-r--r--test/web/rel_me_test.exs2
-rw-r--r--test/web/rich_media/helpers_test.exs30
-rw-r--r--test/web/rich_media/parsers/twitter_card_test.exs130
-rw-r--r--test/web/static_fe/static_fe_controller_test.exs171
-rw-r--r--test/web/streamer/ping_test.exs36
-rw-r--r--test/web/streamer/state_test.exs54
-rw-r--r--test/web/streamer/streamer_test.exs718
-rw-r--r--test/web/twitter_api/password_controller_test.exs2
-rw-r--r--test/web/twitter_api/remote_follow_controller_test.exs125
-rw-r--r--test/web/twitter_api/twitter_api_controller_test.exs8
-rw-r--r--test/web/twitter_api/twitter_api_test.exs324
-rw-r--r--test/web/twitter_api/util_controller_test.exs170
-rw-r--r--test/web/web_finger/web_finger_controller_test.exs4
-rw-r--r--test/web/web_finger/web_finger_test.exs7
-rw-r--r--test/workers/cron/clear_oauth_token_worker_test.exs4
-rw-r--r--test/workers/cron/digest_emails_worker_test.exs8
-rw-r--r--test/workers/cron/new_users_digest_worker_test.exs9
-rw-r--r--test/workers/cron/purge_expired_activities_worker_test.exs32
-rw-r--r--test/workers/scheduled_activity_worker_test.exs9
1602 files changed, 60290 insertions, 22955 deletions
diff --git a/.gitignore b/.gitignore
index 198e80139..599b52b9e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,7 @@
/*.ez
/test/uploads
/.elixir_ls
+/test/fixtures/DSCN0010_tmp.jpg
/test/fixtures/test_tmp.txt
/test/fixtures/image_tmp.jpg
/test/tmp/
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 1b7c03ebb..dc953a929 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,4 +1,4 @@
-image: elixir:1.8.1
+image: elixir:1.9.4
variables: &global_variables
POSTGRES_DB: pleroma_test
@@ -22,6 +22,7 @@ stages:
- docker
before_script:
+ - apt-get update && apt-get install -y cmake
- mix local.hex --force
- mix local.rebar --force
@@ -48,6 +49,7 @@ benchmark:
unit-testing:
stage: test
+ retry: 2
cache: &testing_cache_policy
<<: *global_cache_policy
policy: pull
@@ -57,6 +59,7 @@ unit-testing:
alias: postgres
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
script:
+ - apt-get update && apt-get install -y libimage-exiftool-perl
- mix deps.get
- mix ecto.create
- mix ecto.migrate
@@ -80,6 +83,7 @@ unit-testing:
unit-testing-rum:
stage: test
+ retry: 2
cache: *testing_cache_policy
services:
- name: minibikini/postgres-with-rum:12
@@ -89,6 +93,7 @@ unit-testing-rum:
<<: *global_variables
RUM_ENABLED: "true"
script:
+ - apt-get update && apt-get install -y libimage-exiftool-perl
- mix deps.get
- mix ecto.create
- mix ecto.migrate
@@ -168,8 +173,7 @@ stop_review_app:
amd64:
stage: release
- # TODO: Replace with upstream image when 1.9.0 comes out
- image: rinpatch/elixir:1.9.0-rc.0
+ image: elixir:1.10.3
only: &release-only
- stable@pleroma/pleroma
- develop@pleroma/pleroma
@@ -192,6 +196,7 @@ amd64:
variables: &release-variables
MIX_ENV: prod
before_script: &before-release
+ - apt-get update && apt-get install -y cmake
- echo "import Mix.Config" > config/prod.secret.exs
- mix local.hex --force
- mix local.rebar --force
@@ -206,12 +211,11 @@ amd64-musl:
stage: release
artifacts: *release-artifacts
only: *release-only
- # TODO: Replace with upstream image when 1.9.0 comes out
- image: rinpatch/elixir:1.9.0-rc.0-alpine
+ image: elixir:1.10.3-alpine
cache: *release-cache
variables: *release-variables
before_script: &before-release-musl
- - apk add git gcc g++ musl-dev make
+ - apk add git gcc g++ musl-dev make cmake
- echo "import Mix.Config" > config/prod.secret.exs
- mix local.hex --force
- mix local.rebar --force
@@ -223,8 +227,7 @@ arm:
only: *release-only
tags:
- arm32
- # TODO: Replace with upstream image when 1.9.0 comes out
- image: rinpatch/elixir:1.9.0-rc.0-arm
+ image: elixir:1.10.3
cache: *release-cache
variables: *release-variables
before_script: *before-release
@@ -236,8 +239,7 @@ arm-musl:
only: *release-only
tags:
- arm32
- # TODO: Replace with upstream image when 1.9.0 comes out
- image: rinpatch/elixir:1.9.0-rc.0-arm-alpine
+ image: elixir:1.10.3-alpine
cache: *release-cache
variables: *release-variables
before_script: *before-release-musl
@@ -249,8 +251,7 @@ arm64:
only: *release-only
tags:
- arm
- # TODO: Replace with upstream image when 1.9.0 comes out
- image: rinpatch/elixir:1.9.0-rc.0-arm64
+ image: elixir:1.10.3
cache: *release-cache
variables: *release-variables
before_script: *before-release
@@ -263,7 +264,7 @@ arm64-musl:
tags:
- arm
# TODO: Replace with upstream image when 1.9.0 comes out
- image: rinpatch/elixir:1.9.0-rc.0-arm64-alpine
+ image: elixir:1.10.3-alpine
cache: *release-cache
variables: *release-variables
before_script: *before-release-musl
@@ -281,6 +282,8 @@ docker:
IMAGE_TAG_SLUG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
IMAGE_TAG_LATEST: $CI_REGISTRY_IMAGE:latest
IMAGE_TAG_LATEST_STABLE: $CI_REGISTRY_IMAGE:latest-stable
+ DOCKER_BUILDX_URL: https://github.com/docker/buildx/releases/download/v0.4.1/buildx-v0.4.1.linux-amd64
+ DOCKER_BUILDX_HASH: 71a7d01439aa8c165a25b59c44d3f016fddbd98b
before_script: &before-docker
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker pull $IMAGE_TAG_SLUG || true
@@ -288,10 +291,14 @@ docker:
- export CI_VCS_REF=$CI_COMMIT_SHORT_SHA
allow_failure: true
script:
- - docker build --cache-from $IMAGE_TAG_SLUG --build-arg VCS_REF=$CI_VCS_REF --build-arg BUILD_DATE=$CI_JOB_TIMESTAMP -t $IMAGE_TAG -t $IMAGE_TAG_SLUG -t $IMAGE_TAG_LATEST .
- - docker push $IMAGE_TAG
- - docker push $IMAGE_TAG_SLUG
- - docker push $IMAGE_TAG_LATEST
+ - mkdir -p /root/.docker/cli-plugins
+ - wget "${DOCKER_BUILDX_URL}" -O ~/.docker/cli-plugins/docker-buildx
+ - echo "${DOCKER_BUILDX_HASH} /root/.docker/cli-plugins/docker-buildx" | sha1sum -c
+ - chmod +x ~/.docker/cli-plugins/docker-buildx
+ - docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
+ - docker buildx create --name mbuilder --driver docker-container --use
+ - docker buildx inspect --bootstrap
+ - docker buildx build --platform linux/amd64,linux/arm/v7,linux/arm64/v8 --push --cache-from $IMAGE_TAG_SLUG --build-arg VCS_REF=$CI_VCS_REF --build-arg BUILD_DATE=$CI_JOB_TIMESTAMP -t $IMAGE_TAG -t $IMAGE_TAG_SLUG -t $IMAGE_TAG_LATEST .
tags:
- dind
only:
@@ -306,10 +313,14 @@ docker-stable:
before_script: *before-docker
allow_failure: true
script:
- - docker build --cache-from $IMAGE_TAG_SLUG --build-arg VCS_REF=$CI_VCS_REF --build-arg BUILD_DATE=$CI_JOB_TIMESTAMP -t $IMAGE_TAG -t $IMAGE_TAG_SLUG -t $IMAGE_TAG_LATEST_STABLE .
- - docker push $IMAGE_TAG
- - docker push $IMAGE_TAG_SLUG
- - docker push $IMAGE_TAG_LATEST_STABLE
+ - mkdir -p /root/.docker/cli-plugins
+ - wget "${DOCKER_BUILDX_URL}" -O ~/.docker/cli-plugins/docker-buildx
+ - echo "${DOCKER_BUILDX_HASH} /root/.docker/cli-plugins/docker-buildx" | sha1sum -c
+ - chmod +x ~/.docker/cli-plugins/docker-buildx
+ - docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
+ - docker buildx create --name mbuilder --driver docker-container --use
+ - docker buildx inspect --bootstrap
+ - docker buildx build --platform linux/amd64,linux/arm/v7,linux/arm64/v8 --push --cache-from $IMAGE_TAG_SLUG --build-arg VCS_REF=$CI_VCS_REF --build-arg BUILD_DATE=$CI_JOB_TIMESTAMP -t $IMAGE_TAG -t $IMAGE_TAG_SLUG -t $IMAGE_TAG_LATEST_STABLE .
tags:
- dind
only:
@@ -324,9 +335,15 @@ docker-release:
before_script: *before-docker
allow_failure: true
script:
- - docker build --cache-from $IMAGE_TAG_SLUG --build-arg VCS_REF=$CI_VCS_REF --build-arg BUILD_DATE=$CI_JOB_TIMESTAMP -t $IMAGE_TAG -t $IMAGE_TAG_SLUG .
- - docker push $IMAGE_TAG
- - docker push $IMAGE_TAG_SLUG
+ script:
+ - mkdir -p /root/.docker/cli-plugins
+ - wget "${DOCKER_BUILDX_URL}" -O ~/.docker/cli-plugins/docker-buildx
+ - echo "${DOCKER_BUILDX_HASH} /root/.docker/cli-plugins/docker-buildx" | sha1sum -c
+ - chmod +x ~/.docker/cli-plugins/docker-buildx
+ - docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
+ - docker buildx create --name mbuilder --driver docker-container --use
+ - docker buildx inspect --bootstrap
+ - docker buildx build --platform linux/amd64,linux/arm/v7,linux/arm64/v8 --push --cache-from $IMAGE_TAG_SLUG --build-arg VCS_REF=$CI_VCS_REF --build-arg BUILD_DATE=$CI_JOB_TIMESTAMP -t $IMAGE_TAG -t $IMAGE_TAG_SLUG .
tags:
- dind
only:
diff --git a/.gitlab/issue_templates/Bug.md b/.gitlab/issue_templates/Bug.md
new file mode 100644
index 000000000..dd0d6eb24
--- /dev/null
+++ b/.gitlab/issue_templates/Bug.md
@@ -0,0 +1,18 @@
+<!--
+### Precheck
+
+* For support use https://git.pleroma.social/pleroma/pleroma-support or [community channels](https://git.pleroma.social/pleroma/pleroma#community-channels).
+* Please do a quick search to ensure no similar bug has been reported before. If the bug has not been addressed after 2 weeks, it's fine to bump it.
+* Try to ensure that the bug is actually related to the Pleroma backend. For example, if a bug happens in Pleroma-FE but not in Mastodon-FE or mobile clients, it's likely that the bug should be filed in [Pleroma-FE](https://git.pleroma.social/pleroma/pleroma-fe/issues/new) repository.
+-->
+
+### Environment
+
+* Installation type (OTP or From Source):
+* Pleroma version (could be found in the "Version" tab of settings in Pleroma-FE):
+* Elixir version (`elixir -v` for from source installations, N/A for OTP):
+* Operating system:
+* PostgreSQL version (`psql -V`):
+
+
+### Bug description
diff --git a/.gitlab/merge_request_templates/Release.md b/.gitlab/merge_request_templates/Release.md
new file mode 100644
index 000000000..b2c772696
--- /dev/null
+++ b/.gitlab/merge_request_templates/Release.md
@@ -0,0 +1,6 @@
+### Release checklist
+* [ ] Bump version in `mix.exs`
+* [ ] Compile a changelog
+* [ ] Create an MR with an announcement to pleroma.social
+* [ ] Tag the release
+* [ ] Merge `stable` into `develop` (in case the fixes are already in develop, use `git merge -s ours --no-commit` and manually merge the changelogs)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7991b8196..0850deed7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,119 @@ 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/).
+## [2.1.0] - 2020-08-28
+
+### Changed
+
+- **Breaking:** The default descriptions on uploads are now empty. The old behavior (filename as default) can be configured, see the cheat sheet.
+- **Breaking:** Added the ObjectAgePolicy to the default set of MRFs. This will delist and strip the follower collection of any message received that is older than 7 days. This will stop users from seeing very old messages in the timelines. The messages can still be viewed on the user's page and in conversations. They also still trigger notifications.
+- **Breaking:** Elixir >=1.9 is now required (was >= 1.8)
+- **Breaking:** Configuration: `:auto_linker, :opts` moved to `:pleroma, Pleroma.Formatter`. Old config namespace is deprecated.
+- **Breaking:** Configuration: `:instance, welcome_user_nickname` moved to `:welcome, :direct_message, :sender_nickname`, `:instance, :welcome_message` moved to `:welcome, :direct_message, :message`. Old config namespace is deprecated.
+- **Breaking:** LDAP: Fallback to local database authentication has been removed for security reasons and lack of a mechanism to ensure the passwords are synchronized when LDAP passwords are updated.
+- **Breaking** Changed defaults for `:restrict_unauthenticated` so that when `:instance, :public` is set to `false` then all `:restrict_unauthenticated` items be effectively set to `true`. If you'd like to allow unauthenticated access to specific API endpoints on a private instance, please explicitly set `:restrict_unauthenticated` to non-default value in `config/prod.secret.exs`.
+- In Conversations, return only direct messages as `last_status`
+- Using the `only_media` filter on timelines will now exclude reblog media
+- MFR policy to set global expiration for all local Create activities
+- OGP rich media parser merged with TwitterCard
+- Configuration: `:instance, rewrite_policy` moved to `:mrf, policies`, `:instance, :mrf_transparency` moved to `:mrf, :transparency`, `:instance, :mrf_transparency_exclusions` moved to `:mrf, :transparency_exclusions`. Old config namespace is deprecated.
+- Configuration: `:media_proxy, whitelist` format changed to host with scheme (e.g. `http://example.com` instead of `example.com`). Domain format is deprecated.
+
+<details>
+ <summary>API Changes</summary>
+
+- **Breaking:** Pleroma API: The routes to update avatar, banner and background have been removed.
+- **Breaking:** Image description length is limited now.
+- **Breaking:** Emoji API: changed methods and renamed routes.
+- **Breaking:** Notification Settings API for suppressing notifications has been simplified down to `block_from_strangers`.
+- **Breaking:** Notification Settings API option for hiding push notification contents has been renamed to `hide_notification_contents`.
+- MastodonAPI: Allow removal of avatar, banner and background.
+- Streaming: Repeats of a user's posts will no longer be pushed to the user's stream.
+- Mastodon API: Added `pleroma.metadata.fields_limits` to /api/v1/instance
+- Mastodon API: On deletion, returns the original post text.
+- Mastodon API: Add `pleroma.unread_count` to the Marker entity.
+- Mastodon API: Added `pleroma.metadata.post_formats` to /api/v1/instance
+- Mastodon API (legacy): Allow query parameters for `/api/v1/domain_blocks`, e.g. `/api/v1/domain_blocks?domain=badposters.zone`
+- Mastodon API: Make notifications about statuses from muted users and threads read automatically
+- Pleroma API: `/api/pleroma/captcha` responses now include `seconds_valid` with an integer value.
+
+</details>
+
+<details>
+ <summary>Admin API Changes</summary>
+
+- **Breaking** Changed relay `/api/pleroma/admin/relay` endpoints response format.
+- Status visibility stats: now can return stats per instance.
+- Mix task to refresh counter cache (`mix pleroma.refresh_counter_cache`)
+
+</details>
+
+### Removed
+
+- **Breaking:** removed `with_move` parameter from notifications timeline.
+
+### Added
+
+- Frontends: Add mix task to install frontends.
+- Frontends: Add configurable frontends for primary and admin fe.
+- Configuration: Added a blacklist for email servers.
+- Chats: Added `accepts_chat_messages` field to user, exposed in APIs and federation.
+- Chats: Added support for federated chats. For details, see the docs.
+- ActivityPub: Added support for existing AP ids for instances migrated from Mastodon.
+- Instance: Add `background_image` to configuration and `/api/v1/instance`
+- Instance: Extend `/api/v1/instance` with Pleroma-specific information.
+- NodeInfo: `pleroma:api/v1/notifications:include_types_filter` to the `features` list.
+- NodeInfo: `pleroma_emoji_reactions` to the `features` list.
+- Configuration: `:restrict_unauthenticated` setting, restrict access for unauthenticated users to timelines (public and federate), user profiles and statuses.
+- Configuration: Add `:database_config_whitelist` setting to whitelist settings which can be configured from AdminFE.
+- Configuration: `filename_display_max_length` option to set filename truncate limit, if filename display enabled (0 = no limit).
+- New HTTP adapter [gun](https://github.com/ninenines/gun). Gun adapter requires minimum OTP version of 22.2 otherwise Pleroma won’t start. For hackney OTP update is not required.
+- Mix task to create trusted OAuth App.
+- Mix task to reset MFA for user accounts
+- Notifications: Added `follow_request` notification type.
+- Added `:reject_deletes` group to SimplePolicy
+- MRF (`EmojiStealPolicy`): New MRF Policy which allows to automatically download emojis from remote instances
+- Support pagination in emoji packs API (for packs and for files in pack)
+- Support for viewing instances favicons next to posts and accounts
+- Added Pleroma.Upload.Filter.Exiftool as an alternate EXIF stripping mechanism targeting GPS/location metadata.
+- "By approval" registrations mode.
+- Configuration: Added `:welcome` settings for the welcome message to newly registered users. You can send a welcome message as a direct message, chat or email.
+- Ability to hide favourites and emoji reactions in the API with `[:instance, :show_reactions]` config.
+
+<details>
+ <summary>API Changes</summary>
+
+- Mastodon API: Add pleroma.parent_visible field to statuses.
+- Mastodon API: Extended `/api/v1/instance`.
+- Mastodon API: Support for `include_types` in `/api/v1/notifications`.
+- Mastodon API: Added `/api/v1/notifications/:id/dismiss` endpoint.
+- Mastodon API: Add support for filtering replies in public and home timelines.
+- Mastodon API: Support for `bot` field in `/api/v1/accounts/update_credentials`.
+- Mastodon API: Support irreversible property for filters.
+- Mastodon API: Add pleroma.favicon field to accounts.
+- Admin API: endpoints for create/update/delete OAuth Apps.
+- Admin API: endpoint for status view.
+- OTP: Add command to reload emoji packs
+</details>
+
+### Fixed
+- Fix list pagination and other list issues.
+- Support pagination in conversations API
+- **Breaking**: SimplePolicy `:reject` and `:accept` allow deletions again
+- Fix follower/blocks import when nicknames starts with @
+- Filtering of push notifications on activities from blocked domains
+- Resolving Peertube accounts with Webfinger
+- `blob:` urls not being allowed by connect-src CSP
+- Mastodon API: fix `GET /api/v1/notifications` not returning the full result set
+- Rich Media Previews for Twitter links
+- Admin API: fix `GET /api/pleroma/admin/users/:nickname/credentials` returning 404 when getting the credentials of a remote user while `:instance, :limit_to_local_content` is set to `:unauthenticated`
+- Fix CSP policy generation to include remote Captcha services
+- Fix edge case where MediaProxy truncates media, usually caused when Caddy is serving content for the other Federated instance.
+- Emoji Packs could not be listed when instance was set to `public: false`
+- Fix whole_word always returning false on filter get requests
+- Migrations not working on OTP releases if the database was connected over ssl
+- Fix relay following
+
## [2.0.7] - 2020-06-13
### Security
@@ -107,6 +220,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
2. Run database migrations (inside Pleroma directory):
- OTP: `./bin/pleroma_ctl migrate`
- From Source: `mix ecto.migrate`
+3. Reset status visibility counters (inside Pleroma directory):
+ - OTP: `./bin/pleroma_ctl refresh_counter_cache`
+ - From Source: `mix pleroma.refresh_counter_cache`
+
## [2.0.2] - 2020-04-08
### Added
@@ -128,6 +245,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Static-FE: Fix remote posts not being sanitized
### Fixed
+=======
- Rate limiter crashes when there is no explicitly specified ip in the config
- 500 errors when no `Accept` header is present if Static-FE is enabled
- Instance panel not being updated immediately due to wrong `Cache-Control` headers
@@ -153,7 +271,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [2.0.0] - 2019-03-08
### Security
-- Mastodon API: Fix being able to request enourmous amount of statuses in timelines leading to DoS. Now limited to 40 per request.
+- Mastodon API: Fix being able to request enormous amount of statuses in timelines leading to DoS. Now limited to 40 per request.
### Removed
- **Breaking**: Removed 1.0+ deprecated configurations `Pleroma.Upload, :strip_exif` and `:instance, :dedupe_media`
@@ -162,6 +280,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- **Breaking**: Using third party engines for user recommendation
<details>
<summary>API Changes</summary>
+
- **Breaking**: AdminAPI: migrate_from_db endpoint
</details>
@@ -197,7 +316,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- **Breaking:** Admin API: Return link alongside with token on password reset
- **Breaking:** Admin API: `PUT /api/pleroma/admin/reports/:id` is now `PATCH /api/pleroma/admin/reports`, see admin_api.md for details
- **Breaking:** `/api/pleroma/admin/users/invite_token` now uses `POST`, changed accepted params and returns full invite in json instead of only token string.
-- **Breaking** replying to reports is now "report notes", enpoint changed from `POST /api/pleroma/admin/reports/:id/respond` to `POST /api/pleroma/admin/reports/:id/notes`
+- **Breaking** replying to reports is now "report notes", endpoint changed from `POST /api/pleroma/admin/reports/:id/respond` to `POST /api/pleroma/admin/reports/:id/notes`
- Mastodon API: stopped sanitizing display names, field names and subject fields since they are supposed to be treated as plaintext
- Admin API: Return `total` when querying for reports
- Mastodon API: Return `pleroma.direct_conversation_id` when creating a direct message (`POST /api/v1/statuses`)
diff --git a/COPYING b/COPYING
index 0aede0fba..3140c8038 100644
--- a/COPYING
+++ b/COPYING
@@ -1,4 +1,4 @@
-Unless otherwise stated this repository is copyright © 2017-2019
+Unless otherwise stated this repository is copyright © 2017-2020
Pleroma Authors <https://pleroma.social/>, and is distributed under
The GNU Affero General Public License Version 3, you should have received a
copy of the license file as AGPL-3.
@@ -23,7 +23,7 @@ priv/static/images/pleroma-fox-tan-shy.png
---
-The following files are copyright © 2017-2019 Pleroma Authors
+The following files are copyright © 2017-2020 Pleroma Authors
<https://pleroma.social/>, and are distributed under the Creative Commons
Attribution-ShareAlike 4.0 International license, you should have received
a copy of the license file as CC-BY-SA-4.0.
diff --git a/Dockerfile b/Dockerfile
index 4f7f12716..aa50e27ec 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -4,7 +4,7 @@ COPY . .
ENV MIX_ENV=prod
-RUN apk add git gcc g++ musl-dev make &&\
+RUN apk add git gcc g++ musl-dev make cmake &&\
echo "import Mix.Config" > config/prod.secret.exs &&\
mix local.hex --force &&\
mix local.rebar --force &&\
@@ -12,7 +12,7 @@ RUN apk add git gcc g++ musl-dev make &&\
mkdir release &&\
mix release --path release
-FROM alpine:3.9
+FROM alpine:3.11
ARG BUILD_DATE
ARG VCS_REF
@@ -33,7 +33,7 @@ ARG DATA=/var/lib/pleroma
RUN echo "http://nl.alpinelinux.org/alpine/latest-stable/community" >> /etc/apk/repositories &&\
apk update &&\
- apk add ncurses postgresql-client &&\
+ apk add exiftool imagemagick ncurses postgresql-client &&\
adduser --system --shell /bin/false --home ${HOME} pleroma &&\
mkdir -p ${DATA}/uploads &&\
mkdir -p ${DATA}/static &&\
diff --git a/README.md b/README.md
index 7fc1fd381..6ca3118fb 100644
--- a/README.md
+++ b/README.md
@@ -34,6 +34,16 @@ Currently Pleroma is not packaged by any OS/Distros, but if you want to package
### Docker
While we don’t provide docker files, other people have written very good ones. Take a look at <https://github.com/angristan/docker-pleroma> or <https://glitch.sh/sn0w/pleroma-docker>.
+### Compilation Troubleshooting
+If you ever encounter compilation issues during the updating of Pleroma, you can try these commands and see if they fix things:
+
+- `mix deps.clean --all`
+- `mix local.rebar`
+- `mix local.hex`
+- `rm -r _build`
+
+If you are not developing Pleroma, it is better to use the OTP release, which comes with everything precompiled.
+
## Documentation
- Latest Released revision: <https://docs.pleroma.social>
- Latest Git revision: <https://docs-develop.pleroma.social>
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 000000000..c212a2505
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,16 @@
+# Pleroma backend security policy
+
+## Supported versions
+
+Currently, Pleroma offers bugfixes and security patches only for the latest minor release.
+
+| Version | Support
+|---------| --------
+| 2.0 | Bugfixes and security patches
+
+## Reporting a vulnerability
+
+Please use confidential issues (tick the "This issue is confidential and should only be visible to team members with at least Reporter access." box when submitting) at our [bugtracker](https://git.pleroma.social/pleroma/pleroma/-/issues/new) for reporting vulnerabilities.
+## Announcements
+
+New releases are announced at [pleroma.social](https://pleroma.social/announcements/). All security releases are tagged with ["Security"](https://pleroma.social/announcements/tags/security/). You can be notified of them by subscribing to an Atom feed at <https://pleroma.social/announcements/tags/security/feed.xml>.
diff --git a/benchmarks/load_testing/activities.ex b/benchmarks/load_testing/activities.ex
new file mode 100644
index 000000000..f5c7bfce8
--- /dev/null
+++ b/benchmarks/load_testing/activities.ex
@@ -0,0 +1,595 @@
+defmodule Pleroma.LoadTesting.Activities do
+ @moduledoc """
+ Module for generating different activities.
+ """
+ import Ecto.Query
+ import Pleroma.LoadTesting.Helper, only: [to_sec: 1]
+
+ alias Ecto.UUID
+ alias Pleroma.Constants
+ alias Pleroma.LoadTesting.Users
+ alias Pleroma.Repo
+ alias Pleroma.Web.CommonAPI
+
+ require Constants
+
+ @defaults [
+ iterations: 170,
+ friends_used: 20,
+ non_friends_used: 20
+ ]
+
+ @max_concurrency 10
+
+ @visibility ~w(public private direct unlisted)
+ @types [
+ :simple,
+ :simple_filtered,
+ :emoji,
+ :mentions,
+ :hell_thread,
+ :attachment,
+ :tag,
+ :like,
+ :reblog,
+ :simple_thread
+ ]
+ @groups [:friends_local, :friends_remote, :non_friends_local, :non_friends_local]
+ @remote_groups [:friends_remote, :non_friends_remote]
+ @friends_groups [:friends_local, :friends_remote]
+ @non_friends_groups [:non_friends_local, :non_friends_remote]
+
+ @spec generate(User.t(), keyword()) :: :ok
+ def generate(user, opts \\ []) do
+ {:ok, _} =
+ Agent.start_link(fn -> %{} end,
+ name: :benchmark_state
+ )
+
+ opts = Keyword.merge(@defaults, opts)
+
+ users = Users.prepare_users(user, opts)
+
+ {:ok, _} = Agent.start_link(fn -> users[:non_friends_remote] end, name: :non_friends_remote)
+
+ task_data =
+ for visibility <- @visibility,
+ type <- @types,
+ group <- [:user | @groups],
+ do: {visibility, type, group}
+
+ IO.puts("Starting generating #{opts[:iterations]} iterations of activities...")
+
+ public_long_thread = fn ->
+ generate_long_thread("public", users, opts)
+ end
+
+ private_long_thread = fn ->
+ generate_long_thread("private", users, opts)
+ end
+
+ iterations = opts[:iterations]
+
+ {time, _} =
+ :timer.tc(fn ->
+ Enum.each(
+ 1..iterations,
+ fn
+ i when i == iterations - 2 ->
+ spawn(public_long_thread)
+ spawn(private_long_thread)
+ generate_activities(users, Enum.shuffle(task_data), opts)
+
+ _ ->
+ generate_activities(users, Enum.shuffle(task_data), opts)
+ end
+ )
+ end)
+
+ IO.puts("Generating iterations of activities took #{to_sec(time)} sec.\n")
+ :ok
+ end
+
+ def generate_power_intervals(opts \\ []) do
+ count = Keyword.get(opts, :count, 20)
+ power = Keyword.get(opts, :power, 2)
+ IO.puts("Generating #{count} intervals for a power #{power} series...")
+ counts = Enum.map(1..count, fn n -> :math.pow(n, power) end)
+ sum = Enum.sum(counts)
+
+ densities =
+ Enum.map(counts, fn c ->
+ c / sum
+ end)
+
+ densities
+ |> Enum.reduce(0, fn density, acc ->
+ if acc == 0 do
+ [{0, density}]
+ else
+ [{_, lower} | _] = acc
+ [{lower, lower + density} | acc]
+ end
+ end)
+ |> Enum.reverse()
+ end
+
+ def generate_tagged_activities(opts \\ []) do
+ tag_count = Keyword.get(opts, :tag_count, 20)
+ users = Keyword.get(opts, :users, Repo.all(Pleroma.User))
+ activity_count = Keyword.get(opts, :count, 200_000)
+
+ intervals = generate_power_intervals(count: tag_count)
+
+ IO.puts(
+ "Generating #{activity_count} activities using #{tag_count} different tags of format `tag_n`, starting at tag_0"
+ )
+
+ Enum.each(1..activity_count, fn _ ->
+ random = :rand.uniform()
+ i = Enum.find_index(intervals, fn {lower, upper} -> lower <= random && upper > random end)
+ CommonAPI.post(Enum.random(users), %{status: "a post with the tag #tag_#{i}"})
+ end)
+ end
+
+ defp generate_long_thread(visibility, users, _opts) do
+ group =
+ if visibility == "public",
+ do: :friends_local,
+ else: :user
+
+ tasks = get_reply_tasks(visibility, group) |> Stream.cycle() |> Enum.take(50)
+
+ {:ok, activity} =
+ CommonAPI.post(users[:user], %{
+ status: "Start of #{visibility} long thread",
+ visibility: visibility
+ })
+
+ Agent.update(:benchmark_state, fn state ->
+ key =
+ if visibility == "public",
+ do: :public_thread,
+ else: :private_thread
+
+ Map.put(state, key, activity)
+ end)
+
+ acc = {activity.id, ["@" <> users[:user].nickname, "reply to long thread"]}
+ insert_replies_for_long_thread(tasks, visibility, users, acc)
+ IO.puts("Generating #{visibility} long thread ended\n")
+ end
+
+ defp insert_replies_for_long_thread(tasks, visibility, users, acc) do
+ Enum.reduce(tasks, acc, fn
+ :user, {id, data} ->
+ user = users[:user]
+ insert_reply(user, List.delete(data, "@" <> user.nickname), id, visibility)
+
+ group, {id, data} ->
+ replier = Enum.random(users[group])
+ insert_reply(replier, List.delete(data, "@" <> replier.nickname), id, visibility)
+ end)
+ end
+
+ defp generate_activities(users, task_data, opts) do
+ Task.async_stream(
+ task_data,
+ fn {visibility, type, group} ->
+ insert_activity(type, visibility, group, users, opts)
+ end,
+ max_concurrency: @max_concurrency,
+ timeout: 30_000
+ )
+ |> Stream.run()
+ end
+
+ defp insert_local_activity(visibility, group, users, status) do
+ {:ok, _} =
+ group
+ |> get_actor(users)
+ |> CommonAPI.post(%{status: status, visibility: visibility})
+ end
+
+ defp insert_remote_activity(visibility, group, users, status) do
+ actor = get_actor(group, users)
+ {act_data, obj_data} = prepare_activity_data(actor, visibility, users[:user])
+ {activity_data, object_data} = other_data(actor, status)
+
+ activity_data
+ |> Map.merge(act_data)
+ |> Map.put("object", Map.merge(object_data, obj_data))
+ |> Pleroma.Web.ActivityPub.ActivityPub.insert(false)
+ end
+
+ defp user_mentions(users) do
+ user_mentions =
+ Enum.reduce(
+ @groups,
+ [],
+ fn group, acc ->
+ acc ++ get_random_mentions(users[group], Enum.random(0..2))
+ end
+ )
+
+ if Enum.random([true, false]),
+ do: ["@" <> users[:user].nickname | user_mentions],
+ else: user_mentions
+ end
+
+ defp hell_thread_mentions(users) do
+ with {:ok, nil} <- Cachex.get(:user_cache, "hell_thread_mentions") do
+ cached =
+ @groups
+ |> Enum.reduce([users[:user]], fn group, acc ->
+ acc ++ Enum.take(users[group], 5)
+ end)
+ |> Enum.map(&"@#{&1.nickname}")
+ |> Enum.join(", ")
+
+ Cachex.put(:user_cache, "hell_thread_mentions", cached)
+ cached
+ else
+ {:ok, cached} -> cached
+ end
+ end
+
+ defp insert_activity(:simple, visibility, group, users, _opts)
+ when group in @remote_groups do
+ insert_remote_activity(visibility, group, users, "Remote status")
+ end
+
+ defp insert_activity(:simple, visibility, group, users, _opts) do
+ insert_local_activity(visibility, group, users, "Simple status")
+ end
+
+ defp insert_activity(:simple_filtered, visibility, group, users, _opts)
+ when group in @remote_groups do
+ insert_remote_activity(visibility, group, users, "Remote status which must be filtered")
+ end
+
+ defp insert_activity(:simple_filtered, visibility, group, users, _opts) do
+ insert_local_activity(visibility, group, users, "Simple status which must be filtered")
+ end
+
+ defp insert_activity(:emoji, visibility, group, users, _opts)
+ when group in @remote_groups do
+ insert_remote_activity(visibility, group, users, "Remote status with emoji :firefox:")
+ end
+
+ defp insert_activity(:emoji, visibility, group, users, _opts) do
+ insert_local_activity(visibility, group, users, "Simple status with emoji :firefox:")
+ end
+
+ defp insert_activity(:mentions, visibility, group, users, _opts)
+ when group in @remote_groups do
+ mentions = user_mentions(users)
+
+ status = Enum.join(mentions, ", ") <> " remote status with mentions"
+
+ insert_remote_activity(visibility, group, users, status)
+ end
+
+ defp insert_activity(:mentions, visibility, group, users, _opts) do
+ mentions = user_mentions(users)
+
+ status = Enum.join(mentions, ", ") <> " simple status with mentions"
+ insert_remote_activity(visibility, group, users, status)
+ end
+
+ defp insert_activity(:hell_thread, visibility, group, users, _)
+ when group in @remote_groups do
+ mentions = hell_thread_mentions(users)
+ insert_remote_activity(visibility, group, users, mentions <> " remote hell thread status")
+ end
+
+ defp insert_activity(:hell_thread, visibility, group, users, _opts) do
+ mentions = hell_thread_mentions(users)
+
+ insert_local_activity(visibility, group, users, mentions <> " hell thread status")
+ end
+
+ defp insert_activity(:attachment, visibility, group, users, _opts) do
+ actor = get_actor(group, users)
+
+ obj_data = %{
+ "actor" => actor.ap_id,
+ "name" => "4467-11.jpg",
+ "type" => "Document",
+ "url" => [
+ %{
+ "href" =>
+ "#{Pleroma.Web.base_url()}/media/b1b873552422a07bf53af01f3c231c841db4dfc42c35efde681abaf0f2a4eab7.jpg",
+ "mediaType" => "image/jpeg",
+ "type" => "Link"
+ }
+ ]
+ }
+
+ object = Repo.insert!(%Pleroma.Object{data: obj_data})
+
+ {:ok, _activity} =
+ CommonAPI.post(actor, %{
+ status: "Post with attachment",
+ visibility: visibility,
+ media_ids: [object.id]
+ })
+ end
+
+ defp insert_activity(:tag, visibility, group, users, _opts) do
+ insert_local_activity(visibility, group, users, "Status with #tag")
+ end
+
+ defp insert_activity(:like, visibility, group, users, opts) do
+ actor = get_actor(group, users)
+
+ with activity_id when not is_nil(activity_id) <- get_random_create_activity_id(),
+ {:ok, _activity} <- CommonAPI.favorite(actor, activity_id) do
+ :ok
+ else
+ {:error, _} ->
+ insert_activity(:like, visibility, group, users, opts)
+
+ nil ->
+ Process.sleep(15)
+ insert_activity(:like, visibility, group, users, opts)
+ end
+ end
+
+ defp insert_activity(:reblog, visibility, group, users, opts) do
+ actor = get_actor(group, users)
+
+ with activity_id when not is_nil(activity_id) <- get_random_create_activity_id(),
+ {:ok, _activity} <- CommonAPI.repeat(activity_id, actor) do
+ :ok
+ else
+ {:error, _} ->
+ insert_activity(:reblog, visibility, group, users, opts)
+
+ nil ->
+ Process.sleep(15)
+ insert_activity(:reblog, visibility, group, users, opts)
+ end
+ end
+
+ defp insert_activity(:simple_thread, "direct", group, users, _opts) do
+ actor = get_actor(group, users)
+ tasks = get_reply_tasks("direct", group)
+
+ list =
+ case group do
+ :user ->
+ group = Enum.random(@friends_groups)
+ Enum.take(users[group], 3)
+
+ _ ->
+ Enum.take(users[group], 3)
+ end
+
+ data = Enum.map(list, &("@" <> &1.nickname))
+
+ {:ok, activity} =
+ CommonAPI.post(actor, %{
+ status: Enum.join(data, ", ") <> "simple status",
+ visibility: "direct"
+ })
+
+ acc = {activity.id, ["@" <> users[:user].nickname | data] ++ ["reply to status"]}
+ insert_direct_replies(tasks, users[:user], list, acc)
+ end
+
+ defp insert_activity(:simple_thread, visibility, group, users, _opts) do
+ actor = get_actor(group, users)
+ tasks = get_reply_tasks(visibility, group)
+
+ {:ok, activity} =
+ CommonAPI.post(users[:user], %{status: "Simple status", visibility: visibility})
+
+ acc = {activity.id, ["@" <> actor.nickname, "reply to status"]}
+ insert_replies(tasks, visibility, users, acc)
+ end
+
+ defp get_actor(:user, %{user: user}), do: user
+ defp get_actor(group, users), do: Enum.random(users[group])
+
+ defp other_data(actor, content) do
+ %{host: host} = URI.parse(actor.ap_id)
+ datetime = DateTime.utc_now()
+ context_id = "https://#{host}/contexts/#{UUID.generate()}"
+ activity_id = "https://#{host}/activities/#{UUID.generate()}"
+ object_id = "https://#{host}/objects/#{UUID.generate()}"
+
+ activity_data = %{
+ "actor" => actor.ap_id,
+ "context" => context_id,
+ "id" => activity_id,
+ "published" => datetime,
+ "type" => "Create",
+ "directMessage" => false
+ }
+
+ object_data = %{
+ "actor" => actor.ap_id,
+ "attachment" => [],
+ "attributedTo" => actor.ap_id,
+ "bcc" => [],
+ "bto" => [],
+ "content" => content,
+ "context" => context_id,
+ "conversation" => context_id,
+ "emoji" => %{},
+ "id" => object_id,
+ "published" => datetime,
+ "sensitive" => false,
+ "summary" => "",
+ "tag" => [],
+ "to" => ["https://www.w3.org/ns/activitystreams#Public"],
+ "type" => "Note"
+ }
+
+ {activity_data, object_data}
+ end
+
+ defp prepare_activity_data(actor, "public", _mention) do
+ obj_data = %{
+ "cc" => [actor.follower_address],
+ "to" => [Constants.as_public()]
+ }
+
+ act_data = %{
+ "cc" => [actor.follower_address],
+ "to" => [Constants.as_public()]
+ }
+
+ {act_data, obj_data}
+ end
+
+ defp prepare_activity_data(actor, "private", _mention) do
+ obj_data = %{
+ "cc" => [],
+ "to" => [actor.follower_address]
+ }
+
+ act_data = %{
+ "cc" => [],
+ "to" => [actor.follower_address]
+ }
+
+ {act_data, obj_data}
+ end
+
+ defp prepare_activity_data(actor, "unlisted", _mention) do
+ obj_data = %{
+ "cc" => [Constants.as_public()],
+ "to" => [actor.follower_address]
+ }
+
+ act_data = %{
+ "cc" => [Constants.as_public()],
+ "to" => [actor.follower_address]
+ }
+
+ {act_data, obj_data}
+ end
+
+ defp prepare_activity_data(_actor, "direct", mention) do
+ %{host: mentioned_host} = URI.parse(mention.ap_id)
+
+ obj_data = %{
+ "cc" => [],
+ "content" =>
+ "<span class=\"h-card\"><a class=\"u-url mention\" href=\"#{mention.ap_id}\" rel=\"ugc\">@<span>#{
+ mention.nickname
+ }</span></a></span> direct message",
+ "tag" => [
+ %{
+ "href" => mention.ap_id,
+ "name" => "@#{mention.nickname}@#{mentioned_host}",
+ "type" => "Mention"
+ }
+ ],
+ "to" => [mention.ap_id]
+ }
+
+ act_data = %{
+ "cc" => [],
+ "directMessage" => true,
+ "to" => [mention.ap_id]
+ }
+
+ {act_data, obj_data}
+ end
+
+ defp get_reply_tasks("public", :user) do
+ [:friends_local, :friends_remote, :non_friends_local, :non_friends_remote, :user]
+ end
+
+ defp get_reply_tasks("public", group) when group in @friends_groups do
+ [:non_friends_local, :non_friends_remote, :user, :friends_local, :friends_remote]
+ end
+
+ defp get_reply_tasks("public", group) when group in @non_friends_groups do
+ [:user, :friends_local, :friends_remote, :non_friends_local, :non_friends_remote]
+ end
+
+ defp get_reply_tasks(visibility, :user) when visibility in ["unlisted", "private"] do
+ [:friends_local, :friends_remote, :user, :friends_local, :friends_remote]
+ end
+
+ defp get_reply_tasks(visibility, group)
+ when visibility in ["unlisted", "private"] and group in @friends_groups do
+ [:user, :friends_remote, :friends_local, :user]
+ end
+
+ defp get_reply_tasks(visibility, group)
+ when visibility in ["unlisted", "private"] and
+ group in @non_friends_groups,
+ do: []
+
+ defp get_reply_tasks("direct", :user), do: [:friends_local, :user, :friends_remote]
+
+ defp get_reply_tasks("direct", group) when group in @friends_groups,
+ do: [:user, group, :user]
+
+ defp get_reply_tasks("direct", group) when group in @non_friends_groups do
+ [:user, :non_friends_remote, :user, :non_friends_local]
+ end
+
+ defp insert_replies(tasks, visibility, users, acc) do
+ Enum.reduce(tasks, acc, fn
+ :user, {id, data} ->
+ insert_reply(users[:user], data, id, visibility)
+
+ group, {id, data} ->
+ replier = Enum.random(users[group])
+ insert_reply(replier, data, id, visibility)
+ end)
+ end
+
+ defp insert_direct_replies(tasks, user, list, acc) do
+ Enum.reduce(tasks, acc, fn
+ :user, {id, data} ->
+ {reply_id, _} = insert_reply(user, List.delete(data, "@" <> user.nickname), id, "direct")
+ {reply_id, data}
+
+ _, {id, data} ->
+ actor = Enum.random(list)
+
+ {reply_id, _} =
+ insert_reply(actor, List.delete(data, "@" <> actor.nickname), id, "direct")
+
+ {reply_id, data}
+ end)
+ end
+
+ defp insert_reply(actor, data, activity_id, visibility) do
+ {:ok, reply} =
+ CommonAPI.post(actor, %{
+ status: Enum.join(data, ", "),
+ visibility: visibility,
+ in_reply_to_status_id: activity_id
+ })
+
+ {reply.id, ["@" <> actor.nickname | data]}
+ end
+
+ defp get_random_mentions(_users, count) when count == 0, do: []
+
+ defp get_random_mentions(users, count) do
+ users
+ |> Enum.shuffle()
+ |> Enum.take(count)
+ |> Enum.map(&"@#{&1.nickname}")
+ end
+
+ defp get_random_create_activity_id do
+ Repo.one(
+ from(a in Pleroma.Activity,
+ where: fragment("(?)->>'type' = ?", a.data, ^"Create"),
+ order_by: fragment("RANDOM()"),
+ limit: 1,
+ select: a.id
+ )
+ )
+ end
+end
diff --git a/benchmarks/load_testing/fetcher.ex b/benchmarks/load_testing/fetcher.ex
index a45a71d4a..dfbd916be 100644
--- a/benchmarks/load_testing/fetcher.ex
+++ b/benchmarks/load_testing/fetcher.ex
@@ -1,260 +1,623 @@
defmodule Pleroma.LoadTesting.Fetcher do
- use Pleroma.LoadTesting.Helper
+ alias Pleroma.Activity
+ alias Pleroma.Pagination
+ alias Pleroma.Repo
+ alias Pleroma.User
+ alias Pleroma.Web.ActivityPub.ActivityPub
+ alias Pleroma.Web.MastodonAPI.MastodonAPI
+ alias Pleroma.Web.MastodonAPI.StatusView
- def fetch_user(user) do
- Benchee.run(%{
- "By id" => fn -> Repo.get_by(User, id: user.id) end,
- "By ap_id" => fn -> Repo.get_by(User, ap_id: user.ap_id) end,
- "By email" => fn -> Repo.get_by(User, email: user.email) end,
- "By nickname" => fn -> Repo.get_by(User, nickname: user.nickname) end
+ @spec run_benchmarks(User.t()) :: any()
+ def run_benchmarks(user) do
+ fetch_user(user)
+ fetch_timelines(user)
+ render_views(user)
+ end
+
+ defp formatters do
+ [
+ Benchee.Formatters.Console
+ ]
+ end
+
+ defp fetch_user(user) do
+ Benchee.run(
+ %{
+ "By id" => fn -> Repo.get_by(User, id: user.id) end,
+ "By ap_id" => fn -> Repo.get_by(User, ap_id: user.ap_id) end,
+ "By email" => fn -> Repo.get_by(User, email: user.email) end,
+ "By nickname" => fn -> Repo.get_by(User, nickname: user.nickname) end
+ },
+ formatters: formatters()
+ )
+ end
+
+ defp create_filter(user) do
+ Pleroma.Filter.create(%Pleroma.Filter{
+ user_id: user.id,
+ phrase: "must be filtered",
+ hide: true
})
end
- def query_timelines(user) do
- home_timeline_params = %{
- "count" => 20,
- "with_muted" => true,
- "type" => ["Create", "Announce"],
- "blocking_user" => user,
- "muting_user" => user,
- "user" => user
+ defp delete_filter(filter), do: Repo.delete(filter)
+
+ defp fetch_timelines(user) do
+ fetch_home_timeline(user)
+ fetch_home_timeline_with_filter(user)
+ fetch_direct_timeline(user)
+ fetch_public_timeline(user)
+ fetch_public_timeline_with_filter(user)
+ fetch_public_timeline(user, :with_blocks)
+ fetch_public_timeline(user, :local)
+ fetch_public_timeline(user, :tag)
+ fetch_notifications(user)
+ fetch_favourites(user)
+ fetch_long_thread(user)
+ fetch_timelines_with_reply_filtering(user)
+ end
+
+ defp render_views(user) do
+ render_timelines(user)
+ render_long_thread(user)
+ end
+
+ defp opts_for_home_timeline(user) do
+ %{
+ blocking_user: user,
+ count: "20",
+ muting_user: user,
+ type: ["Create", "Announce"],
+ user: user,
+ with_muted: true
}
+ end
+
+ defp fetch_home_timeline(user, title_end \\ "") do
+ opts = opts_for_home_timeline(user)
+
+ recipients = [user.ap_id | User.following(user)]
+
+ first_page_last =
+ ActivityPub.fetch_activities(recipients, opts) |> Enum.reverse() |> List.last()
+
+ second_page_last =
+ ActivityPub.fetch_activities(recipients, Map.put(opts, :max_id, first_page_last.id))
+ |> Enum.reverse()
+ |> List.last()
- mastodon_public_timeline_params = %{
- "count" => 20,
- "local_only" => true,
- "only_media" => "false",
- "type" => ["Create", "Announce"],
- "with_muted" => "true",
- "blocking_user" => user,
- "muting_user" => user
+ third_page_last =
+ ActivityPub.fetch_activities(recipients, Map.put(opts, :max_id, second_page_last.id))
+ |> Enum.reverse()
+ |> List.last()
+
+ forth_page_last =
+ ActivityPub.fetch_activities(recipients, Map.put(opts, :max_id, third_page_last.id))
+ |> Enum.reverse()
+ |> List.last()
+
+ title = "home timeline " <> title_end
+
+ Benchee.run(
+ %{
+ title => fn opts -> ActivityPub.fetch_activities(recipients, opts) end
+ },
+ inputs: %{
+ "1 page" => opts,
+ "2 page" => Map.put(opts, :max_id, first_page_last.id),
+ "3 page" => Map.put(opts, :max_id, second_page_last.id),
+ "4 page" => Map.put(opts, :max_id, third_page_last.id),
+ "5 page" => Map.put(opts, :max_id, forth_page_last.id),
+ "1 page only media" => Map.put(opts, :only_media, true),
+ "2 page only media" =>
+ Map.put(opts, :max_id, first_page_last.id) |> Map.put(:only_media, true),
+ "3 page only media" =>
+ Map.put(opts, :max_id, second_page_last.id) |> Map.put(:only_media, true),
+ "4 page only media" =>
+ Map.put(opts, :max_id, third_page_last.id) |> Map.put(:only_media, true),
+ "5 page only media" =>
+ Map.put(opts, :max_id, forth_page_last.id) |> Map.put(:only_media, true)
+ },
+ formatters: formatters()
+ )
+ end
+
+ defp fetch_home_timeline_with_filter(user) do
+ {:ok, filter} = create_filter(user)
+
+ fetch_home_timeline(user, "with filters")
+
+ delete_filter(filter)
+ end
+
+ defp opts_for_direct_timeline(user) do
+ %{
+ visibility: "direct",
+ blocking_user: user,
+ count: "20",
+ type: "Create",
+ user: user,
+ with_muted: true
}
+ end
+
+ defp fetch_direct_timeline(user) do
+ recipients = [user.ap_id]
+
+ opts = opts_for_direct_timeline(user)
+
+ first_page_last =
+ recipients
+ |> ActivityPub.fetch_activities_query(opts)
+ |> Pagination.fetch_paginated(opts)
+ |> List.last()
+
+ opts2 = Map.put(opts, :max_id, first_page_last.id)
+
+ second_page_last =
+ recipients
+ |> ActivityPub.fetch_activities_query(opts2)
+ |> Pagination.fetch_paginated(opts2)
+ |> List.last()
+
+ opts3 = Map.put(opts, :max_id, second_page_last.id)
- mastodon_federated_timeline_params = %{
- "count" => 20,
- "only_media" => "false",
- "type" => ["Create", "Announce"],
- "with_muted" => "true",
- "blocking_user" => user,
- "muting_user" => user
+ third_page_last =
+ recipients
+ |> ActivityPub.fetch_activities_query(opts3)
+ |> Pagination.fetch_paginated(opts3)
+ |> List.last()
+
+ opts4 = Map.put(opts, :max_id, third_page_last.id)
+
+ forth_page_last =
+ recipients
+ |> ActivityPub.fetch_activities_query(opts4)
+ |> Pagination.fetch_paginated(opts4)
+ |> List.last()
+
+ Benchee.run(
+ %{
+ "direct timeline" => fn opts ->
+ ActivityPub.fetch_activities_query(recipients, opts) |> Pagination.fetch_paginated(opts)
+ end
+ },
+ inputs: %{
+ "1 page" => opts,
+ "2 page" => opts2,
+ "3 page" => opts3,
+ "4 page" => opts4,
+ "5 page" => Map.put(opts4, :max_id, forth_page_last.id)
+ },
+ formatters: formatters()
+ )
+ end
+
+ defp opts_for_public_timeline(user) do
+ %{
+ type: ["Create", "Announce"],
+ local_only: false,
+ blocking_user: user,
+ muting_user: user
}
+ end
- following = User.following(user)
+ defp opts_for_public_timeline(user, :local) do
+ %{
+ type: ["Create", "Announce"],
+ local_only: true,
+ blocking_user: user,
+ muting_user: user
+ }
+ end
- Benchee.run(%{
- "User home timeline" => fn ->
- Pleroma.Web.ActivityPub.ActivityPub.fetch_activities(
- following,
- home_timeline_params
- )
- end,
- "User mastodon public timeline" => fn ->
- Pleroma.Web.ActivityPub.ActivityPub.fetch_public_activities(
- mastodon_public_timeline_params
- )
- end,
- "User mastodon federated public timeline" => fn ->
- Pleroma.Web.ActivityPub.ActivityPub.fetch_public_activities(
- mastodon_federated_timeline_params
- )
- end
- })
+ defp opts_for_public_timeline(user, :tag) do
+ %{
+ blocking_user: user,
+ count: "20",
+ local_only: nil,
+ muting_user: user,
+ tag: ["tag"],
+ tag_all: [],
+ tag_reject: [],
+ type: "Create",
+ user: user,
+ with_muted: true
+ }
+ end
- home_activities =
- Pleroma.Web.ActivityPub.ActivityPub.fetch_activities(
- following,
- home_timeline_params
- )
+ defp fetch_public_timeline(user) do
+ opts = opts_for_public_timeline(user)
- public_activities =
- Pleroma.Web.ActivityPub.ActivityPub.fetch_public_activities(mastodon_public_timeline_params)
+ fetch_public_timeline(opts, "public timeline")
+ end
- public_federated_activities =
- Pleroma.Web.ActivityPub.ActivityPub.fetch_public_activities(
- mastodon_federated_timeline_params
- )
+ defp fetch_public_timeline_with_filter(user) do
+ {:ok, filter} = create_filter(user)
+ opts = opts_for_public_timeline(user)
- Benchee.run(%{
- "Rendering home timeline" => fn ->
- Pleroma.Web.MastodonAPI.StatusView.render("index.json", %{
- activities: home_activities,
- for: user,
- as: :activity
- })
- end,
- "Rendering public timeline" => fn ->
- Pleroma.Web.MastodonAPI.StatusView.render("index.json", %{
- activities: public_activities,
- for: user,
- as: :activity
- })
- end,
- "Rendering public federated timeline" => fn ->
- Pleroma.Web.MastodonAPI.StatusView.render("index.json", %{
- activities: public_federated_activities,
- for: user,
- as: :activity
- })
- end,
- "Rendering favorites timeline" => fn ->
- conn = Phoenix.ConnTest.build_conn(:get, "http://localhost:4001/api/v1/favourites", nil)
- Pleroma.Web.MastodonAPI.StatusController.favourites(
- %Plug.Conn{conn |
- assigns: %{user: user},
- query_params: %{"limit" => "0"},
- body_params: %{},
- cookies: %{},
- params: %{},
- path_params: %{},
- private: %{
- Pleroma.Web.Router => {[], %{}},
- phoenix_router: Pleroma.Web.Router,
- phoenix_action: :favourites,
- phoenix_controller: Pleroma.Web.MastodonAPI.StatusController,
- phoenix_endpoint: Pleroma.Web.Endpoint,
- phoenix_format: "json",
- phoenix_layout: {Pleroma.Web.LayoutView, "app.html"},
- phoenix_recycled: true,
-
- phoenix_view: Pleroma.Web.MastodonAPI.StatusView,
- plug_session: %{"user_id" => user.id},
- plug_session_fetch: :done,
- plug_session_info: :write,
- plug_skip_csrf_protection: true
- }
- },
- %{})
- end,
- })
+ fetch_public_timeline(opts, "public timeline with filters")
+ delete_filter(filter)
end
- def query_notifications(user) do
- without_muted_params = %{"count" => "20", "with_muted" => "false"}
- with_muted_params = %{"count" => "20", "with_muted" => "true"}
+ defp fetch_public_timeline(user, :local) do
+ opts = opts_for_public_timeline(user, :local)
- Benchee.run(%{
- "Notifications without muted" => fn ->
- Pleroma.Web.MastodonAPI.MastodonAPI.get_notifications(user, without_muted_params)
- end,
- "Notifications with muted" => fn ->
- Pleroma.Web.MastodonAPI.MastodonAPI.get_notifications(user, with_muted_params)
- end
- })
+ fetch_public_timeline(opts, "public timeline only local")
+ end
- without_muted_notifications =
- Pleroma.Web.MastodonAPI.MastodonAPI.get_notifications(user, without_muted_params)
+ defp fetch_public_timeline(user, :tag) do
+ opts = opts_for_public_timeline(user, :tag)
- with_muted_notifications =
- Pleroma.Web.MastodonAPI.MastodonAPI.get_notifications(user, with_muted_params)
+ fetch_public_timeline(opts, "hashtag timeline")
+ end
- Benchee.run(%{
- "Render notifications without muted" => fn ->
- Pleroma.Web.MastodonAPI.NotificationView.render("index.json", %{
- notifications: without_muted_notifications,
- for: user
- })
- end,
- "Render notifications with muted" => fn ->
- Pleroma.Web.MastodonAPI.NotificationView.render("index.json", %{
- notifications: with_muted_notifications,
- for: user
- })
- end
- })
+ defp fetch_public_timeline(user, :only_media) do
+ opts = opts_for_public_timeline(user) |> Map.put(:only_media, true)
+
+ fetch_public_timeline(opts, "public timeline only media")
end
- def query_dms(user) do
- params = %{
- "count" => "20",
- "with_muted" => "true",
- "type" => "Create",
- "blocking_user" => user,
- "user" => user,
- visibility: "direct"
- }
+ defp fetch_public_timeline(user, :with_blocks) do
+ opts = opts_for_public_timeline(user)
+
+ remote_non_friends = Agent.get(:non_friends_remote, & &1)
Benchee.run(%{
- "Direct messages with muted" => fn ->
- Pleroma.Web.ActivityPub.ActivityPub.fetch_activities_query([user.ap_id], params)
- |> Pleroma.Pagination.fetch_paginated(params)
- end,
- "Direct messages without muted" => fn ->
- Pleroma.Web.ActivityPub.ActivityPub.fetch_activities_query([user.ap_id], params)
- |> Pleroma.Pagination.fetch_paginated(Map.put(params, "with_muted", false))
+ "public timeline without blocks" => fn ->
+ ActivityPub.fetch_public_activities(opts)
end
})
- dms_with_muted =
- Pleroma.Web.ActivityPub.ActivityPub.fetch_activities_query([user.ap_id], params)
- |> Pleroma.Pagination.fetch_paginated(params)
+ Enum.each(remote_non_friends, fn non_friend ->
+ {:ok, _} = User.block(user, non_friend)
+ end)
- dms_without_muted =
- Pleroma.Web.ActivityPub.ActivityPub.fetch_activities_query([user.ap_id], params)
- |> Pleroma.Pagination.fetch_paginated(Map.put(params, "with_muted", false))
+ user = User.get_by_id(user.id)
+
+ opts = Map.put(opts, :blocking_user, user)
Benchee.run(%{
- "Rendering dms with muted" => fn ->
- Pleroma.Web.MastodonAPI.StatusView.render("index.json", %{
- activities: dms_with_muted,
- for: user,
- as: :activity
- })
- end,
- "Rendering dms without muted" => fn ->
- Pleroma.Web.MastodonAPI.StatusView.render("index.json", %{
- activities: dms_without_muted,
- for: user,
- as: :activity
- })
+ "public timeline with user block" => fn ->
+ ActivityPub.fetch_public_activities(opts)
end
})
- end
- def query_long_thread(user, activity) do
+ domains =
+ Enum.reduce(remote_non_friends, [], fn non_friend, domains ->
+ {:ok, _user} = User.unblock(user, non_friend)
+ %{host: host} = URI.parse(non_friend.ap_id)
+ [host | domains]
+ end)
+
+ domains = Enum.uniq(domains)
+
+ Enum.each(domains, fn domain ->
+ {:ok, _} = User.block_domain(user, domain)
+ end)
+
+ user = User.get_by_id(user.id)
+ opts = Map.put(opts, :blocking_user, user)
+
Benchee.run(%{
- "Fetch main post" => fn ->
- Pleroma.Activity.get_by_id_with_object(activity.id)
- end,
- "Fetch context of main post" => fn ->
- Pleroma.Web.ActivityPub.ActivityPub.fetch_activities_for_context(
- activity.data["context"],
- %{
- "blocking_user" => user,
- "user" => user,
- "exclude_id" => activity.id
- }
- )
+ "public timeline with domain block" => fn ->
+ ActivityPub.fetch_public_activities(opts)
end
})
+ end
- activity = Pleroma.Activity.get_by_id_with_object(activity.id)
+ defp fetch_public_timeline(opts, title) when is_binary(title) do
+ first_page_last = ActivityPub.fetch_public_activities(opts) |> List.last()
- context =
- Pleroma.Web.ActivityPub.ActivityPub.fetch_activities_for_context(
- activity.data["context"],
- %{
- "blocking_user" => user,
- "user" => user,
- "exclude_id" => activity.id
- }
+ second_page_last =
+ ActivityPub.fetch_public_activities(Map.put(opts, :max_id, first_page_last.id))
+ |> List.last()
+
+ third_page_last =
+ ActivityPub.fetch_public_activities(Map.put(opts, :max_id, second_page_last.id))
+ |> List.last()
+
+ forth_page_last =
+ ActivityPub.fetch_public_activities(Map.put(opts, :max_id, third_page_last.id))
+ |> List.last()
+
+ Benchee.run(
+ %{
+ title => fn opts ->
+ ActivityPub.fetch_public_activities(opts)
+ end
+ },
+ inputs: %{
+ "1 page" => opts,
+ "2 page" => Map.put(opts, :max_id, first_page_last.id),
+ "3 page" => Map.put(opts, :max_id, second_page_last.id),
+ "4 page" => Map.put(opts, :max_id, third_page_last.id),
+ "5 page" => Map.put(opts, :max_id, forth_page_last.id)
+ },
+ formatters: formatters()
+ )
+ end
+
+ defp opts_for_notifications do
+ %{count: "20", with_muted: true}
+ end
+
+ defp fetch_notifications(user) do
+ opts = opts_for_notifications()
+
+ first_page_last = MastodonAPI.get_notifications(user, opts) |> List.last()
+
+ second_page_last =
+ MastodonAPI.get_notifications(user, Map.put(opts, :max_id, first_page_last.id))
+ |> List.last()
+
+ third_page_last =
+ MastodonAPI.get_notifications(user, Map.put(opts, :max_id, second_page_last.id))
+ |> List.last()
+
+ forth_page_last =
+ MastodonAPI.get_notifications(user, Map.put(opts, :max_id, third_page_last.id))
+ |> List.last()
+
+ Benchee.run(
+ %{
+ "Notifications" => fn opts ->
+ MastodonAPI.get_notifications(user, opts)
+ end
+ },
+ inputs: %{
+ "1 page" => opts,
+ "2 page" => Map.put(opts, :max_id, first_page_last.id),
+ "3 page" => Map.put(opts, :max_id, second_page_last.id),
+ "4 page" => Map.put(opts, :max_id, third_page_last.id),
+ "5 page" => Map.put(opts, :max_id, forth_page_last.id)
+ },
+ formatters: formatters()
+ )
+ end
+
+ defp fetch_favourites(user) do
+ first_page_last = ActivityPub.fetch_favourites(user) |> List.last()
+
+ second_page_last =
+ ActivityPub.fetch_favourites(user, %{:max_id => first_page_last.id}) |> List.last()
+
+ third_page_last =
+ ActivityPub.fetch_favourites(user, %{:max_id => second_page_last.id}) |> List.last()
+
+ forth_page_last =
+ ActivityPub.fetch_favourites(user, %{:max_id => third_page_last.id}) |> List.last()
+
+ Benchee.run(
+ %{
+ "Favourites" => fn opts ->
+ ActivityPub.fetch_favourites(user, opts)
+ end
+ },
+ inputs: %{
+ "1 page" => %{},
+ "2 page" => %{:max_id => first_page_last.id},
+ "3 page" => %{:max_id => second_page_last.id},
+ "4 page" => %{:max_id => third_page_last.id},
+ "5 page" => %{:max_id => forth_page_last.id}
+ },
+ formatters: formatters()
+ )
+ end
+
+ defp opts_for_long_thread(user) do
+ %{
+ blocking_user: user,
+ user: user
+ }
+ end
+
+ defp fetch_long_thread(user) do
+ %{public_thread: public, private_thread: private} =
+ Agent.get(:benchmark_state, fn state -> state end)
+
+ opts = opts_for_long_thread(user)
+
+ private_input = {private.data["context"], Map.put(opts, :exclude_id, private.id)}
+
+ public_input = {public.data["context"], Map.put(opts, :exclude_id, public.id)}
+
+ Benchee.run(
+ %{
+ "fetch context" => fn {context, opts} ->
+ ActivityPub.fetch_activities_for_context(context, opts)
+ end
+ },
+ inputs: %{
+ "Private long thread" => private_input,
+ "Public long thread" => public_input
+ },
+ formatters: formatters()
+ )
+ end
+
+ defp render_timelines(user) do
+ opts = opts_for_home_timeline(user)
+
+ recipients = [user.ap_id | User.following(user)]
+
+ home_activities = ActivityPub.fetch_activities(recipients, opts) |> Enum.reverse()
+
+ recipients = [user.ap_id]
+
+ opts = opts_for_direct_timeline(user)
+
+ direct_activities =
+ recipients
+ |> ActivityPub.fetch_activities_query(opts)
+ |> Pagination.fetch_paginated(opts)
+
+ opts = opts_for_public_timeline(user)
+
+ public_activities = ActivityPub.fetch_public_activities(opts)
+
+ opts = opts_for_public_timeline(user, :tag)
+
+ tag_activities = ActivityPub.fetch_public_activities(opts)
+
+ opts = opts_for_notifications()
+
+ notifications = MastodonAPI.get_notifications(user, opts)
+
+ favourites = ActivityPub.fetch_favourites(user)
+
+ Benchee.run(
+ %{
+ "Rendering home timeline" => fn ->
+ StatusView.render("index.json", %{
+ activities: home_activities,
+ for: user,
+ as: :activity
+ })
+ end,
+ "Rendering direct timeline" => fn ->
+ StatusView.render("index.json", %{
+ activities: direct_activities,
+ for: user,
+ as: :activity
+ })
+ end,
+ "Rendering public timeline" => fn ->
+ StatusView.render("index.json", %{
+ activities: public_activities,
+ for: user,
+ as: :activity
+ })
+ end,
+ "Rendering tag timeline" => fn ->
+ StatusView.render("index.json", %{
+ activities: tag_activities,
+ for: user,
+ as: :activity
+ })
+ end,
+ "Rendering notifications" => fn ->
+ Pleroma.Web.MastodonAPI.NotificationView.render("index.json", %{
+ notifications: notifications,
+ for: user
+ })
+ end,
+ "Rendering favourites timeline" => fn ->
+ StatusView.render("index.json", %{
+ activities: favourites,
+ for: user,
+ as: :activity
+ })
+ end
+ },
+ formatters: formatters()
+ )
+ end
+
+ defp render_long_thread(user) do
+ %{public_thread: public, private_thread: private} =
+ Agent.get(:benchmark_state, fn state -> state end)
+
+ opts = %{for: user}
+ public_activity = Activity.get_by_id_with_object(public.id)
+ private_activity = Activity.get_by_id_with_object(private.id)
+
+ Benchee.run(
+ %{
+ "render" => fn opts ->
+ StatusView.render("show.json", opts)
+ end
+ },
+ inputs: %{
+ "Public root" => Map.put(opts, :activity, public_activity),
+ "Private root" => Map.put(opts, :activity, private_activity)
+ },
+ formatters: formatters()
+ )
+
+ fetch_opts = opts_for_long_thread(user)
+
+ public_context =
+ ActivityPub.fetch_activities_for_context(
+ public.data["context"],
+ Map.put(fetch_opts, :exclude_id, public.id)
)
- Benchee.run(%{
- "Render status" => fn ->
- Pleroma.Web.MastodonAPI.StatusView.render("show.json", %{
- activity: activity,
- for: user
- })
- end,
- "Render context" => fn ->
- Pleroma.Web.MastodonAPI.StatusView.render(
- "index.json",
- for: user,
- activities: context,
- as: :activity
- )
- |> Enum.reverse()
- end
- })
+ private_context =
+ ActivityPub.fetch_activities_for_context(
+ private.data["context"],
+ Map.put(fetch_opts, :exclude_id, private.id)
+ )
+
+ Benchee.run(
+ %{
+ "render" => fn opts ->
+ StatusView.render("context.json", opts)
+ end
+ },
+ inputs: %{
+ "Public context" => %{user: user, activity: public_activity, activities: public_context},
+ "Private context" => %{
+ user: user,
+ activity: private_activity,
+ activities: private_context
+ }
+ },
+ formatters: formatters()
+ )
+ end
+
+ defp fetch_timelines_with_reply_filtering(user) do
+ public_params = opts_for_public_timeline(user)
+
+ Benchee.run(
+ %{
+ "Public timeline without reply filtering" => fn ->
+ ActivityPub.fetch_public_activities(public_params)
+ end,
+ "Public timeline with reply filtering - following" => fn ->
+ public_params
+ |> Map.put(:reply_visibility, "following")
+ |> Map.put(:reply_filtering_user, user)
+ |> ActivityPub.fetch_public_activities()
+ end,
+ "Public timeline with reply filtering - self" => fn ->
+ public_params
+ |> Map.put(:reply_visibility, "self")
+ |> Map.put(:reply_filtering_user, user)
+ |> ActivityPub.fetch_public_activities()
+ end
+ },
+ formatters: formatters()
+ )
+
+ private_params = opts_for_home_timeline(user)
+
+ recipients = [user.ap_id | User.following(user)]
+
+ Benchee.run(
+ %{
+ "Home timeline without reply filtering" => fn ->
+ ActivityPub.fetch_activities(recipients, private_params)
+ end,
+ "Home timeline with reply filtering - following" => fn ->
+ private_params =
+ private_params
+ |> Map.put(:reply_filtering_user, user)
+ |> Map.put(:reply_visibility, "following")
+
+ ActivityPub.fetch_activities(recipients, private_params)
+ end,
+ "Home timeline with reply filtering - self" => fn ->
+ private_params =
+ private_params
+ |> Map.put(:reply_filtering_user, user)
+ |> Map.put(:reply_visibility, "self")
+
+ ActivityPub.fetch_activities(recipients, private_params)
+ end
+ },
+ formatters: formatters()
+ )
end
end
diff --git a/benchmarks/load_testing/generator.ex b/benchmarks/load_testing/generator.ex
deleted file mode 100644
index 3f88fefd7..000000000
--- a/benchmarks/load_testing/generator.ex
+++ /dev/null
@@ -1,409 +0,0 @@
-defmodule Pleroma.LoadTesting.Generator do
- use Pleroma.LoadTesting.Helper
- alias Pleroma.Web.CommonAPI
-
- def generate_like_activities(user, posts) do
- count_likes = Kernel.trunc(length(posts) / 4)
- IO.puts("Starting generating #{count_likes} like activities...")
-
- {time, _} =
- :timer.tc(fn ->
- Task.async_stream(
- Enum.take_random(posts, count_likes),
- fn post -> {:ok, _, _} = CommonAPI.favorite(post.id, user) end,
- max_concurrency: 10,
- timeout: 30_000
- )
- |> Stream.run()
- end)
-
- IO.puts("Inserting like activities take #{to_sec(time)} sec.\n")
- end
-
- def generate_users(opts) do
- IO.puts("Starting generating #{opts[:users_max]} users...")
- {time, _} = :timer.tc(fn -> do_generate_users(opts) end)
-
- IO.puts("Inserting users take #{to_sec(time)} sec.\n")
- end
-
- defp do_generate_users(opts) do
- max = Keyword.get(opts, :users_max)
-
- Task.async_stream(
- 1..max,
- &generate_user_data(&1),
- max_concurrency: 10,
- timeout: 30_000
- )
- |> Enum.to_list()
- end
-
- defp generate_user_data(i) do
- remote = Enum.random([true, false])
-
- user = %User{
- name: "Test テスト User #{i}",
- email: "user#{i}@example.com",
- nickname: "nick#{i}",
- password_hash:
- "$pbkdf2-sha512$160000$bU.OSFI7H/yqWb5DPEqyjw$uKp/2rmXw12QqnRRTqTtuk2DTwZfF8VR4MYW2xMeIlqPR/UX1nT1CEKVUx2CowFMZ5JON8aDvURrZpJjSgqXrg",
- bio: "Tester Number #{i}",
- local: remote
- }
-
- user_urls =
- if remote do
- base_url =
- Enum.random(["https://domain1.com", "https://domain2.com", "https://domain3.com"])
-
- ap_id = "#{base_url}/users/#{user.nickname}"
-
- %{
- ap_id: ap_id,
- follower_address: ap_id <> "/followers",
- following_address: ap_id <> "/following"
- }
- else
- %{
- ap_id: User.ap_id(user),
- follower_address: User.ap_followers(user),
- following_address: User.ap_following(user)
- }
- end
-
- user = Map.merge(user, user_urls)
-
- Repo.insert!(user)
- end
-
- def generate_activities(user, users) do
- do_generate_activities(user, users)
- end
-
- defp do_generate_activities(user, users) do
- IO.puts("Starting generating 20000 common activities...")
-
- {time, _} =
- :timer.tc(fn ->
- Task.async_stream(
- 1..20_000,
- fn _ ->
- do_generate_activity([user | users])
- end,
- max_concurrency: 10,
- timeout: 30_000
- )
- |> Stream.run()
- end)
-
- IO.puts("Inserting common activities take #{to_sec(time)} sec.\n")
-
- IO.puts("Starting generating 20000 activities with mentions...")
-
- {time, _} =
- :timer.tc(fn ->
- Task.async_stream(
- 1..20_000,
- fn _ ->
- do_generate_activity_with_mention(user, users)
- end,
- max_concurrency: 10,
- timeout: 30_000
- )
- |> Stream.run()
- end)
-
- IO.puts("Inserting activities with menthions take #{to_sec(time)} sec.\n")
-
- IO.puts("Starting generating 10000 activities with threads...")
-
- {time, _} =
- :timer.tc(fn ->
- Task.async_stream(
- 1..10_000,
- fn _ ->
- do_generate_threads([user | users])
- end,
- max_concurrency: 10,
- timeout: 30_000
- )
- |> Stream.run()
- end)
-
- IO.puts("Inserting activities with threads take #{to_sec(time)} sec.\n")
- end
-
- defp do_generate_activity(users) do
- post = %{
- "status" => "Some status without mention with random user"
- }
-
- CommonAPI.post(Enum.random(users), post)
- end
-
- def generate_power_intervals(opts \\ []) do
- count = Keyword.get(opts, :count, 20)
- power = Keyword.get(opts, :power, 2)
- IO.puts("Generating #{count} intervals for a power #{power} series...")
- counts = Enum.map(1..count, fn n -> :math.pow(n, power) end)
- sum = Enum.sum(counts)
-
- densities =
- Enum.map(counts, fn c ->
- c / sum
- end)
-
- densities
- |> Enum.reduce(0, fn density, acc ->
- if acc == 0 do
- [{0, density}]
- else
- [{_, lower} | _] = acc
- [{lower, lower + density} | acc]
- end
- end)
- |> Enum.reverse()
- end
-
- def generate_tagged_activities(opts \\ []) do
- tag_count = Keyword.get(opts, :tag_count, 20)
- users = Keyword.get(opts, :users, Repo.all(User))
- activity_count = Keyword.get(opts, :count, 200_000)
-
- intervals = generate_power_intervals(count: tag_count)
-
- IO.puts(
- "Generating #{activity_count} activities using #{tag_count} different tags of format `tag_n`, starting at tag_0"
- )
-
- Enum.each(1..activity_count, fn _ ->
- random = :rand.uniform()
- i = Enum.find_index(intervals, fn {lower, upper} -> lower <= random && upper > random end)
- CommonAPI.post(Enum.random(users), %{"status" => "a post with the tag #tag_#{i}"})
- end)
- end
-
- defp do_generate_activity_with_mention(user, users) do
- mentions_cnt = Enum.random([2, 3, 4, 5])
- with_user = Enum.random([true, false])
- users = Enum.shuffle(users)
- mentions_users = Enum.take(users, mentions_cnt)
- mentions_users = if with_user, do: [user | mentions_users], else: mentions_users
-
- mentions_str =
- Enum.map(mentions_users, fn user -> "@" <> user.nickname end) |> Enum.join(", ")
-
- post = %{
- "status" => mentions_str <> "some status with mentions random users"
- }
-
- CommonAPI.post(Enum.random(users), post)
- end
-
- defp do_generate_threads(users) do
- thread_length = Enum.random([2, 3, 4, 5])
- actor = Enum.random(users)
-
- post = %{
- "status" => "Start of the thread"
- }
-
- {:ok, activity} = CommonAPI.post(actor, post)
-
- Enum.each(1..thread_length, fn _ ->
- user = Enum.random(users)
-
- post = %{
- "status" => "@#{actor.nickname} reply to thread",
- "in_reply_to_status_id" => activity.id
- }
-
- CommonAPI.post(user, post)
- end)
- end
-
- def generate_remote_activities(user, users) do
- do_generate_remote_activities(user, users)
- end
-
- defp do_generate_remote_activities(user, users) do
- IO.puts("Starting generating 10000 remote activities...")
-
- {time, _} =
- :timer.tc(fn ->
- Task.async_stream(
- 1..10_000,
- fn i ->
- do_generate_remote_activity(i, user, users)
- end,
- max_concurrency: 10,
- timeout: 30_000
- )
- |> Stream.run()
- end)
-
- IO.puts("Inserting remote activities take #{to_sec(time)} sec.\n")
- end
-
- defp do_generate_remote_activity(i, user, users) do
- actor = Enum.random(users)
- %{host: host} = URI.parse(actor.ap_id)
- date = Date.utc_today()
- datetime = DateTime.utc_now()
-
- map = %{
- "actor" => actor.ap_id,
- "cc" => [actor.follower_address, user.ap_id],
- "context" => "tag:mastodon.example.org,#{date}:objectId=#{i}:objectType=Conversation",
- "id" => actor.ap_id <> "/statuses/#{i}/activity",
- "object" => %{
- "actor" => actor.ap_id,
- "atomUri" => actor.ap_id <> "/statuses/#{i}",
- "attachment" => [],
- "attributedTo" => actor.ap_id,
- "bcc" => [],
- "bto" => [],
- "cc" => [actor.follower_address, user.ap_id],
- "content" =>
- "<p><span class=\"h-card\"><a href=\"" <>
- user.ap_id <>
- "\" class=\"u-url mention\">@<span>" <> user.nickname <> "</span></a></span></p>",
- "context" => "tag:mastodon.example.org,#{date}:objectId=#{i}:objectType=Conversation",
- "conversation" =>
- "tag:mastodon.example.org,#{date}:objectId=#{i}:objectType=Conversation",
- "emoji" => %{},
- "id" => actor.ap_id <> "/statuses/#{i}",
- "inReplyTo" => nil,
- "inReplyToAtomUri" => nil,
- "published" => datetime,
- "sensitive" => true,
- "summary" => "cw",
- "tag" => [
- %{
- "href" => user.ap_id,
- "name" => "@#{user.nickname}@#{host}",
- "type" => "Mention"
- }
- ],
- "to" => ["https://www.w3.org/ns/activitystreams#Public"],
- "type" => "Note",
- "url" => "http://#{host}/@#{actor.nickname}/#{i}"
- },
- "published" => datetime,
- "to" => ["https://www.w3.org/ns/activitystreams#Public"],
- "type" => "Create"
- }
-
- Pleroma.Web.ActivityPub.ActivityPub.insert(map, false)
- end
-
- def generate_dms(user, users, opts) do
- IO.puts("Starting generating #{opts[:dms_max]} DMs")
- {time, _} = :timer.tc(fn -> do_generate_dms(user, users, opts) end)
- IO.puts("Inserting dms take #{to_sec(time)} sec.\n")
- end
-
- defp do_generate_dms(user, users, opts) do
- Task.async_stream(
- 1..opts[:dms_max],
- fn _ ->
- do_generate_dm(user, users)
- end,
- max_concurrency: 10,
- timeout: 30_000
- )
- |> Stream.run()
- end
-
- defp do_generate_dm(user, users) do
- post = %{
- "status" => "@#{user.nickname} some direct message",
- "visibility" => "direct"
- }
-
- CommonAPI.post(Enum.random(users), post)
- end
-
- def generate_long_thread(user, users, opts) do
- IO.puts("Starting generating long thread with #{opts[:thread_length]} replies")
- {time, activity} = :timer.tc(fn -> do_generate_long_thread(user, users, opts) end)
- IO.puts("Inserting long thread replies take #{to_sec(time)} sec.\n")
- {:ok, activity}
- end
-
- defp do_generate_long_thread(user, users, opts) do
- {:ok, %{id: id} = activity} = CommonAPI.post(user, %{"status" => "Start of long thread"})
-
- Task.async_stream(
- 1..opts[:thread_length],
- fn _ -> do_generate_thread(users, id) end,
- max_concurrency: 10,
- timeout: 30_000
- )
- |> Stream.run()
-
- activity
- end
-
- defp do_generate_thread(users, activity_id) do
- CommonAPI.post(Enum.random(users), %{
- "status" => "reply to main post",
- "in_reply_to_status_id" => activity_id
- })
- end
-
- def generate_non_visible_message(user, users) do
- IO.puts("Starting generating 1000 non visible posts")
-
- {time, _} =
- :timer.tc(fn ->
- do_generate_non_visible_posts(user, users)
- end)
-
- IO.puts("Inserting non visible posts take #{to_sec(time)} sec.\n")
- end
-
- defp do_generate_non_visible_posts(user, users) do
- [not_friend | users] = users
-
- make_friends(user, users)
-
- Task.async_stream(1..1000, fn _ -> do_generate_non_visible_post(not_friend, users) end,
- max_concurrency: 10,
- timeout: 30_000
- )
- |> Stream.run()
- end
-
- defp make_friends(_user, []), do: nil
-
- defp make_friends(user, [friend | users]) do
- {:ok, _} = User.follow(user, friend)
- {:ok, _} = User.follow(friend, user)
- make_friends(user, users)
- end
-
- defp do_generate_non_visible_post(not_friend, users) do
- post = %{
- "status" => "some non visible post",
- "visibility" => "private"
- }
-
- {:ok, activity} = CommonAPI.post(not_friend, post)
-
- thread_length = Enum.random([2, 3, 4, 5])
-
- Enum.each(1..thread_length, fn _ ->
- user = Enum.random(users)
-
- post = %{
- "status" => "@#{not_friend.nickname} reply to non visible post",
- "in_reply_to_status_id" => activity.id,
- "visibility" => "private"
- }
-
- CommonAPI.post(user, post)
- end)
- end
-end
diff --git a/benchmarks/load_testing/helper.ex b/benchmarks/load_testing/helper.ex
index 47b25c65f..cab60acb4 100644
--- a/benchmarks/load_testing/helper.ex
+++ b/benchmarks/load_testing/helper.ex
@@ -1,11 +1,14 @@
defmodule Pleroma.LoadTesting.Helper do
- defmacro __using__(_) do
- quote do
- import Ecto.Query
- alias Pleroma.Repo
- alias Pleroma.User
+ alias Ecto.Adapters.SQL
+ alias Pleroma.Repo
- defp to_sec(microseconds), do: microseconds / 1_000_000
- end
+ def to_sec(microseconds), do: microseconds / 1_000_000
+
+ def clean_tables do
+ IO.puts("Deleting old data...\n")
+ SQL.query!(Repo, "TRUNCATE users CASCADE;")
+ SQL.query!(Repo, "TRUNCATE activities CASCADE;")
+ SQL.query!(Repo, "TRUNCATE objects CASCADE;")
+ SQL.query!(Repo, "TRUNCATE oban_jobs CASCADE;")
end
end
diff --git a/benchmarks/load_testing/users.ex b/benchmarks/load_testing/users.ex
new file mode 100644
index 000000000..6cf3958c1
--- /dev/null
+++ b/benchmarks/load_testing/users.ex
@@ -0,0 +1,189 @@
+defmodule Pleroma.LoadTesting.Users do
+ @moduledoc """
+ Module for generating users with friends.
+ """
+ import Ecto.Query
+ import Pleroma.LoadTesting.Helper, only: [to_sec: 1]
+
+ alias Pleroma.Repo
+ alias Pleroma.User
+ alias Pleroma.User.Query
+
+ @defaults [
+ users: 20_000,
+ friends: 100
+ ]
+
+ @max_concurrency 10
+
+ @spec generate(keyword()) :: User.t()
+ def generate(opts \\ []) do
+ opts = Keyword.merge(@defaults, opts)
+
+ generate_users(opts[:users])
+
+ main_user =
+ Repo.one(from(u in User, where: u.local == true, order_by: fragment("RANDOM()"), limit: 1))
+
+ make_friends(main_user, opts[:friends])
+
+ User.get_by_id(main_user.id)
+ end
+
+ def generate_users(max) do
+ IO.puts("Starting generating #{max} users...")
+
+ {time, users} =
+ :timer.tc(fn ->
+ Task.async_stream(
+ 1..max,
+ &generate_user(&1),
+ max_concurrency: @max_concurrency,
+ timeout: 30_000
+ )
+ |> Enum.to_list()
+ end)
+
+ IO.puts("Generating users took #{to_sec(time)} sec.\n")
+ users
+ end
+
+ defp generate_user(i) do
+ remote = Enum.random([true, false])
+
+ %User{
+ name: "Test テスト User #{i}",
+ email: "user#{i}@example.com",
+ nickname: "nick#{i}",
+ password_hash: Pbkdf2.hash_pwd_salt("test"),
+ bio: "Tester Number #{i}",
+ local: !remote
+ }
+ |> user_urls()
+ |> Repo.insert!()
+ end
+
+ defp user_urls(%{local: true} = user) do
+ urls = %{
+ ap_id: User.ap_id(user),
+ follower_address: User.ap_followers(user),
+ following_address: User.ap_following(user)
+ }
+
+ Map.merge(user, urls)
+ end
+
+ defp user_urls(%{local: false} = user) do
+ base_domain = Enum.random(["domain1.com", "domain2.com", "domain3.com"])
+
+ ap_id = "https://#{base_domain}/users/#{user.nickname}"
+
+ urls = %{
+ ap_id: ap_id,
+ follower_address: ap_id <> "/followers",
+ following_address: ap_id <> "/following"
+ }
+
+ Map.merge(user, urls)
+ end
+
+ def make_friends(main_user, max) when is_integer(max) do
+ IO.puts("Starting making friends for #{max} users...")
+
+ {time, _} =
+ :timer.tc(fn ->
+ number_of_users =
+ (max / 2)
+ |> Kernel.trunc()
+
+ main_user
+ |> get_users(%{limit: number_of_users, local: :local})
+ |> run_stream(main_user)
+
+ main_user
+ |> get_users(%{limit: number_of_users, local: :external})
+ |> run_stream(main_user)
+ end)
+
+ IO.puts("Making friends took #{to_sec(time)} sec.\n")
+ end
+
+ def make_friends(%User{} = main_user, %User{} = user) do
+ {:ok, _} = User.follow(main_user, user)
+ {:ok, _} = User.follow(user, main_user)
+ end
+
+ @spec get_users(User.t(), keyword()) :: [User.t()]
+ def get_users(user, opts) do
+ criteria = %{limit: opts[:limit]}
+
+ criteria =
+ if opts[:local] do
+ Map.put(criteria, opts[:local], true)
+ else
+ criteria
+ end
+
+ criteria =
+ if opts[:friends?] do
+ Map.put(criteria, :friends, user)
+ else
+ criteria
+ end
+
+ query =
+ criteria
+ |> Query.build()
+ |> random_without_user(user)
+
+ query =
+ if opts[:friends?] == false do
+ friends_ids =
+ %{friends: user}
+ |> Query.build()
+ |> Repo.all()
+ |> Enum.map(& &1.id)
+
+ from(u in query, where: u.id not in ^friends_ids)
+ else
+ query
+ end
+
+ Repo.all(query)
+ end
+
+ defp random_without_user(query, user) do
+ from(u in query,
+ where: u.id != ^user.id,
+ order_by: fragment("RANDOM()")
+ )
+ end
+
+ defp run_stream(users, main_user) do
+ Task.async_stream(users, &make_friends(main_user, &1),
+ max_concurrency: @max_concurrency,
+ timeout: 30_000
+ )
+ |> Stream.run()
+ end
+
+ @spec prepare_users(User.t(), keyword()) :: map()
+ def prepare_users(user, opts) do
+ friends_limit = opts[:friends_used]
+ non_friends_limit = opts[:non_friends_used]
+
+ %{
+ user: user,
+ friends_local: fetch_users(user, friends_limit, :local, true),
+ friends_remote: fetch_users(user, friends_limit, :external, true),
+ non_friends_local: fetch_users(user, non_friends_limit, :local, false),
+ non_friends_remote: fetch_users(user, non_friends_limit, :external, false)
+ }
+ end
+
+ defp fetch_users(user, limit, local, friends?) do
+ user
+ |> get_users(limit: limit, local: local, friends?: friends?)
+ |> Enum.shuffle()
+ end
+end
diff --git a/benchmarks/mix/tasks/pleroma/benchmarks/tags.ex b/benchmarks/mix/tasks/pleroma/benchmarks/tags.ex
index fd1506907..c051335a5 100644
--- a/benchmarks/mix/tasks/pleroma/benchmarks/tags.ex
+++ b/benchmarks/mix/tasks/pleroma/benchmarks/tags.ex
@@ -1,9 +1,11 @@
defmodule Mix.Tasks.Pleroma.Benchmarks.Tags do
use Mix.Task
- alias Pleroma.Repo
- alias Pleroma.LoadTesting.Generator
+
+ import Pleroma.LoadTesting.Helper, only: [clean_tables: 0]
import Ecto.Query
+ alias Pleroma.Repo
+
def run(_args) do
Mix.Pleroma.start_pleroma()
activities_count = Repo.aggregate(from(a in Pleroma.Activity), :count, :id)
@@ -11,8 +13,8 @@ defmodule Mix.Tasks.Pleroma.Benchmarks.Tags do
if activities_count == 0 do
IO.puts("Did not find any activities, cleaning and generating")
clean_tables()
- Generator.generate_users(users_max: 10)
- Generator.generate_tagged_activities()
+ Pleroma.LoadTesting.Users.generate_users(10)
+ Pleroma.LoadTesting.Activities.generate_tagged_activities()
else
IO.puts("Found #{activities_count} activities, won't generate new ones")
end
@@ -34,7 +36,7 @@ defmodule Mix.Tasks.Pleroma.Benchmarks.Tags do
Benchee.run(
%{
"Hashtag fetching, any" => fn tags ->
- Pleroma.Web.MastodonAPI.TimelineController.hashtag_fetching(
+ hashtag_fetching(
%{
"any" => tags
},
@@ -44,7 +46,7 @@ defmodule Mix.Tasks.Pleroma.Benchmarks.Tags do
end,
# Will always return zero results because no overlapping hashtags are generated.
"Hashtag fetching, all" => fn tags ->
- Pleroma.Web.MastodonAPI.TimelineController.hashtag_fetching(
+ hashtag_fetching(
%{
"all" => tags
},
@@ -64,7 +66,7 @@ defmodule Mix.Tasks.Pleroma.Benchmarks.Tags do
Benchee.run(
%{
"Hashtag fetching" => fn tag ->
- Pleroma.Web.MastodonAPI.TimelineController.hashtag_fetching(
+ hashtag_fetching(
%{
"tag" => tag
},
@@ -78,10 +80,34 @@ defmodule Mix.Tasks.Pleroma.Benchmarks.Tags do
)
end
- defp clean_tables do
- IO.puts("Deleting old data...\n")
- Ecto.Adapters.SQL.query!(Repo, "TRUNCATE users CASCADE;")
- Ecto.Adapters.SQL.query!(Repo, "TRUNCATE activities CASCADE;")
- Ecto.Adapters.SQL.query!(Repo, "TRUNCATE objects CASCADE;")
+ defp hashtag_fetching(params, user, local_only) do
+ tags =
+ [params["tag"], params["any"]]
+ |> List.flatten()
+ |> Enum.uniq()
+ |> Enum.filter(& &1)
+ |> Enum.map(&String.downcase(&1))
+
+ tag_all =
+ params
+ |> Map.get("all", [])
+ |> Enum.map(&String.downcase(&1))
+
+ tag_reject =
+ params
+ |> Map.get("none", [])
+ |> Enum.map(&String.downcase(&1))
+
+ _activities =
+ params
+ |> Map.put(:type, "Create")
+ |> Map.put(:local_only, local_only)
+ |> Map.put(:blocking_user, user)
+ |> Map.put(:muting_user, user)
+ |> Map.put(:user, user)
+ |> Map.put(:tag, tags)
+ |> Map.put(:tag_all, tag_all)
+ |> Map.put(:tag_reject, tag_reject)
+ |> Pleroma.Web.ActivityPub.ActivityPub.fetch_public_activities()
end
end
diff --git a/benchmarks/mix/tasks/pleroma/benchmarks/timelines.ex b/benchmarks/mix/tasks/pleroma/benchmarks/timelines.ex
new file mode 100644
index 000000000..9b7ac6111
--- /dev/null
+++ b/benchmarks/mix/tasks/pleroma/benchmarks/timelines.ex
@@ -0,0 +1,70 @@
+defmodule Mix.Tasks.Pleroma.Benchmarks.Timelines do
+ use Mix.Task
+
+ import Pleroma.LoadTesting.Helper, only: [clean_tables: 0]
+
+ alias Pleroma.Web.CommonAPI
+ alias Plug.Conn
+
+ def run(_args) do
+ Mix.Pleroma.start_pleroma()
+
+ # Cleaning tables
+ clean_tables()
+
+ [{:ok, user} | users] = Pleroma.LoadTesting.Users.generate_users(1000)
+
+ # Let the user make 100 posts
+
+ 1..100
+ |> Enum.each(fn i -> CommonAPI.post(user, %{"status" => to_string(i)}) end)
+
+ # Let 10 random users post
+ posts =
+ users
+ |> Enum.take_random(10)
+ |> Enum.map(fn {:ok, random_user} ->
+ {:ok, activity} = CommonAPI.post(random_user, %{"status" => "."})
+ activity
+ end)
+
+ # let our user repeat them
+ posts
+ |> Enum.each(fn activity ->
+ CommonAPI.repeat(activity.id, user)
+ end)
+
+ Benchee.run(
+ %{
+ "user timeline, no followers" => fn reading_user ->
+ conn =
+ Phoenix.ConnTest.build_conn()
+ |> Conn.assign(:user, reading_user)
+ |> Conn.assign(:skip_link_headers, true)
+
+ Pleroma.Web.MastodonAPI.AccountController.statuses(conn, %{"id" => user.id})
+ end
+ },
+ inputs: %{"user" => user, "no user" => nil},
+ time: 60
+ )
+
+ users
+ |> Enum.each(fn {:ok, follower} -> Pleroma.User.follow(follower, user) end)
+
+ Benchee.run(
+ %{
+ "user timeline, all following" => fn reading_user ->
+ conn =
+ Phoenix.ConnTest.build_conn()
+ |> Conn.assign(:user, reading_user)
+ |> Conn.assign(:skip_link_headers, true)
+
+ Pleroma.Web.MastodonAPI.AccountController.statuses(conn, %{"id" => user.id})
+ end
+ },
+ inputs: %{"user" => user, "no user" => nil},
+ time: 60
+ )
+ end
+end
diff --git a/benchmarks/mix/tasks/pleroma/load_testing.ex b/benchmarks/mix/tasks/pleroma/load_testing.ex
index 0a751adac..388883240 100644
--- a/benchmarks/mix/tasks/pleroma/load_testing.ex
+++ b/benchmarks/mix/tasks/pleroma/load_testing.ex
@@ -1,114 +1,56 @@
defmodule Mix.Tasks.Pleroma.LoadTesting do
use Mix.Task
- use Pleroma.LoadTesting.Helper
- import Mix.Pleroma
- import Pleroma.LoadTesting.Generator
- import Pleroma.LoadTesting.Fetcher
+ import Ecto.Query
+ import Pleroma.LoadTesting.Helper, only: [clean_tables: 0]
+
+ alias Pleroma.Repo
+ alias Pleroma.User
@shortdoc "Factory for generation data"
@moduledoc """
Generates data like:
- local/remote users
- - local/remote activities with notifications
- - direct messages
- - long thread
- - non visible posts
+ - local/remote activities with differrent visibility:
+ - simple activiities
+ - with emoji
+ - with mentions
+ - hellthreads
+ - with attachments
+ - with tags
+ - likes
+ - reblogs
+ - simple threads
+ - long threads
## Generate data
- MIX_ENV=benchmark mix pleroma.load_testing --users 20000 --dms 20000 --thread_length 2000
- MIX_ENV=benchmark mix pleroma.load_testing -u 20000 -d 20000 -t 2000
+ MIX_ENV=benchmark mix pleroma.load_testing --users 20000 --friends 1000 --iterations 170 --friends_used 20 --non_friends_used 20
+ MIX_ENV=benchmark mix pleroma.load_testing -u 20000 -f 1000 -i 170 -fu 20 -nfu 20
Options:
- `--users NUMBER` - number of users to generate. Defaults to: 20000. Alias: `-u`
- - `--dms NUMBER` - number of direct messages to generate. Defaults to: 20000. Alias `-d`
- - `--thread_length` - number of messages in thread. Defaults to: 2000. ALias `-t`
+ - `--friends NUMBER` - number of friends for main user. Defaults to: 1000. Alias: `-f`
+ - `--iterations NUMBER` - number of iterations to generate activities. For each iteration in database is inserted about 120+ activities with different visibility, actors and types.Defaults to: 170. Alias: `-i`
+ - `--friends_used NUMBER` - number of main user friends used in activity generation. Defaults to: 20. Alias: `-fu`
+ - `--non_friends_used NUMBER` - number of non friends used in activity generation. Defaults to: 20. Alias: `-nfu`
"""
- @aliases [u: :users, d: :dms, t: :thread_length]
+ @aliases [u: :users, f: :friends, i: :iterations, fu: :friends_used, nfu: :non_friends_used]
@switches [
users: :integer,
- dms: :integer,
- thread_length: :integer
+ friends: :integer,
+ iterations: :integer,
+ friends_used: :integer,
+ non_friends_used: :integer
]
- @users_default 20_000
- @dms_default 1_000
- @thread_length_default 2_000
def run(args) do
- start_pleroma()
- Pleroma.Config.put([:instance, :skip_thread_containment], true)
- {opts, _} = OptionParser.parse!(args, strict: @switches, aliases: @aliases)
-
- users_max = Keyword.get(opts, :users, @users_default)
- dms_max = Keyword.get(opts, :dms, @dms_default)
- thread_length = Keyword.get(opts, :thread_length, @thread_length_default)
-
+ Logger.configure(level: :error)
+ Mix.Pleroma.start_pleroma()
clean_tables()
+ {opts, _} = OptionParser.parse!(args, strict: @switches, aliases: @aliases)
- opts =
- Keyword.put(opts, :users_max, users_max)
- |> Keyword.put(:dms_max, dms_max)
- |> Keyword.put(:thread_length, thread_length)
-
- generate_users(opts)
-
- # main user for queries
- IO.puts("Fetching local main user...")
-
- {time, user} =
- :timer.tc(fn ->
- Repo.one(
- from(u in User, where: u.local == true, order_by: fragment("RANDOM()"), limit: 1)
- )
- end)
-
- IO.puts("Fetching main user take #{to_sec(time)} sec.\n")
-
- IO.puts("Fetching local users...")
-
- {time, users} =
- :timer.tc(fn ->
- Repo.all(
- from(u in User,
- where: u.id != ^user.id,
- where: u.local == true,
- order_by: fragment("RANDOM()"),
- limit: 10
- )
- )
- end)
-
- IO.puts("Fetching local users take #{to_sec(time)} sec.\n")
-
- IO.puts("Fetching remote users...")
-
- {time, remote_users} =
- :timer.tc(fn ->
- Repo.all(
- from(u in User,
- where: u.id != ^user.id,
- where: u.local == false,
- order_by: fragment("RANDOM()"),
- limit: 10
- )
- )
- end)
-
- IO.puts("Fetching remote users take #{to_sec(time)} sec.\n")
-
- generate_activities(user, users)
-
- generate_remote_activities(user, remote_users)
-
- generate_like_activities(
- user, Pleroma.Repo.all(Pleroma.Activity.Queries.by_type("Create"))
- )
-
- generate_dms(user, users, opts)
-
- {:ok, activity} = generate_long_thread(user, users, opts)
-
- generate_non_visible_message(user, users)
+ user = Pleroma.LoadTesting.Users.generate(opts)
+ Pleroma.LoadTesting.Activities.generate(user, opts)
IO.puts("Users in DB: #{Repo.aggregate(from(u in User), :count, :id)}")
@@ -120,19 +62,6 @@ defmodule Mix.Tasks.Pleroma.LoadTesting do
"Notifications in DB: #{Repo.aggregate(from(n in Pleroma.Notification), :count, :id)}"
)
- fetch_user(user)
- query_timelines(user)
- query_notifications(user)
- query_dms(user)
- query_long_thread(user, activity)
- Pleroma.Config.put([:instance, :skip_thread_containment], false)
- query_timelines(user)
- end
-
- defp clean_tables do
- IO.puts("Deleting old data...\n")
- Ecto.Adapters.SQL.query!(Repo, "TRUNCATE users CASCADE;")
- Ecto.Adapters.SQL.query!(Repo, "TRUNCATE activities CASCADE;")
- Ecto.Adapters.SQL.query!(Repo, "TRUNCATE objects CASCADE;")
+ Pleroma.LoadTesting.Fetcher.run_benchmarks(user)
end
end
diff --git a/config/benchmark.exs b/config/benchmark.exs
index 84c6782a2..e867253eb 100644
--- a/config/benchmark.exs
+++ b/config/benchmark.exs
@@ -39,7 +39,7 @@ config :pleroma, Pleroma.Repo,
adapter: Ecto.Adapters.Postgres,
username: "postgres",
password: "postgres",
- database: "pleroma_test",
+ database: "pleroma_benchmark",
hostname: System.get_env("DB_HOST") || "localhost",
pool_size: 10
@@ -61,8 +61,6 @@ config :web_push_encryption, :vapid_details,
config :web_push_encryption, :http_client, Pleroma.Web.WebPushHttpClientMock
-config :pleroma_job_queue, disabled: true
-
config :pleroma, Pleroma.ScheduledActivity,
daily_user_limit: 2,
total_user_limit: 3,
diff --git a/config/config.exs b/config/config.exs
index 5eb1c7583..246712b9f 100644
--- a/config/config.exs
+++ b/config/config.exs
@@ -58,20 +58,6 @@ config :pleroma, Pleroma.Captcha,
config :pleroma, Pleroma.Captcha.Kocaptcha, endpoint: "https://captcha.kotobank.ch"
-config :pleroma, :hackney_pools,
- federation: [
- max_connections: 50,
- timeout: 150_000
- ],
- media: [
- max_connections: 50,
- timeout: 150_000
- ],
- upload: [
- max_connections: 25,
- timeout: 300_000
- ]
-
# Upload configuration
config :pleroma, Pleroma.Upload,
uploader: Pleroma.Uploaders.Local,
@@ -85,7 +71,9 @@ config :pleroma, Pleroma.Upload,
follow_redirect: true,
pool: :upload
]
- ]
+ ],
+ filename_display_max_length: 30,
+ default_description: nil
config :pleroma, Pleroma.Uploaders.Local, uploads: "uploads"
@@ -110,6 +98,7 @@ config :pleroma, :uri_schemes,
"dat",
"dweb",
"gopher",
+ "hyper",
"ipfs",
"ipns",
"irc",
@@ -190,14 +179,18 @@ config :tesla, adapter: Tesla.Adapter.Hackney
config :pleroma, :http,
proxy_url: nil,
send_user_agent: true,
- user_agent: :default
+ user_agent: :default,
+ adapter: []
config :pleroma, :instance,
name: "Pleroma",
email: "example@example.com",
notify_email: "noreply@example.com",
- description: "A Pleroma instance, an alternative fediverse server",
+ description: "Pleroma: An efficient and flexible fediverse server",
+ background_image: "/images/city.jpg",
+ instance_thumbnail: "/instance/thumbnail.jpeg",
limit: 5_000,
+ description_limit: 5_000,
chat_limit: 5_000,
remote_limit: 100_000,
upload_limit: 16_000_000,
@@ -213,6 +206,7 @@ config :pleroma, :instance,
registrations_open: true,
invites_enabled: false,
account_activation_required: false,
+ account_approval_required: false,
federating: true,
federation_incoming_replies_max_depth: 100,
federation_reachability_timeout_days: 7,
@@ -220,7 +214,6 @@ config :pleroma, :instance,
Pleroma.Web.ActivityPub.Publisher
],
allow_relay: true,
- rewrite_policy: Pleroma.Web.ActivityPub.MRF.NoOpPolicy,
public: true,
quarantined_instances: [],
managed_config: true,
@@ -231,13 +224,9 @@ config :pleroma, :instance,
"text/markdown",
"text/bbcode"
],
- mrf_transparency: true,
- mrf_transparency_exclusions: [],
autofollowed_nicknames: [],
max_pinned_statuses: 1,
attachment_links: false,
- welcome_user_nickname: nil,
- welcome_message: nil,
max_report_comment_size: 1000,
safe_dm_mentions: false,
healthcheck: false,
@@ -250,9 +239,41 @@ config :pleroma, :instance,
max_remote_account_fields: 20,
account_field_name_length: 512,
account_field_value_length: 2048,
+ registration_reason_length: 500,
external_user_synchronization: true,
extended_nickname_format: true,
- cleanup_attachments: false
+ cleanup_attachments: false,
+ multi_factor_authentication: [
+ totp: [
+ # digits 6 or 8
+ digits: 6,
+ period: 30
+ ],
+ backup_codes: [
+ number: 5,
+ length: 16
+ ]
+ ],
+ show_reactions: true
+
+config :pleroma, :welcome,
+ direct_message: [
+ enabled: false,
+ sender_nickname: nil,
+ message: nil
+ ],
+ chat_message: [
+ enabled: false,
+ sender_nickname: nil,
+ message: nil
+ ],
+ email: [
+ enabled: false,
+ sender: nil,
+ subject: "Welcome to <%= instance_name %>",
+ html: "Welcome to <%= instance_name %>",
+ text: "Welcome to <%= instance_name %>"
+ ]
config :pleroma, :feed,
post_title: %{
@@ -274,20 +295,33 @@ config :pleroma, :markup,
config :pleroma, :frontend_configurations,
pleroma_fe: %{
- theme: "pleroma-dark",
- logo: "/static/logo.png",
+ alwaysShowSubjectInput: true,
background: "/images/city.jpg",
- redirectRootNoLogin: "/main/all",
- redirectRootLogin: "/main/friends",
- showInstanceSpecificPanel: true,
- scopeOptionsEnabled: false,
- formattingOptionsEnabled: false,
collapseMessageWithSubject: false,
+ disableChat: false,
+ greentext: false,
+ hideFilteredStatuses: false,
+ hideMutedPosts: false,
hidePostStats: false,
+ hideSitename: false,
hideUserStats: false,
+ loginMethod: "password",
+ logo: "/static/logo.png",
+ logoMargin: ".1em",
+ logoMask: true,
+ minimalScopesMode: false,
+ noAttachmentLinks: false,
+ nsfwCensorImage: "",
+ postContentType: "text/plain",
+ redirectRootLogin: "/main/friends",
+ redirectRootNoLogin: "/main/all",
scopeCopy: true,
+ sidebarRight: false,
+ showFeaturesPanel: true,
+ showInstanceSpecificPanel: false,
subjectLineBehavior: "email",
- alwaysShowSubjectInput: true
+ theme: "pleroma-dark",
+ webPushNotifications: false
},
masto_fe: %{
showInstanceSpecificPanel: true
@@ -346,9 +380,11 @@ config :pleroma, :mrf_simple,
federated_timeline_removal: [],
report_removal: [],
reject: [],
+ followers_only: [],
accept: [],
avatar_removal: [],
- banner_removal: []
+ banner_removal: [],
+ reject_deletes: []
config :pleroma, :mrf_keyword,
reject: [],
@@ -357,12 +393,15 @@ config :pleroma, :mrf_keyword,
config :pleroma, :mrf_subchain, match_actor: %{}
+config :pleroma, :mrf_activity_expiration, days: 365
+
config :pleroma, :mrf_vocabulary,
accept: [],
reject: []
+# threshold of 7 days
config :pleroma, :mrf_object_age,
- threshold: 172_800,
+ threshold: 604_800,
actions: [:delist, :strip_followers]
config :pleroma, :rich_media,
@@ -371,13 +410,16 @@ config :pleroma, :rich_media,
ignore_tld: ["local", "localdomain", "lan"],
parsers: [
Pleroma.Web.RichMedia.Parsers.TwitterCard,
- Pleroma.Web.RichMedia.Parsers.OGP,
Pleroma.Web.RichMedia.Parsers.OEmbed
],
ttl_setters: [Pleroma.Web.RichMedia.Parser.TTL.AwsSignedUrl]
config :pleroma, :media_proxy,
enabled: false,
+ invalidation: [
+ enabled: false,
+ provider: Pleroma.Web.MediaProxy.Invalidation.Script
+ ],
proxy_opts: [
redirect_on_failure: false,
max_body_length: 25 * 1_048_576,
@@ -388,6 +430,13 @@ config :pleroma, :media_proxy,
],
whitelist: []
+config :pleroma, Pleroma.Web.MediaProxy.Invalidation.Http,
+ method: :purge,
+ headers: [],
+ options: []
+
+config :pleroma, Pleroma.Web.MediaProxy.Invalidation.Script, script_path: nil
+
config :pleroma, :chat, enabled: true
config :phoenix, :format_encoders, json: Jason
@@ -410,6 +459,11 @@ config :pleroma, Pleroma.Web.Metadata,
],
unfurl_nsfw: false
+config :pleroma, Pleroma.Web.Preload,
+ providers: [
+ Pleroma.Web.Preload.Providers.Instance
+ ]
+
config :pleroma, :http_security,
enabled: true,
sts: false,
@@ -462,13 +516,19 @@ config :pleroma, Pleroma.User,
"user-search",
"user_exists",
"users",
- "web"
- ]
+ "web",
+ "verify_credentials",
+ "update_credentials",
+ "relationships",
+ "search",
+ "confirmation_resend",
+ "mfa"
+ ],
+ email_blacklist: []
config :pleroma, Oban,
repo: Pleroma.Repo,
- verbose: false,
- prune: {:maxlen, 1500},
+ log: false,
queues: [
activity_expiration: 10,
federator_incoming: 50,
@@ -482,6 +542,7 @@ config :pleroma, Oban,
attachments_cleanup: 5,
new_users_digest: 1
],
+ plugins: [Oban.Plugins.Pruner],
crontab: [
{"0 0 * * *", Pleroma.Workers.Cron.ClearOauthTokenWorker},
{"0 * * * *", Pleroma.Workers.Cron.StatsWorker},
@@ -496,16 +557,14 @@ config :pleroma, :workers,
federator_outgoing: 5
]
-config :auto_linker,
- opts: [
- extra: true,
- # TODO: Set to :no_scheme when it works properly
- validate_tld: true,
- class: false,
- strip_prefix: false,
- new_window: false,
- rel: "ugc"
- ]
+config :pleroma, Pleroma.Formatter,
+ class: false,
+ rel: "ugc",
+ new_window: false,
+ truncate: false,
+ strip_prefix: false,
+ extra: true,
+ validate_tld: :no_scheme
config :pleroma, :ldap,
enabled: System.get_env("LDAP_ENABLED") == "true",
@@ -604,6 +663,59 @@ config :pleroma, Pleroma.Plugs.RemoteIp, enabled: true
config :pleroma, :static_fe, enabled: false
+# Example of frontend configuration
+# This example will make us serve the primary frontend from the
+# frontends directory within your `:pleroma, :instance, static_dir`.
+# e.g., instance/static/frontends/pleroma/develop/
+#
+# With no frontend configuration, the bundled files from the `static` directory will
+# be used.
+#
+# config :pleroma, :frontends,
+# primary: %{"name" => "pleroma-fe", "ref" => "develop"},
+# admin: %{"name" => "admin-fe", "ref" => "stable"},
+# available: %{...}
+
+config :pleroma, :frontends,
+ available: %{
+ "kenoma" => %{
+ "name" => "kenoma",
+ "git" => "https://git.pleroma.social/lambadalambda/kenoma",
+ "build_url" =>
+ "https://git.pleroma.social/lambadalambda/kenoma/-/jobs/artifacts/${ref}/download?job=build",
+ "ref" => "master"
+ },
+ "pleroma-fe" => %{
+ "name" => "pleroma-fe",
+ "git" => "https://git.pleroma.social/pleroma/pleroma-fe",
+ "build_url" =>
+ "https://git.pleroma.social/pleroma/pleroma-fe/-/jobs/artifacts/${ref}/download?job=build",
+ "ref" => "develop"
+ },
+ "fedi-fe" => %{
+ "name" => "fedi-fe",
+ "git" => "https://git.pleroma.social/pleroma/fedi-fe",
+ "build_url" =>
+ "https://git.pleroma.social/pleroma/fedi-fe/-/jobs/artifacts/${ref}/download?job=build",
+ "ref" => "master"
+ },
+ "admin-fe" => %{
+ "name" => "admin-fe",
+ "git" => "https://git.pleroma.social/pleroma/admin-fe",
+ "build_url" =>
+ "https://git.pleroma.social/pleroma/admin-fe/-/jobs/artifacts/${ref}/download?job=build",
+ "ref" => "develop"
+ },
+ "soapbox-fe" => %{
+ "name" => "soapbox-fe",
+ "git" => "https://gitlab.com/soapbox-pub/soapbox-fe",
+ "build_url" =>
+ "https://gitlab.com/soapbox-pub/soapbox-fe/-/jobs/artifacts/${ref}/download?job=build-production",
+ "ref" => "v1.0.0",
+ "build_dir" => "static"
+ }
+ }
+
config :pleroma, :web_cache_ttl,
activity_pub: nil,
activity_pub_question: 30_000
@@ -616,6 +728,71 @@ config :pleroma, Pleroma.Repo,
parameters: [gin_fuzzy_search_limit: "500"],
prepare: :unnamed
+config :pleroma, :connections_pool,
+ reclaim_multiplier: 0.1,
+ connection_acquisition_wait: 250,
+ connection_acquisition_retries: 5,
+ max_connections: 250,
+ max_idle_time: 30_000,
+ retry: 0,
+ await_up_timeout: 5_000
+
+config :pleroma, :pools,
+ federation: [
+ size: 50,
+ max_waiting: 10
+ ],
+ media: [
+ size: 50,
+ max_waiting: 10
+ ],
+ upload: [
+ size: 25,
+ max_waiting: 5
+ ],
+ default: [
+ size: 10,
+ max_waiting: 2
+ ]
+
+config :pleroma, :hackney_pools,
+ federation: [
+ max_connections: 50,
+ timeout: 150_000
+ ],
+ media: [
+ max_connections: 50,
+ timeout: 150_000
+ ],
+ upload: [
+ max_connections: 25,
+ timeout: 300_000
+ ]
+
+private_instance? = :if_instance_is_private
+
+config :pleroma, :restrict_unauthenticated,
+ timelines: %{local: private_instance?, federated: private_instance?},
+ profiles: %{local: private_instance?, remote: private_instance?},
+ activities: %{local: private_instance?, remote: private_instance?}
+
+config :pleroma, Pleroma.Web.ApiSpec.CastAndValidate, strict: false
+
+config :pleroma, :mrf,
+ policies: Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy,
+ transparency: true,
+ transparency_exclusions: []
+
+config :tzdata, :http_client, Pleroma.HTTP.Tzdata
+
+config :ex_aws, http_client: Pleroma.HTTP.ExAws
+
+config :pleroma, :instances_favicons, enabled: false
+
+config :floki, :html_parser, Floki.HTMLParser.FastHtml
+
+config :pleroma, Pleroma.Web.Auth.Authenticator, Pleroma.Web.Auth.PleromaAuthenticator
+
# Import environment specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above.
import_config "#{Mix.env()}.exs"
diff --git a/config/description.exs b/config/description.exs
index 37cb548ff..29a657333 100644
--- a/config/description.exs
+++ b/config/description.exs
@@ -12,6 +12,55 @@ websocket_config = [
compress: false
]
+installed_frontend_options = [
+ %{
+ key: "name",
+ label: "Name",
+ type: :string,
+ description:
+ "Name of the installed frontend. Valid config must include both `Name` and `Reference` values."
+ },
+ %{
+ key: "ref",
+ label: "Reference",
+ type: :string,
+ description:
+ "Reference of the installed frontend to be used. Valid config must include both `Name` and `Reference` values."
+ }
+]
+
+frontend_options = [
+ %{
+ key: "name",
+ label: "Name",
+ type: :string,
+ description: "Name of the frontend."
+ },
+ %{
+ key: "ref",
+ label: "Reference",
+ type: :string,
+ description: "Reference of the frontend to be used."
+ },
+ %{
+ key: "git",
+ type: :string,
+ description: "URL of the git repository of the frontend"
+ },
+ %{
+ key: "build_url",
+ type: :string,
+ description:
+ "Either an url to a zip file containing the frontend or a template to build it by inserting the `ref`. The string `${ref}` will be replaced by the configured `ref`.",
+ example: "https://some.url/builds/${ref}.zip"
+ },
+ %{
+ key: "build_dir",
+ type: :string,
+ description: "The directory inside the zip file "
+ }
+]
+
config :pleroma, :config_description, [
%{
group: :pleroma,
@@ -23,28 +72,26 @@ config :pleroma, :config_description, [
key: :uploader,
type: :module,
description: "Module which will be used for uploads",
- suggestions: [Pleroma.Uploaders.Local, Pleroma.Uploaders.S3]
+ suggestions: {:list_behaviour_implementations, Pleroma.Uploaders.Uploader}
},
%{
key: :filters,
type: {:list, :module},
- description: "List of filter modules for uploads",
- suggestions:
- Generator.list_modules_in_dir(
- "lib/pleroma/upload/filter",
- "Elixir.Pleroma.Upload.Filter."
- )
+ description:
+ "List of filter modules for uploads. Module names are shortened (removed leading `Pleroma.Upload.Filter.` part), but on adding custom module you need to use full name.",
+ suggestions: {:list_behaviour_implementations, Pleroma.Upload.Filter}
},
%{
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`."
+ "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,
+ label: "Base URL",
type: :string,
- description: "Base url for the uploads, needed if you use CDN",
+ description: "Base URL for the uploads, needed if you use CDN",
suggestions: [
"https://cdn-host.com"
]
@@ -57,6 +104,7 @@ config :pleroma, :config_description, [
},
%{
key: :proxy_opts,
+ label: "Proxy Options",
type: :keyword,
description: "Options for Pleroma.ReverseProxy",
suggestions: [
@@ -84,6 +132,7 @@ config :pleroma, :config_description, [
},
%{
key: :http,
+ label: "HTTP",
type: :keyword,
description: "HTTP options",
children: [
@@ -118,6 +167,11 @@ config :pleroma, :config_description, [
]
}
]
+ },
+ %{
+ key: :filename_display_max_length,
+ type: :integer,
+ description: "Set max length of a filename to display. 0 = no limit. Default: 30"
}
]
},
@@ -187,7 +241,9 @@ config :pleroma, :config_description, [
%{
key: :args,
type: [:string, {:list, :string}, {:list, :tuple}],
- description: "List of actions for the mogrify command",
+ description:
+ "List of actions for the mogrify command. It's possible to add self-written settings as string. " <>
+ "For example `auto-orient, strip, {\"resize\", \"3840x1080>\"}` value will be parsed into valid list of the settings.",
suggestions: [
"strip",
"auto-orient",
@@ -473,6 +529,7 @@ config :pleroma, :config_description, [
%{
group: :pleroma,
key: :uri_schemes,
+ label: "URI Schemes",
type: :group,
description: "URI schemes related settings",
children: [
@@ -486,6 +543,7 @@ config :pleroma, :config_description, [
"dat",
"dweb",
"gopher",
+ "hyper",
"ipfs",
"ipns",
"irc",
@@ -645,17 +703,22 @@ config :pleroma, :config_description, [
key: :invites_enabled,
type: :boolean,
description:
- "Enable user invitations for admins (depends on `registrations_open` being disabled)."
+ "Enable user invitations for admins (depends on `registrations_open` being disabled)"
},
%{
key: :account_activation_required,
type: :boolean,
- description: "Require users to confirm their emails before signing in."
+ description: "Require users to confirm their emails before signing in"
+ },
+ %{
+ key: :account_approval_required,
+ type: :boolean,
+ description: "Require users to be manually approved by an admin before signing in"
},
%{
key: :federating,
type: :boolean,
- description: "Enable federation with other instances."
+ description: "Enable federation with other instances"
},
%{
key: :federation_incoming_replies_max_depth,
@@ -673,46 +736,29 @@ config :pleroma, :config_description, [
label: "Fed. reachability timeout days",
type: :integer,
description:
- "Timeout (in days) of each external federation target being unreachable prior to pausing federating to it.",
+ "Timeout (in days) of each external federation target being unreachable prior to pausing federating to it",
suggestions: [
7
]
},
%{
- key: :federation_publisher_modules,
- type: {:list, :module},
- description: "List of modules for federation publishing",
- suggestions: [
- Pleroma.Web.ActivityPub.Publisher
- ]
- },
- %{
key: :allow_relay,
type: :boolean,
description: "Enable Pleroma's Relay, which makes it possible to follow a whole instance"
},
%{
- key: :rewrite_policy,
- type: [:module, {:list, :module}],
- description: "A list of MRF policies enabled",
- suggestions:
- Generator.list_modules_in_dir(
- "lib/pleroma/web/activity_pub/mrf",
- "Elixir.Pleroma.Web.ActivityPub.MRF."
- )
- },
- %{
key: :public,
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."
+ "Makes the client API in authenticated mode-only except for user-profiles." <>
+ " Useful for disabling the Local Timeline and The Whole Known Network. " <>
+ " Note: when setting to `false`, please also check `:restrict_unauthenticated` setting."
},
%{
key: :quarantined_instances,
type: {:list, :string},
description:
- "List of ActivityPub instances where private (DMs, followers-only) activities will not be send",
+ "List of ActivityPub instances where private (DMs, followers-only) activities will not be sent",
suggestions: [
"quarantined.com",
"*.quarantined.com"
@@ -744,23 +790,6 @@ config :pleroma, :config_description, [
]
},
%{
- key: :mrf_transparency,
- label: "MRF transparency",
- type: :boolean,
- description:
- "Make the content of your Message Rewrite Facility settings public (via nodeinfo)"
- },
- %{
- key: :mrf_transparency_exclusions,
- label: "MRF transparency exclusions",
- type: {:list, :string},
- description:
- "Exclude specific instance names from MRF transparency. The use of the exclusions feature will be disclosed in nodeinfo as a boolean value.",
- suggestions: [
- "exclusion.com"
- ]
- },
- %{
key: :extended_nickname_format,
type: :boolean,
description:
@@ -804,23 +833,6 @@ config :pleroma, :config_description, [
description: "Enable to automatically add attachment link text to statuses"
},
%{
- key: :welcome_message,
- type: :string,
- description:
- "A message that will be sent to a newly registered users as a direct message",
- suggestions: [
- "Hi, @username! Welcome on board!"
- ]
- },
- %{
- key: :welcome_user_nickname,
- type: :string,
- description: "The nickname of the local user that sends the welcome message",
- suggestions: [
- "lain"
- ]
- },
- %{
key: :max_report_comment_size,
type: :integer,
description: "The maximum size of the report comment. Default: 1000.",
@@ -830,6 +842,7 @@ config :pleroma, :config_description, [
},
%{
key: :safe_dm_mentions,
+ label: "Safe DM mentions",
type: :boolean,
description:
"If enabled, only mentions at the beginning of a post will be used to address people in direct messages." <>
@@ -869,7 +882,7 @@ config :pleroma, :config_description, [
%{
key: :skip_thread_containment,
type: :boolean,
- description: "Skip filtering out broken threads. Default: enabled"
+ description: "Skip filtering out broken threads. Default: enabled."
},
%{
key: :limit_to_local_content,
@@ -916,9 +929,193 @@ config :pleroma, :config_description, [
]
},
%{
+ key: :registration_reason_length,
+ type: :integer,
+ description: "Maximum registration reason length. Default: 500.",
+ suggestions: [
+ 500
+ ]
+ },
+ %{
key: :external_user_synchronization,
type: :boolean,
description: "Enabling following/followers counters synchronization for external users"
+ },
+ %{
+ key: :multi_factor_authentication,
+ type: :keyword,
+ description: "Multi-factor authentication settings",
+ suggestions: [
+ [
+ totp: [digits: 6, period: 30],
+ backup_codes: [number: 5, length: 16]
+ ]
+ ],
+ children: [
+ %{
+ key: :totp,
+ label: "TOTP settings",
+ type: :keyword,
+ description: "TOTP settings",
+ suggestions: [digits: 6, period: 30],
+ children: [
+ %{
+ key: :digits,
+ type: :integer,
+ suggestions: [6],
+ description:
+ "Determines the length of a one-time pass-code, in characters. Defaults to 6 characters."
+ },
+ %{
+ key: :period,
+ type: :integer,
+ suggestions: [30],
+ description:
+ "A period for which the TOTP code will be valid, in seconds. Defaults to 30 seconds."
+ }
+ ]
+ },
+ %{
+ key: :backup_codes,
+ type: :keyword,
+ description: "MFA backup codes settings",
+ suggestions: [number: 5, length: 16],
+ children: [
+ %{
+ key: :number,
+ type: :integer,
+ suggestions: [5],
+ description: "Number of backup codes to generate."
+ },
+ %{
+ key: :length,
+ type: :integer,
+ suggestions: [16],
+ description:
+ "Determines the length of backup one-time pass-codes, in characters. Defaults to 16 characters."
+ }
+ ]
+ }
+ ]
+ },
+ %{
+ key: :instance_thumbnail,
+ type: {:string, :image},
+ description:
+ "The instance thumbnail can be any image that represents your instance and is used by some apps or services when they display information about your instance.",
+ suggestions: ["/instance/thumbnail.jpeg"]
+ },
+ %{
+ key: :show_reactions,
+ type: :boolean,
+ description: "Let favourites and emoji reactions be viewed through the API."
+ }
+ ]
+ },
+ %{
+ group: :pleroma,
+ key: :welcome,
+ type: :group,
+ description: "Welcome messages settings",
+ children: [
+ %{
+ key: :direct_message,
+ type: :keyword,
+ descpiption: "Direct message settings",
+ children: [
+ %{
+ key: :enabled,
+ type: :boolean,
+ description: "Enables sending a direct message to newly registered users"
+ },
+ %{
+ key: :message,
+ type: :string,
+ description: "A message that will be sent to newly registered users",
+ suggestions: [
+ "Hi, @username! Welcome on board!"
+ ]
+ },
+ %{
+ key: :sender_nickname,
+ type: :string,
+ description: "The nickname of the local user that sends a welcome message",
+ suggestions: [
+ "lain"
+ ]
+ }
+ ]
+ },
+ %{
+ key: :chat_message,
+ type: :keyword,
+ descpiption: "Chat message settings",
+ children: [
+ %{
+ key: :enabled,
+ type: :boolean,
+ description: "Enables sending a chat message to newly registered users"
+ },
+ %{
+ key: :message,
+ type: :string,
+ description:
+ "A message that will be sent to newly registered users as a chat message",
+ suggestions: [
+ "Hello, welcome on board!"
+ ]
+ },
+ %{
+ key: :sender_nickname,
+ type: :string,
+ description: "The nickname of the local user that sends a welcome chat message",
+ suggestions: [
+ "lain"
+ ]
+ }
+ ]
+ },
+ %{
+ key: :email,
+ type: :keyword,
+ descpiption: "Email message settings",
+ children: [
+ %{
+ key: :enabled,
+ type: :boolean,
+ description: "Enables sending an email to newly registered users"
+ },
+ %{
+ key: :sender,
+ type: [:string, :tuple],
+ description:
+ "Email address and/or nickname that will be used to send the welcome email.",
+ suggestions: [
+ {"Pleroma App", "welcome@pleroma.app"}
+ ]
+ },
+ %{
+ key: :subject,
+ type: :string,
+ description:
+ "Subject of the welcome email. EEX template with user and instance_name variables can be used.",
+ suggestions: ["Welcome to <%= instance_name%>"]
+ },
+ %{
+ key: :html,
+ type: :string,
+ description:
+ "HTML content of the welcome email. EEX template with user and instance_name variables can be used.",
+ suggestions: ["<h1>Hello <%= user.name%>. Welcome to <%= instance_name%></h1>"]
+ },
+ %{
+ key: :text,
+ type: :string,
+ description:
+ "Text content of the welcome email. EEX template with user and instance_name variables can be used.",
+ suggestions: ["Hello <%= user.name%>. \n Welcome to <%= instance_name%>\n"]
+ }
+ ]
}
]
},
@@ -940,6 +1137,7 @@ config :pleroma, :config_description, [
group: :logger,
type: :group,
key: :ex_syslogger,
+ label: "ExSyslogger",
description: "ExSyslogger-related settings",
children: [
%{
@@ -958,7 +1156,7 @@ config :pleroma, :config_description, [
%{
key: :format,
type: :string,
- description: "Default: \"$date $time [$level] $levelpad$node $metadata $message\".",
+ description: "Default: \"$date $time [$level] $levelpad$node $metadata $message\"",
suggestions: ["$metadata[$level] $message"]
},
%{
@@ -972,6 +1170,7 @@ config :pleroma, :config_description, [
group: :logger,
type: :group,
key: :console,
+ label: "Console Logger",
description: "Console logger settings",
children: [
%{
@@ -983,7 +1182,7 @@ config :pleroma, :config_description, [
%{
key: :format,
type: :string,
- description: "Default: \"$date $time [$level] $levelpad$node $metadata $message\".",
+ description: "Default: \"$date $time [$level] $levelpad$node $metadata $message\"",
suggestions: ["$metadata[$level] $message"]
},
%{
@@ -996,6 +1195,7 @@ config :pleroma, :config_description, [
%{
group: :quack,
type: :group,
+ label: "Quack Logger",
description: "Quack-related settings",
children: [
%{
@@ -1024,6 +1224,7 @@ config :pleroma, :config_description, [
},
%{
key: :webhook_url,
+ label: "Webhook URL",
type: :string,
description: "Configure the Slack incoming webhook",
suggestions: ["https://hooks.slack.com/services/YOUR-KEY-HERE"]
@@ -1046,87 +1247,79 @@ config :pleroma, :config_description, [
description: "Settings for Pleroma FE",
suggestions: [
%{
- theme: "pleroma-dark",
- logo: "/static/logo.png",
- background: "/images/city.jpg",
- redirectRootNoLogin: "/main/all",
- redirectRootLogin: "/main/friends",
- showInstanceSpecificPanel: true,
- scopeOptionsEnabled: false,
- formattingOptionsEnabled: false,
+ alwaysShowSubjectInput: true,
+ background: "/static/aurora_borealis.jpg",
collapseMessageWithSubject: false,
+ disableChat: false,
+ greentext: false,
+ hideFilteredStatuses: false,
+ hideMutedPosts: false,
hidePostStats: false,
+ hideSitename: false,
hideUserStats: false,
+ loginMethod: "password",
+ logo: "/static/logo.png",
+ logoMargin: ".1em",
+ logoMask: true,
+ minimalScopesMode: false,
+ noAttachmentLinks: false,
+ nsfwCensorImage: "/static/img/nsfw.74818f9.png",
+ postContentType: "text/plain",
+ redirectRootLogin: "/main/friends",
+ redirectRootNoLogin: "/main/all",
scopeCopy: true,
+ sidebarRight: false,
+ showFeaturesPanel: true,
+ showInstanceSpecificPanel: false,
subjectLineBehavior: "email",
- alwaysShowSubjectInput: true,
- logoMask: false,
- logoMargin: ".1em",
- stickers: false,
- enableEmojiPicker: false
+ theme: "pleroma-dark",
+ webPushNotifications: false
}
],
children: [
%{
- key: :theme,
- type: :string,
- description: "Which theme to use, they are defined in styles.json",
- suggestions: ["pleroma-dark"]
- },
- %{
- key: :logo,
- type: :string,
- description: "URL of the logo, defaults to Pleroma's logo",
- suggestions: ["/static/logo.png"]
+ key: :alwaysShowSubjectInput,
+ label: "Always show subject input",
+ type: :boolean,
+ description: "When disabled, auto-hide the subject field if it's empty"
},
%{
key: :background,
- type: :string,
+ type: {:string, :image},
description:
"URL of the background, unless viewing a user profile with a background that is set",
suggestions: ["/images/city.jpg"]
},
%{
- key: :redirectRootNoLogin,
- label: "Redirect root no login",
- type: :string,
- description:
- "Relative URL which indicates where to redirect when a user isn't logged in",
- suggestions: ["/main/all"]
- },
- %{
- key: :redirectRootLogin,
- label: "Redirect root login",
- type: :string,
+ key: :collapseMessageWithSubject,
+ label: "Collapse message with subject",
+ type: :boolean,
description:
- "Relative URL which indicates where to redirect when a user is logged in",
- suggestions: ["/main/friends"]
+ "When a message has a subject (aka Content Warning), collapse it by default"
},
%{
- key: :showInstanceSpecificPanel,
- label: "Show instance specific panel",
+ key: :disableChat,
+ label: "PleromaFE Chat",
type: :boolean,
- description: "Whenether to show the instance's specific panel"
+ description: "Disables PleromaFE Chat component"
},
%{
- key: :scopeOptionsEnabled,
- label: "Scope options enabled",
+ key: :greentext,
+ label: "Greentext",
type: :boolean,
- description: "Enable setting a notice visibility and subject/CW when posting"
+ description: "Enables green text on lines prefixed with the > character"
},
%{
- key: :formattingOptionsEnabled,
- label: "Formatting options enabled",
+ key: :hideFilteredStatuses,
+ label: "Hide Filtered Statuses",
type: :boolean,
- description:
- "Enable setting a formatting different than plain-text (ie. HTML, Markdown) when posting, relates to `:instance`, `allowed_post_formats`"
+ description: "Hides filtered statuses from timelines"
},
%{
- key: :collapseMessageWithSubject,
- label: "Collapse message with subject",
+ key: :hideMutedPosts,
+ label: "Hide Muted Posts",
type: :boolean,
- description:
- "When a message has a subject (aka Content Warning), collapse it by default"
+ description: "Hides muted statuses from timelines"
},
%{
key: :hidePostStats,
@@ -1135,6 +1328,12 @@ config :pleroma, :config_description, [
description: "Hide notices statistics (repeats, favorites, ...)"
},
%{
+ key: :hideSitename,
+ label: "Hide Sitename",
+ type: :boolean,
+ description: "Hides instance name from PleromaFE banner"
+ },
+ %{
key: :hideUserStats,
label: "Hide user stats",
type: :boolean,
@@ -1142,26 +1341,19 @@ config :pleroma, :config_description, [
"Hide profile statistics (posts, posts per day, followers, followings, ...)"
},
%{
- key: :scopeCopy,
- label: "Scope copy",
- type: :boolean,
- description: "Copy the scope (private/unlisted/public) in replies to posts by default"
+ key: :logo,
+ type: {:string, :image},
+ description: "URL of the logo, defaults to Pleroma's logo",
+ suggestions: ["/static/logo.png"]
},
%{
- key: :subjectLineBehavior,
- label: "Subject line behavior",
+ key: :logoMargin,
+ label: "Logo margin",
type: :string,
- description: "Allows changing the default behaviour of subject lines in replies.
- `email`: copy and preprend re:, as in email,
- `masto`: copy verbatim, as in Mastodon,
- `noop`: don't copy the subject.",
- suggestions: ["email", "masto", "noop"]
- },
- %{
- key: :alwaysShowSubjectInput,
- label: "Always show subject input",
- type: :boolean,
- description: "When disabled, auto-hide the subject field if it's empty"
+ description:
+ "Allows you to adjust vertical margins between logo boundary and navbar borders. " <>
+ "The idea is that to have logo's image without any extra margins and instead adjust them to your need in layout.",
+ suggestions: [".1em"]
},
%{
key: :logoMask,
@@ -1172,24 +1364,84 @@ config :pleroma, :config_description, [
"If you want a colorful logo you must disable logoMask."
},
%{
- key: :logoMargin,
- label: "Logo margin",
+ key: :minimalScopesMode,
+ label: "Minimal scopes mode",
+ type: :boolean,
+ description:
+ "Limit scope selection to Direct, User default, and Scope of post replying to. " <>
+ "Also prevents replying to a DM with a public post from PleromaFE."
+ },
+ %{
+ key: :nsfwCensorImage,
+ label: "NSFW Censor Image",
+ type: {:string, :image},
+ description:
+ "URL of the image to use for hiding NSFW media attachments in the timeline",
+ suggestions: ["/static/img/nsfw.74818f9.png"]
+ },
+ %{
+ key: :postContentType,
+ label: "Post Content Type",
+ type: {:dropdown, :atom},
+ description: "Default post formatting option",
+ suggestions: ["text/plain", "text/html", "text/markdown", "text/bbcode"]
+ },
+ %{
+ key: :redirectRootNoLogin,
+ label: "Redirect root no login",
type: :string,
description:
- "Allows you to adjust vertical margins between logo boundary and navbar borders. " <>
- "The idea is that to have logo's image without any extra margins and instead adjust them to your need in layout.",
- suggestions: [".1em"]
+ "Relative URL which indicates where to redirect when a user isn't logged in",
+ suggestions: ["/main/all"]
+ },
+ %{
+ key: :redirectRootLogin,
+ label: "Redirect root login",
+ type: :string,
+ description:
+ "Relative URL which indicates where to redirect when a user is logged in",
+ suggestions: ["/main/friends"]
+ },
+ %{
+ key: :scopeCopy,
+ label: "Scope copy",
+ type: :boolean,
+ description: "Copy the scope (private/unlisted/public) in replies to posts by default"
},
%{
- key: :stickers,
+ key: :sidebarRight,
+ label: "Sidebar on Right",
type: :boolean,
- description: "Enables stickers."
+ description: "Change alignment of sidebar and panels to the right"
},
%{
- key: :enableEmojiPicker,
- label: "Emoji picker",
+ key: :showFeaturesPanel,
+ label: "Show instance features panel",
type: :boolean,
- description: "Enables emoji picker."
+ description:
+ "Enables panel displaying functionality of the instance on the About page"
+ },
+ %{
+ key: :showInstanceSpecificPanel,
+ label: "Show instance specific panel",
+ type: :boolean,
+ description: "Whether to show the instance's custom panel"
+ },
+ %{
+ key: :subjectLineBehavior,
+ label: "Subject line behavior",
+ type: :string,
+ description: "Allows changing the default behaviour of subject lines in replies.
+ `email`: copy and preprend re:, as in email,
+ `masto`: copy verbatim, as in Mastodon,
+ `noop`: don't copy the subject.",
+ suggestions: ["email", "masto", "noop"]
+ },
+ %{
+ key: :theme,
+ type: :string,
+ description: "Which theme to use. Available themes are defined in styles.json",
+ suggestions: ["pleroma-dark"]
}
]
},
@@ -1225,7 +1477,7 @@ config :pleroma, :config_description, [
key: :mascots,
type: {:keyword, :map},
description:
- "Keyword of mascots, each element must contain both an url and a mime_type key",
+ "Keyword of mascots, each element must contain both an URL and a mime_type key",
suggestions: [
pleroma_fox_tan: %{
url: "/images/pleroma-fox-tan-smol.png",
@@ -1245,6 +1497,12 @@ config :pleroma, :config_description, [
suggestions: [
:pleroma_fox_tan
]
+ },
+ %{
+ key: :default_user_avatar,
+ type: {:string, :image},
+ description: "URL of the default user avatar",
+ suggestions: ["/images/avi.png"]
}
]
},
@@ -1253,7 +1511,7 @@ config :pleroma, :config_description, [
key: :manifest,
type: :group,
description:
- "This section describe PWA manifest instance-specific values. Currently this option relate only for MastoFE",
+ "This section describe PWA manifest instance-specific values. Currently this option relate only for MastoFE.",
children: [
%{
key: :icons,
@@ -1289,10 +1547,46 @@ config :pleroma, :config_description, [
},
%{
group: :pleroma,
+ key: :mrf,
+ tab: :mrf,
+ label: "MRF",
+ type: :group,
+ description: "General MRF settings",
+ children: [
+ %{
+ key: :policies,
+ type: [:module, {:list, :module}],
+ description:
+ "A list of MRF policies enabled. Module names are shortened (removed leading `Pleroma.Web.ActivityPub.MRF.` part), but on adding custom module you need to use full name.",
+ suggestions: {:list_behaviour_implementations, Pleroma.Web.ActivityPub.MRF}
+ },
+ %{
+ key: :transparency,
+ label: "MRF transparency",
+ type: :boolean,
+ description:
+ "Make the content of your Message Rewrite Facility settings public (via nodeinfo)"
+ },
+ %{
+ key: :transparency_exclusions,
+ label: "MRF transparency exclusions",
+ type: {:list, :string},
+ description:
+ "Exclude specific instance names from MRF transparency. The use of the exclusions feature will be disclosed in nodeinfo as a boolean value.",
+ suggestions: [
+ "exclusion.com"
+ ]
+ }
+ ]
+ },
+ %{
+ group: :pleroma,
key: :mrf_simple,
- label: "MRF simple",
+ tab: :mrf,
+ related_policy: "Pleroma.Web.ActivityPub.MRF.SimplePolicy",
+ label: "MRF Simple",
type: :group,
- description: "Message Rewrite Facility",
+ description: "Simple ingress policies",
children: [
%{
key: :media_removal,
@@ -1311,19 +1605,25 @@ config :pleroma, :config_description, [
key: :federated_timeline_removal,
type: {:list, :string},
description:
- "List of instances to remove from Federated (aka The Whole Known Network) Timeline",
+ "List of instances to remove from the Federated (aka The Whole Known Network) Timeline",
suggestions: ["example.com", "*.example.com"]
},
%{
key: :reject,
type: {:list, :string},
- description: "List of instances to reject any activities from",
+ description: "List of instances to reject activities from (except deletes)",
suggestions: ["example.com", "*.example.com"]
},
%{
key: :accept,
type: {:list, :string},
- description: "List of instances to accept any activities from",
+ description: "List of instances to only accept activities from (except deletes)",
+ suggestions: ["example.com", "*.example.com"]
+ },
+ %{
+ key: :followers_only,
+ type: {:list, :string},
+ description: "Force posts from the given instances to be visible by followers only",
suggestions: ["example.com", "*.example.com"]
},
%{
@@ -1343,13 +1643,38 @@ config :pleroma, :config_description, [
type: {:list, :string},
description: "List of instances to strip banners from",
suggestions: ["example.com", "*.example.com"]
+ },
+ %{
+ key: :reject_deletes,
+ type: {:list, :string},
+ description: "List of instances to reject deletions from",
+ suggestions: ["example.com", "*.example.com"]
+ }
+ ]
+ },
+ %{
+ group: :pleroma,
+ key: :mrf_activity_expiration,
+ tab: :mrf,
+ related_policy: "Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy",
+ label: "MRF Activity Expiration Policy",
+ type: :group,
+ description: "Adds automatic expiration to all local activities",
+ children: [
+ %{
+ key: :days,
+ type: :integer,
+ description: "Default global expiration time for all local activities (in days)",
+ suggestions: [90, 365]
}
]
},
%{
group: :pleroma,
key: :mrf_subchain,
- label: "MRF subchain",
+ tab: :mrf,
+ related_policy: "Pleroma.Web.ActivityPub.MRF.SubchainPolicy",
+ label: "MRF Subchain",
type: :group,
description:
"This policy processes messages through an alternate pipeline when a given message matches certain criteria." <>
@@ -1357,7 +1682,7 @@ config :pleroma, :config_description, [
children: [
%{
key: :match_actor,
- type: :map,
+ type: {:map, {:list, :string}},
description: "Matches a series of regular expressions against the actor field",
suggestions: [
%{
@@ -1370,9 +1695,10 @@ config :pleroma, :config_description, [
%{
group: :pleroma,
key: :mrf_rejectnonpublic,
- description:
- "MRF RejectNonPublic settings. RejectNonPublic drops posts with non-public visibility settings.",
- label: "MRF reject non public",
+ tab: :mrf,
+ related_policy: "Pleroma.Web.ActivityPub.MRF.RejectNonPublic",
+ description: "RejectNonPublic drops posts with non-public visibility settings.",
+ label: "MRF Reject Non Public",
type: :group,
children: [
%{
@@ -1391,16 +1717,18 @@ config :pleroma, :config_description, [
%{
group: :pleroma,
key: :mrf_hellthread,
- label: "MRF hellthread",
+ tab: :mrf,
+ related_policy: "Pleroma.Web.ActivityPub.MRF.HellthreadPolicy",
+ label: "MRF Hellthread",
type: :group,
- description: "Block messages with too much mentions",
+ description: "Block messages with excessive user mentions",
children: [
%{
key: :delist_threshold,
type: :integer,
description:
- "Number of mentioned users after which the message gets delisted (the message can still be seen, " <>
- " but it will not show up in public timelines and mentioned users won't get notifications about it). Set to 0 to disable.",
+ "Number of mentioned users after which the message gets removed from timelines and" <>
+ "disables notifications. Set to 0 to disable.",
suggestions: [10]
},
%{
@@ -1415,27 +1743,29 @@ config :pleroma, :config_description, [
%{
group: :pleroma,
key: :mrf_keyword,
- label: "MRF keyword",
+ tab: :mrf,
+ related_policy: "Pleroma.Web.ActivityPub.MRF.KeywordPolicy",
+ label: "MRF Keyword",
type: :group,
description: "Reject or Word-Replace messages with a keyword or regex",
children: [
%{
key: :reject,
- type: [:string, :regex],
+ type: {:list, :string},
description:
"A list of patterns which result in message being rejected. Each pattern can be a string or a regular expression.",
suggestions: ["foo", ~r/foo/iu]
},
%{
key: :federated_timeline_removal,
- type: [:string, :regex],
+ type: {:list, :string},
description:
"A list of patterns which result in message being removed from federated timelines (a.k.a unlisted). Each pattern can be a string or a regular expression.",
suggestions: ["foo", ~r/foo/iu]
},
%{
key: :replace,
- type: [{:tuple, :string, :string}, {:tuple, :regex, :string}],
+ type: {:list, :tuple},
description:
"A list of tuples containing {pattern, replacement}. Each pattern can be a string or a regular expression.",
suggestions: [{"foo", "bar"}, {~r/foo/iu, "bar"}]
@@ -1445,14 +1775,16 @@ config :pleroma, :config_description, [
%{
group: :pleroma,
key: :mrf_mention,
- label: "MRF mention",
+ tab: :mrf,
+ related_policy: "Pleroma.Web.ActivityPub.MRF.MentionPolicy",
+ label: "MRF Mention",
type: :group,
- description: "Block messages which mention a user",
+ description: "Block messages which mention a specific user",
children: [
%{
key: :actors,
type: {:list, :string},
- description: "A list of actors for which any post mentioning them will be dropped.",
+ description: "A list of actors for which any post mentioning them will be dropped",
suggestions: ["actor1", "actor2"]
}
]
@@ -1460,7 +1792,9 @@ config :pleroma, :config_description, [
%{
group: :pleroma,
key: :mrf_vocabulary,
- label: "MRF vocabulary",
+ tab: :mrf,
+ related_policy: "Pleroma.Web.ActivityPub.MRF.VocabularyPolicy",
+ label: "MRF Vocabulary",
type: :group,
description: "Filter messages which belong to certain activity vocabularies",
children: [
@@ -1468,14 +1802,14 @@ config :pleroma, :config_description, [
key: :accept,
type: {:list, :string},
description:
- "A list of ActivityStreams terms to accept. If empty, all supported messages are accepted",
+ "A list of ActivityStreams terms to accept. If empty, all supported messages are accepted.",
suggestions: ["Create", "Follow", "Mention", "Announce", "Like"]
},
%{
key: :reject,
type: {:list, :string},
description:
- "A list of ActivityStreams terms to reject. If empty, no messages are rejected",
+ "A list of ActivityStreams terms to reject. If empty, no messages are rejected.",
suggestions: ["Create", "Follow", "Mention", "Announce", "Like"]
}
]
@@ -1483,6 +1817,8 @@ config :pleroma, :config_description, [
# %{
# group: :pleroma,
# key: :mrf_user_allowlist,
+ # tab: :mrf,
+ # related_policy: "Pleroma.Web.ActivityPub.MRF.UserAllowListPolicy",
# type: :map,
# description:
# "The keys in this section are the domain names that the policy should apply to." <>
@@ -1505,13 +1841,40 @@ config :pleroma, :config_description, [
},
%{
key: :base_url,
+ label: "Base URL",
type: :string,
description:
"The base URL to access a user-uploaded file. Useful when you want to proxy the media files via another host/CDN fronts.",
suggestions: ["https://example.com"]
},
%{
+ key: :invalidation,
+ type: :keyword,
+ descpiption: "",
+ suggestions: [
+ enabled: true,
+ provider: Pleroma.Web.MediaProxy.Invalidation.Script
+ ],
+ children: [
+ %{
+ key: :enabled,
+ type: :boolean,
+ description: "Enables media cache object invalidation."
+ },
+ %{
+ key: :provider,
+ type: :module,
+ description: "Module which will be used to purge objects from the cache.",
+ suggestions: [
+ Pleroma.Web.MediaProxy.Invalidation.Script,
+ Pleroma.Web.MediaProxy.Invalidation.Http
+ ]
+ }
+ ]
+ },
+ %{
key: :proxy_opts,
+ label: "Proxy Options",
type: :keyword,
description: "Options for Pleroma.ReverseProxy",
suggestions: [
@@ -1539,6 +1902,7 @@ config :pleroma, :config_description, [
},
%{
key: :http,
+ label: "HTTP",
type: :keyword,
description: "HTTP options",
children: [
@@ -1577,8 +1941,52 @@ config :pleroma, :config_description, [
%{
key: :whitelist,
type: {:list, :string},
- description: "List of domains to bypass the mediaproxy",
- suggestions: ["example.com"]
+ description: "List of hosts with scheme to bypass the mediaproxy",
+ suggestions: ["http://example.com"]
+ }
+ ]
+ },
+ %{
+ group: :pleroma,
+ key: Pleroma.Web.MediaProxy.Invalidation.Http,
+ type: :group,
+ description: "HTTP invalidate settings",
+ children: [
+ %{
+ key: :method,
+ type: :atom,
+ description: "HTTP method of request. Default: :purge"
+ },
+ %{
+ key: :headers,
+ type: {:keyword, :string},
+ description: "HTTP headers of request",
+ suggestions: [{"x-refresh", 1}]
+ },
+ %{
+ key: :options,
+ type: :keyword,
+ description: "Request options",
+ children: [
+ %{
+ key: :params,
+ type: {:map, :string}
+ }
+ ]
+ }
+ ]
+ },
+ %{
+ group: :pleroma,
+ key: Pleroma.Web.MediaProxy.Invalidation.Script,
+ type: :group,
+ description: "Script invalidate settings",
+ children: [
+ %{
+ key: :script_path,
+ type: :string,
+ description: "Path to shell script. Which will run purge cache.",
+ suggestions: ["./installation/nginx-cache-purge.sh.example"]
}
]
},
@@ -1595,6 +2003,7 @@ config :pleroma, :config_description, [
},
%{
key: :ip,
+ label: "IP",
type: :tuple,
description: "IP address to bind to",
suggestions: [{0, 0, 0, 0}]
@@ -1608,7 +2017,7 @@ config :pleroma, :config_description, [
%{
key: :dstport,
type: :integer,
- description: "Port advertised in urls (optional, defaults to port)",
+ description: "Port advertised in URLs (optional, defaults to port)",
suggestions: [9999]
}
]
@@ -1616,6 +2025,7 @@ config :pleroma, :config_description, [
%{
group: :pleroma,
key: :activitypub,
+ label: "ActivityPub",
type: :group,
description: "ActivityPub-related settings",
children: [
@@ -1638,7 +2048,7 @@ config :pleroma, :config_description, [
key: :note_replies_output_limit,
type: :integer,
description:
- "The number of Note replies' URIs to be included with outgoing federation (`5` to match Mastodon hardcoded value, `0` to disable the output)."
+ "The number of Note replies' URIs to be included with outgoing federation (`5` to match Mastodon hardcoded value, `0` to disable the output)"
},
%{
key: :follow_handshake_timeout,
@@ -1651,6 +2061,7 @@ config :pleroma, :config_description, [
%{
group: :pleroma,
key: :http_security,
+ label: "HTTP security",
type: :group,
description: "HTTP security settings",
children: [
@@ -1689,7 +2100,7 @@ config :pleroma, :config_description, [
key: :report_uri,
label: "Report URI",
type: :string,
- description: "Adds the specified url to report-uri and report-to group in CSP header",
+ description: "Adds the specified URL to report-uri and report-to group in CSP header",
suggestions: ["https://example.com/report-uri"]
}
]
@@ -1697,9 +2108,10 @@ config :pleroma, :config_description, [
%{
group: :web_push_encryption,
key: :vapid_details,
+ label: "Vapid Details",
type: :group,
description:
- "Web Push Notifications configuration. You can use the mix task mix web_push.gen.keypair to generate it",
+ "Web Push Notifications configuration. You can use the mix task mix web_push.gen.keypair to generate it.",
children: [
%{
key: :subject,
@@ -1766,34 +2178,18 @@ config :pleroma, :config_description, [
},
%{
group: :pleroma,
+ label: "Pleroma Admin Token",
type: :group,
description:
- "Allows to set a token that can be used to authenticate with the admin api without using an actual user by giving it as the `admin_token` parameter",
+ "Allows setting a token that can be used to authenticate requests with admin privileges without a normal user account token. Append the `admin_token` parameter to requests to utilize it. (Please reconsider using HTTP Basic Auth or OAuth-based authentication if possible)",
children: [
%{
key: :admin_token,
type: :string,
- description: "Token",
- suggestions: ["We recommend a secure random string or UUID"]
- }
- ]
- },
- %{
- group: :pleroma_job_queue,
- key: :queues,
- type: :group,
- description: "[Deprecated] Replaced with `Oban`/`:queues` (keeping the same format)"
- },
- %{
- group: :pleroma,
- key: Pleroma.Web.Federator.RetryQueue,
- type: :group,
- description: "[Deprecated] See `Oban` and `:workers` sections for configuration notes",
- children: [
- %{
- key: :max_retries,
- type: :integer,
- description: "[Deprecated] Replaced as `Oban`/`:queues`/`:outgoing_federation` value"
+ description: "Admin token",
+ suggestions: [
+ "Please use a high entropy string or UUID"
+ ]
}
]
},
@@ -1811,25 +2207,12 @@ config :pleroma, :config_description, [
""",
children: [
%{
- key: :repo,
- type: :module,
- description: "Application's Ecto repo",
- suggestions: [Pleroma.Repo]
- },
- %{
- key: :verbose,
+ key: :log,
type: {:dropdown, :atom},
description: "Logs verbose mode",
suggestions: [false, :error, :warn, :info, :debug]
},
%{
- key: :prune,
- type: [:atom, :tuple],
- description:
- "Non-retryable jobs [pruning settings](https://github.com/sorentwo/oban#pruning)",
- suggestions: [:disabled, {:maxlen, 1500}, {:maxage, 60 * 60}]
- },
- %{
key: :queues,
type: {:keyword, :integer},
description:
@@ -1963,34 +2346,33 @@ config :pleroma, :config_description, [
key: :rich_media,
type: :group,
description:
- "If enabled the instance will parse metadata from attached links to generate link previews.",
+ "If enabled the instance will parse metadata from attached links to generate link previews",
children: [
%{
key: :enabled,
type: :boolean,
- description: "Enables RichMedia parsing of URLs."
+ description: "Enables RichMedia parsing of URLs"
},
%{
key: :ignore_hosts,
type: {:list, :string},
- description: "List of hosts which will be ignored by the metadata parser.",
+ description: "List of hosts which will be ignored by the metadata parser",
suggestions: ["accounts.google.com", "xss.website"]
},
%{
key: :ignore_tld,
label: "Ignore TLD",
type: {:list, :string},
- description: "List TLDs (top-level domains) which will ignore for parse metadata.",
+ description: "List TLDs (top-level domains) which will ignore for parse metadata",
suggestions: ["local", "localdomain", "lan"]
},
%{
key: :parsers,
type: {:list, :module},
- description: "List of Rich Media parsers.",
+ description:
+ "List of Rich Media parsers. Module names are shortened (removed leading `Pleroma.Web.RichMedia.Parsers.` part), but on adding custom module you need to use full name.",
suggestions: [
- Pleroma.Web.RichMedia.Parsers.MetaTagsParser,
Pleroma.Web.RichMedia.Parsers.OEmbed,
- Pleroma.Web.RichMedia.Parsers.OGP,
Pleroma.Web.RichMedia.Parsers.TwitterCard
]
},
@@ -1998,7 +2380,8 @@ config :pleroma, :config_description, [
key: :ttl_setters,
label: "TTL setters",
type: {:list, :module},
- description: "List of rich media TTL setters.",
+ description:
+ "List of rich media TTL setters. Module names are shortened (removed leading `Pleroma.Web.RichMedia.Parser.` part), but on adding custom module you need to use full name.",
suggestions: [
Pleroma.Web.RichMedia.Parser.TTL.AwsSignedUrl
]
@@ -2006,44 +2389,53 @@ config :pleroma, :config_description, [
]
},
%{
- group: :auto_linker,
- key: :opts,
+ group: :pleroma,
+ key: Pleroma.Formatter,
+ label: "Auto Linker",
type: :group,
- description: "Configuration for the auto_linker library",
+ description:
+ "Configuration for Pleroma's link formatter which parses mentions, hashtags, and URLs.",
children: [
%{
key: :class,
- type: [:string, false],
- description: "Specify the class to be added to the generated link. Disable to clear",
+ type: [:string, :boolean],
+ description: "Specify the class to be added to the generated link. Disable to clear.",
suggestions: ["auto-linker", false]
},
%{
key: :rel,
- type: [:string, false],
- description: "Override the rel attribute. Disable to clear",
+ type: [:string, :boolean],
+ description: "Override the rel attribute. Disable to clear.",
suggestions: ["ugc", "noopener noreferrer", false]
},
%{
key: :new_window,
type: :boolean,
- description: "Link urls will open in new window/tab"
+ description: "Link URLs will open in a new window/tab."
},
%{
key: :truncate,
- type: [:integer, false],
+ type: [:integer, :boolean],
description:
- "Set to a number to truncate urls longer then the number. Truncated urls will end in `..`",
+ "Set to a number to truncate URLs longer than the number. Truncated URLs will end in `...`",
suggestions: [15, false]
},
%{
key: :strip_prefix,
type: :boolean,
- description: "Strip the scheme prefix"
+ description: "Strip the scheme prefix."
},
%{
key: :extra,
type: :boolean,
- description: "Link urls with rarely used schemes (magnet, ipfs, irc, etc.)"
+ description: "Link URLs with rarely used schemes (magnet, ipfs, irc, etc.)"
+ },
+ %{
+ key: :validate_tld,
+ type: [:atom, :boolean],
+ description:
+ "Set to false to disable TLD validation for URLs/emails. Can be set to :no_scheme to validate TLDs only for URLs without a scheme (e.g `example.com` will be validated, but `http://example.loki` won't)",
+ suggestions: [:no_scheme, true]
}
]
},
@@ -2089,6 +2481,7 @@ config :pleroma, :config_description, [
},
%{
group: :pleroma,
+ label: "Pleroma Authenticator",
type: :group,
description: "Authenticator",
children: [
@@ -2102,6 +2495,7 @@ config :pleroma, :config_description, [
%{
group: :pleroma,
key: :ldap,
+ label: "LDAP",
type: :group,
description:
"Use LDAP for user authentication. When a user logs in to the Pleroma instance, the name and password" <>
@@ -2188,6 +2582,7 @@ config :pleroma, :config_description, [
},
%{
key: :uid,
+ label: "UID",
type: :string,
description:
"LDAP attribute name to authenticate the user, e.g. when \"cn\", the filter will be \"cn=username,base\"",
@@ -2203,11 +2598,12 @@ config :pleroma, :config_description, [
children: [
%{
key: :enforce_oauth_admin_scope_usage,
+ label: "Enforce OAuth admin scope usage",
type: :boolean,
description:
"OAuth admin scope requirement toggle. " <>
"If enabled, admin actions explicitly demand admin OAuth scope(s) presence in OAuth token " <>
- "(client app must support admin scopes). If disabled and token doesn't have admin scope(s)," <>
+ "(client app must support admin scopes). If disabled and token doesn't have admin scope(s), " <>
"`is_admin` user flag grants access to admin-specific actions."
},
%{
@@ -2219,6 +2615,7 @@ config :pleroma, :config_description, [
},
%{
key: :oauth_consumer_template,
+ label: "OAuth consumer template",
type: :string,
description:
"OAuth consumer mode authentication form template. By default it's `consumer.html` which corresponds to" <>
@@ -2227,6 +2624,7 @@ config :pleroma, :config_description, [
},
%{
key: :oauth_consumer_strategies,
+ label: "OAuth consumer strategies",
type: {:list, :string},
description:
"The list of enabled OAuth consumer strategies. By default it's set by OAUTH_CONSUMER_STRATEGIES environment variable." <>
@@ -2293,14 +2691,14 @@ config :pleroma, :config_description, [
children: [
%{
key: :logo,
- type: :string,
+ type: {:string, :image},
description: "A path to a custom logo. Set it to `nil` to use the default Pleroma logo.",
suggestions: ["some/path/logo.png"]
},
%{
key: :styling,
type: :map,
- description: "a map with color settings for email templates.",
+ description: "A map with color settings for email templates.",
suggestions: [
%{
link_color: "#d8a070",
@@ -2355,14 +2753,14 @@ config :pleroma, :config_description, [
%{
key: :enabled,
type: :boolean,
- description: "enables new users admin digest email when `true`",
- suggestions: [false]
+ description: "Enables new users admin digest email when `true`"
}
]
},
%{
group: :pleroma,
key: :oauth2,
+ label: "OAuth2",
type: :group,
description: "Configure OAuth 2 provider capabilities",
children: [
@@ -2381,7 +2779,7 @@ config :pleroma, :config_description, [
%{
key: :clean_expired_tokens,
type: :boolean,
- description: "Enable a background job to clean expired oauth tokens. Default: disabled."
+ description: "Enable a background job to clean expired OAuth tokens. Default: disabled."
}
]
},
@@ -2405,7 +2803,7 @@ config :pleroma, :config_description, [
},
%{
key: :groups,
- type: {:keyword, :string, {:list, :string}},
+ type: {:keyword, {:list, :string}},
description:
"Emojis are ordered in groups (tags). This is an array of key-value pairs where the key is the group name" <>
" and the value is the location or array of locations. * can be used as a wildcard.",
@@ -2465,6 +2863,7 @@ config :pleroma, :config_description, [
},
%{
key: :relation_id_action,
+ label: "Relation ID action",
type: [:tuple, {:list, :tuple}],
description: "For actions on relation with a specific user (follow, unfollow)",
suggestions: [{1000, 10}, [{10_000, 10}, {10_000, 50}]]
@@ -2478,6 +2877,7 @@ config :pleroma, :config_description, [
},
%{
key: :status_id_action,
+ label: "Status ID action",
type: [:tuple, {:list, :tuple}],
description:
"For fav / unfav or reblog / unreblog actions on the same status by the same user",
@@ -2493,6 +2893,7 @@ config :pleroma, :config_description, [
},
%{
group: :esshd,
+ label: "ESSHD",
type: :group,
description:
"Before enabling this you must add :esshd to mix.exs as one of the extra_applications " <>
@@ -2531,8 +2932,9 @@ config :pleroma, :config_description, [
},
%{
group: :mime,
+ label: "Mime Types",
type: :group,
- description: "Mime types",
+ description: "Mime Types settings",
children: [
%{
key: :types,
@@ -2577,19 +2979,6 @@ config :pleroma, :config_description, [
]
},
%{
- group: :tesla,
- type: :group,
- description: "Tesla settings",
- children: [
- %{
- key: :adapter,
- type: :module,
- description: "Tesla adapter",
- suggestions: [Tesla.Adapter.Hackney]
- }
- ]
- },
- %{
group: :pleroma,
key: :chat,
type: :group,
@@ -2602,20 +2991,9 @@ config :pleroma, :config_description, [
]
},
%{
- group: :http_signatures,
- type: :group,
- description: "HTTP Signatures settings",
- children: [
- %{
- key: :adapter,
- type: :module,
- suggestions: [Pleroma.Signature]
- }
- ]
- },
- %{
group: :pleroma,
key: :http,
+ label: "HTTP",
type: :group,
description: "HTTP settings",
children: [
@@ -2664,6 +3042,7 @@ config :pleroma, :config_description, [
%{
group: :pleroma,
key: :markup,
+ label: "Markup Settings",
type: :group,
children: [
%{
@@ -2685,6 +3064,8 @@ config :pleroma, :config_description, [
%{
key: :scrub_policy,
type: {:list, :module},
+ description:
+ "Module names are shortened (removed leading `Pleroma.HTML.` part), but on adding custom module you need to use full name.",
suggestions: [Pleroma.HTML.Transform.MediaProxy, Pleroma.HTML.Scrubber.Default]
}
]
@@ -2703,7 +3084,9 @@ config :pleroma, :config_description, [
%{
group: :pleroma,
key: :mrf_normalize_markup,
- label: "MRF normalize markup",
+ tab: :mrf,
+ related_policy: "Pleroma.Web.ActivityPub.MRF.NormalizeMarkup",
+ label: "MRF Normalize Markup",
description: "MRF NormalizeMarkup settings. Scrub configured hypertext markup.",
type: :group,
children: [
@@ -2722,6 +3105,7 @@ config :pleroma, :config_description, [
%{
key: :restricted_nicknames,
type: {:list, :string},
+ description: "List of nicknames users may not register with.",
suggestions: [
".well-known",
"~",
@@ -2754,11 +3138,18 @@ config :pleroma, :config_description, [
"users",
"web"
]
+ },
+ %{
+ key: :email_blacklist,
+ type: {:list, :string},
+ description: "List of email domains users may not register with.",
+ suggestions: ["mailinator.com", "maildrop.cc"]
}
]
},
%{
group: :cors_plug,
+ label: "CORS plug config",
type: :group,
children: [
%{
@@ -2831,6 +3222,7 @@ config :pleroma, :config_description, [
%{
group: :pleroma,
key: :web_cache_ttl,
+ label: "Web cache TTL",
type: :group,
description:
"The expiration time for the web responses cache. Values should be in milliseconds or `nil` to disable expiration.",
@@ -2853,9 +3245,10 @@ config :pleroma, :config_description, [
%{
group: :pleroma,
key: :static_fe,
+ label: "Static FE",
type: :group,
description:
- "Render profiles and posts using server-generated HTML that is viewable without using JavaScript.",
+ "Render profiles and posts using server-generated HTML that is viewable without using JavaScript",
children: [
%{
key: :enabled,
@@ -2873,18 +3266,18 @@ config :pleroma, :config_description, [
%{
key: :post_title,
type: :map,
- description: "Configure title rendering.",
+ description: "Configure title rendering",
children: [
%{
key: :max_length,
type: :integer,
- description: "Maximum number of characters before truncating title.",
+ description: "Maximum number of characters before truncating title",
suggestions: [100]
},
%{
key: :omission,
type: :string,
- description: "Replacement which will be used after truncating string.",
+ description: "Replacement which will be used after truncating string",
suggestions: ["..."]
}
]
@@ -2894,8 +3287,12 @@ config :pleroma, :config_description, [
%{
group: :pleroma,
key: :mrf_object_age,
+ tab: :mrf,
+ related_policy: "Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy",
+ label: "MRF Object Age",
type: :group,
-