aboutsummaryrefslogtreecommitdiff
path: root/lib/pleroma/web
diff options
context:
space:
mode:
Diffstat (limited to 'lib/pleroma/web')
-rwxr-xr-xlib/pleroma/web/.router.ex.un~bin89164 -> 0 bytes
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/activity_pub.ex105
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/activity_pub/persisting.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/activity_pub/streaming.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/activity_pub_controller.ex18
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/builder.ex97
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/internal_fetch_actor.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/mrf.ex19
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/mrf/activity_expiration_policy.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/mrf/anti_followbot_policy.ex2
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/mrf/anti_link_spam_policy.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/mrf/drop_policy.ex0
-rw-r--r--lib/pleroma/web/activity_pub/mrf/emoji_policy.ex281
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/mrf/ensure_re_prepended.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/mrf/follow_bot_policy.ex2
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/mrf/force_bot_unlisted_policy.ex0
-rw-r--r--lib/pleroma/web/activity_pub/mrf/force_mention.ex59
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/mrf/force_mentions_in_content.ex10
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/mrf/hashtag_policy.ex4
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex0
-rw-r--r--lib/pleroma/web/activity_pub/mrf/inline_quote_policy.ex77
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/mrf/keyword_policy.ex21
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/mrf/media_proxy_warming_policy.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/mrf/mention_policy.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/mrf/no_empty_policy.ex16
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/mrf/no_op_policy.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/mrf/no_placeholder_text_policy.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/mrf/normalize_markup.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/mrf/object_age_policy.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/mrf/pipeline_filtering.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/mrf/policy.ex4
-rw-r--r--lib/pleroma/web/activity_pub/mrf/quote_to_link_tag_policy.ex49
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/mrf/reject_non_public.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/mrf/simple_policy.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex10
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/mrf/subchain_policy.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/mrf/tag_policy.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/mrf/user_allow_list_policy.ex0
-rw-r--r--lib/pleroma/web/activity_pub/mrf/utils.ex15
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/mrf/vocabulary_policy.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/object_validator.ex18
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/object_validator/validating.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/object_validators/accept_reject_validator.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/object_validators/add_remove_validator.ex3
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/object_validators/announce_validator.ex2
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/object_validators/answer_validator.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/object_validators/article_note_page_validator.ex1
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/object_validators/attachment_validator.ex4
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/object_validators/audio_image_video_validator.ex (renamed from lib/pleroma/web/activity_pub/object_validators/audio_video_validator.ex)16
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/object_validators/block_validator.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/object_validators/chat_message_validator.ex5
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/object_validators/common_fields.ex6
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/object_validators/common_fixes.ex49
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/object_validators/common_validations.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/object_validators/create_chat_message_validator.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/object_validators/delete_validator.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/object_validators/emoji_react_validator.ex51
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/object_validators/event_validator.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/object_validators/follow_validator.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/object_validators/like_validator.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/object_validators/question_options_validator.ex4
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/object_validators/question_validator.ex2
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/object_validators/tag_validator.ex20
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/object_validators/undo_validator.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/object_validators/update_validator.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/pipeline.ex2
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/publisher.ex204
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/relay.ex2
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/side_effects.ex44
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/side_effects/handling.ex2
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/transmogrifier.ex85
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/utils.ex122
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/views/object_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/views/user_view.ex13
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/activity_pub/visibility.ex50
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/admin_api/controllers/admin_api_controller.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/admin_api/controllers/announcement_controller.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/admin_api/controllers/chat_controller.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/admin_api/controllers/config_controller.ex6
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/admin_api/controllers/fallback_controller.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/admin_api/controllers/frontend_controller.ex25
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/admin_api/controllers/instance_controller.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/admin_api/controllers/instance_document_controller.ex13
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/admin_api/controllers/invite_controller.ex14
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/admin_api/controllers/media_proxy_cache_controller.ex15
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/admin_api/controllers/o_auth_app_controller.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/admin_api/controllers/relay_controller.ex18
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/admin_api/controllers/report_controller.ex42
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/admin_api/controllers/status_controller.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/admin_api/controllers/user_controller.ex107
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/admin_api/report.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/admin_api/search.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/admin_api/views/account_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/admin_api/views/announcement_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/admin_api/views/chat_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/admin_api/views/config_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/admin_api/views/frontend_view.ex3
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/admin_api/views/invite_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/admin_api/views/media_proxy_cache_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/admin_api/views/moderation_log_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/admin_api/views/o_auth_app_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/admin_api/views/report_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/admin_api/views/status_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/admin_api/views/user_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec.ex43
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/cast_and_validate.ex14
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/helpers.ex2
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/account_operation.ex23
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/admin/announcement_operation.ex10
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/admin/chat_operation.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/admin/config_operation.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/admin/frontend_operation.ex9
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/admin/instance_document_operation.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/admin/invite_operation.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/admin/media_proxy_cache_operation.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/admin/o_auth_app_operation.ex8
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/admin/relay_operation.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/admin/report_operation.ex12
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/admin/status_operation.ex8
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/admin/user_operation.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/announcement_operation.ex4
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/app_operation.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/chat_operation.ex14
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/conversation_operation.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/custom_emoji_operation.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/directory_operation.ex4
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/domain_block_operation.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/emoji_reaction_operation.ex6
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/filter_operation.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/follow_request_operation.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/instance_operation.ex205
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/list_operation.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/marker_operation.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/media_operation.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/notification_operation.ex2
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/pleroma_account_operation.ex2
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/pleroma_app_operation.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/pleroma_backup_operation.ex12
-rw-r--r--lib/pleroma/web/api_spec/operations/pleroma_bookmark_folder_operation.ex125
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/pleroma_conversation_operation.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/pleroma_emoji_file_operation.ex6
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/pleroma_emoji_pack_operation.ex28
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/pleroma_instances_operation.ex2
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/pleroma_mascot_operation.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/pleroma_notification_operation.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/pleroma_report_operation.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/pleroma_scrobble_operation.ex10
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/pleroma_settings_operation.ex0
-rw-r--r--lib/pleroma/web/api_spec/operations/pleroma_status_operation.ex45
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/poll_operation.ex2
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/report_operation.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/scheduled_activity_operation.ex2
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/search_operation.ex4
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/status_operation.ex43
-rw-r--r--lib/pleroma/web/api_spec/operations/streaming_operation.ex464
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/subscription_operation.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/timeline_operation.ex7
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/twitter_util_operation.ex35
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/operations/user_import_operation.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/render_error.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/schemas/account.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/schemas/account_field.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/schemas/account_relationship.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/schemas/actor_type.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/schemas/announcement.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/schemas/api_error.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/schemas/app.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/schemas/attachment.ex2
-rw-r--r--lib/pleroma/web/api_spec/schemas/bookmark_folder.ex26
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/schemas/boolean_like.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/schemas/chat.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/schemas/chat_message.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/schemas/conversation.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/schemas/emoji.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/schemas/flake_id.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/schemas/list.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/schemas/poll.ex14
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/schemas/push_subscription.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/schemas/scheduled_status.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/schemas/status.ex43
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/schemas/tag.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/api_spec/schemas/visibility_scope.ex0
-rw-r--r--lib/pleroma/web/api_spec/scopes/compiler.ex82
-rw-r--r--lib/pleroma/web/api_spec/scopes/translator.ex10
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/auth/authenticator.ex2
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/auth/helpers.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/auth/ldap_authenticator.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/auth/pleroma_authenticator.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/auth/totp_authenticator.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/auth/wrapper_authenticator.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/channels/user_socket.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/common_api.ex12
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/common_api/activity_draft.ex53
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/common_api/utils.ex24
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/controller_helper.ex18
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/embed_controller.ex4
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/endpoint.ex105
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/fallback/legacy_pleroma_api_rerouter_plug.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/fallback/redirect_controller.ex27
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/federator.ex32
-rwxr-xr-xlib/pleroma/web/federator/publisher.ex109
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/federator/publishing.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/feed/feed_view.ex4
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/feed/tag_controller.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/feed/user_controller.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/gettext.ex4
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/instance_document.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mailer/subscription_controller.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/manifest_controller.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/controllers/account_controller.ex103
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/controllers/announcement_controller.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/controllers/app_controller.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/controllers/auth_controller.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/controllers/conversation_controller.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/controllers/custom_emoji_controller.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/controllers/directory_controller.ex2
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/controllers/domain_block_controller.ex18
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/controllers/filter_controller.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/controllers/follow_request_controller.ex4
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/controllers/instance_controller.ex7
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/controllers/list_controller.ex52
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/controllers/marker_controller.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/controllers/media_controller.ex26
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/controllers/notification_controller.ex63
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/controllers/poll_controller.ex12
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/controllers/report_controller.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/controllers/scheduled_activity_controller.ex17
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/controllers/search_controller.ex20
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/controllers/status_controller.ex192
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/controllers/suggestion_controller.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/mastodon_api.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/views/account_view.ex24
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/views/announcement_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/views/app_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/views/conversation_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/views/custom_emoji_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/views/filter_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/views/follow_request_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/views/instance_view.ex162
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/views/list_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/views/marker_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/views/media_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/views/notification_view.ex5
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/views/poll_view.ex5
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/views/report_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/views/scheduled_activity_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/views/status_view.ex164
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/views/subscription_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/views/suggestion_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/views/timeline_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mastodon_api/websocket_handler.ex249
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/media_proxy.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/media_proxy/invalidation.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/media_proxy/invalidation/http.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/media_proxy/invalidation/script.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/media_proxy/media_proxy_controller.ex2
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/metadata.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/metadata/player_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/metadata/providers/feed.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/metadata/providers/open_graph.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/metadata/providers/provider.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/metadata/providers/rel_me.ex14
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/metadata/providers/restrict_indexing.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/metadata/providers/twitter_card.ex13
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/metadata/utils.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/mongoose_im/mongoose_im_controller.ex0
-rw-r--r--lib/pleroma/web/multipart.ex22
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/nodeinfo/nodeinfo.ex2
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/nodeinfo/nodeinfo_controller.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/o_auth.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/o_auth/app.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/o_auth/authorization.ex8
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/o_auth/fallback_controller.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/o_auth/mfa_controller.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/o_auth/mfa_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/o_auth/o_auth_controller.ex9
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/o_auth/o_auth_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/o_auth/scopes.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/o_auth/token.ex9
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/o_auth/token/query.ex4
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/o_auth/token/strategy/refresh_token.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/o_auth/token/strategy/revoke.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/o_auth/token/utils.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/o_status/o_status_controller.ex9
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/pleroma_api/controllers/account_controller.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/pleroma_api/controllers/app_controller.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/pleroma_api/controllers/backup_controller.ex0
-rw-r--r--lib/pleroma/web/pleroma_api/controllers/bookmark_folder_controller.ex68
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/pleroma_api/controllers/chat_controller.ex69
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/pleroma_api/controllers/conversation_controller.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/pleroma_api/controllers/emoji_file_controller.ex24
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex29
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/pleroma_api/controllers/emoji_reaction_controller.ex24
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/pleroma_api/controllers/instances_controller.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex13
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/pleroma_api/controllers/notification_controller.ex16
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/pleroma_api/controllers/report_controller.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/pleroma_api/controllers/scrobble_controller.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/pleroma_api/controllers/settings_controller.ex0
-rw-r--r--lib/pleroma/web/pleroma_api/controllers/status_controller.ex66
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/pleroma_api/controllers/two_factor_authentication_controller.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/pleroma_api/controllers/user_import_controller.ex41
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/pleroma_api/views/account_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/pleroma_api/views/app_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/pleroma_api/views/backup_view.ex10
-rw-r--r--lib/pleroma/web/pleroma_api/views/bookmark_folder_view.ex42
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/pleroma_api/views/chat/message_reference_view.ex13
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/pleroma_api/views/chat_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/pleroma_api/views/conversation_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/pleroma_api/views/emoji_reaction_view.ex17
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/pleroma_api/views/notification_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/pleroma_api/views/report_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/pleroma_api/views/scrobble_view.ex1
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/plug.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/plugs/admin_secret_authentication_plug.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/plugs/authentication_plug.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/plugs/basic_auth_decoder_plug.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/plugs/cache.ex2
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/plugs/digest_plug.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/plugs/ensure_authenticated_plug.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/plugs/ensure_privileged_plug.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/plugs/ensure_public_or_authenticated_plug.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/plugs/ensure_user_token_assigns_plug.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/plugs/expect_authenticated_check_plug.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/plugs/expect_public_or_authenticated_check_plug.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/plugs/federating_plug.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/plugs/frontend_static.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/plugs/http_security_plug.ex20
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/plugs/http_signature_plug.ex2
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/plugs/idempotency_plug.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/plugs/instance_static.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/plugs/mapped_signature_to_identity_plug.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/plugs/o_auth_plug.ex4
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/plugs/o_auth_scopes_plug.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/plugs/plug_helper.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/plugs/rate_limiter.ex2
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/plugs/rate_limiter/limiter_supervisor.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/plugs/rate_limiter/supervisor.ex2
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/plugs/remote_ip.ex2
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/plugs/set_format_plug.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/plugs/set_locale_plug.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/plugs/set_user_session_id_plug.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/plugs/static_fe_plug.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/plugs/trailing_format_plug.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/plugs/uploaded_media.ex6
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/plugs/user_enabled_plug.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/plugs/user_fetcher_plug.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/plugs/user_is_admin_plug.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/plugs/user_is_staff_plug.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/plugs/user_tracking_plug.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/preload.ex4
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/preload/providers/instance.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/preload/providers/provider.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/preload/providers/timelines.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/preload/providers/user.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/push.ex2
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/push/impl.ex2
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/push/subscription.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/rel_me.ex0
-rw-r--r--lib/pleroma/web/rich_media/backfill.ex101
-rw-r--r--lib/pleroma/web/rich_media/card.ex157
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/rich_media/helpers.ex89
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/rich_media/parser.ex169
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/rich_media/parser/ttl.ex15
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/rich_media/parser/ttl/aws_signed_url.ex15
-rw-r--r--lib/pleroma/web/rich_media/parser/ttl/opengraph.ex20
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/rich_media/parsers/meta_tags_parser.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/rich_media/parsers/o_embed.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/rich_media/parsers/ogp.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/rich_media/parsers/twitter_card.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/router.ex223
-rwxr-xr-xlib/pleroma/web/router.ex~1017
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/shout_channel.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/static_fe/static_fe_controller.ex13
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/static_fe/static_fe_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/streamer.ex70
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/email/digest.html.eex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/email/new_users_digest.html.eex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/embed/_attachment.html.eex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/embed/show.html.eex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/feed/feed/_activity.atom.eex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/feed/feed/_activity.rss.eex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/feed/feed/_author.atom.eex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/feed/feed/_author.rss.eex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/feed/feed/_tag_activity.atom.eex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/feed/feed/_tag_activity.xml.eex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/feed/feed/_tag_author.atom.eex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/feed/feed/tag.atom.eex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/feed/feed/tag.rss.eex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/feed/feed/user.atom.eex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/feed/feed/user.rss.eex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/layout/app.html.eex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/layout/email.html.eex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/layout/email_styled.html.eex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/layout/embed.html.eex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/layout/metadata_player.html.eex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/layout/static_fe.html.eex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/mailer/subscription/unsubscribe_failure.html.eex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/mailer/subscription/unsubscribe_success.html.eex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/o_auth/mfa/recovery.html.eex8
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/o_auth/mfa/totp.html.eex8
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/o_auth/o_auth/_scopes.html.eex2
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/o_auth/o_auth/consumer.html.eex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/o_auth/o_auth/oob_authorization_created.html.eex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/o_auth/o_auth/oob_token_exists.html.eex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/o_auth/o_auth/register.html.eex8
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/o_auth/o_auth/show.html.eex10
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/static_fe/static_fe/_attachment.html.eex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/static_fe/static_fe/_notice.html.eex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/static_fe/static_fe/_user_card.html.eex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/static_fe/static_fe/conversation.html.eex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/static_fe/static_fe/error.html.eex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/static_fe/static_fe/profile.html.eex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/twitter_api/password/invalid_token.html.eex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/twitter_api/password/reset.html.eex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/twitter_api/password/reset_failed.html.eex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/twitter_api/password/reset_success.html.eex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/twitter_api/remote_follow/follow.html.eex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/twitter_api/remote_follow/follow_login.html.eex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/twitter_api/remote_follow/follow_mfa.html.eex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/twitter_api/remote_follow/followed.html.eex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/twitter_api/util/status_interact.html.eex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/templates/twitter_api/util/subscribe.html.eex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/translation_helpers.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/twitter_api/controller.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/twitter_api/controllers/password_controller.ex2
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/twitter_api/controllers/remote_follow_controller.ex11
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/twitter_api/controllers/util_controller.ex59
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/twitter_api/twitter_api.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/twitter_api/views/password_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/twitter_api/views/remote_follow_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/twitter_api/views/token_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/twitter_api/views/util_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/uploader_controller.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/utils/guards.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/utils/params.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/views/email_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/views/embed_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/views/error_helpers.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/views/error_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/views/layout_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/views/mailer/subscription_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/views/manifest_view.ex0
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/views/streamer_view.ex61
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/web_finger.ex10
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/web_finger/web_finger_controller.ex2
-rw-r--r--[-rwxr-xr-x]lib/pleroma/web/xml.ex2
452 files changed, 4855 insertions, 2374 deletions
diff --git a/lib/pleroma/web/.router.ex.un~ b/lib/pleroma/web/.router.ex.un~
deleted file mode 100755
index 7ec278f..0000000
--- a/lib/pleroma/web/.router.ex.un~
+++ /dev/null
Binary files differ
diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex
index 1ab2db9..a1fccc7 100755..100644
--- a/lib/pleroma/web/activity_pub/activity_pub.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub.ex
@@ -74,29 +74,40 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
defp check_remote_limit(_), do: true
def increase_note_count_if_public(actor, object) do
- if is_public?(object), do: User.increase_note_count(actor), else: {:ok, actor}
+ if public?(object), do: User.increase_note_count(actor), else: {:ok, actor}
end
def decrease_note_count_if_public(actor, object) do
- if is_public?(object), do: User.decrease_note_count(actor), else: {:ok, actor}
+ if public?(object), do: User.decrease_note_count(actor), else: {:ok, actor}
end
def update_last_status_at_if_public(actor, object) do
- if is_public?(object), do: User.update_last_status_at(actor), else: {:ok, actor}
+ if public?(object), do: User.update_last_status_at(actor), else: {:ok, actor}
end
defp increase_replies_count_if_reply(%{
"object" => %{"inReplyTo" => reply_ap_id} = object,
"type" => "Create"
}) do
- if is_public?(object) do
+ if public?(object) do
Object.increase_replies_count(reply_ap_id)
end
end
defp increase_replies_count_if_reply(_create_data), do: :noop
- @object_types ~w[ChatMessage Question Answer Audio Video Event Article Note Page]
+ defp increase_quotes_count_if_quote(%{
+ "object" => %{"quoteUrl" => quote_ap_id} = object,
+ "type" => "Create"
+ }) do
+ if public?(object) do
+ Object.increase_quotes_count(quote_ap_id)
+ end
+ end
+
+ defp increase_quotes_count_if_quote(_create_data), do: :noop
+
+ @object_types ~w[ChatMessage Question Answer Audio Video Image Event Article Note Page]
@impl true
def persist(%{"type" => type} = object, meta) when type in @object_types do
with {:ok, object} <- Object.create(object) do
@@ -136,9 +147,10 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
# Splice in the child object if we have one.
activity = Maps.put_if_present(activity, :object, object)
- ConcurrentLimiter.limit(Pleroma.Web.RichMedia.Helpers, fn ->
- Task.start(fn -> Pleroma.Web.RichMedia.Helpers.fetch_data_for_activity(activity) end)
- end)
+ Pleroma.Web.RichMedia.Card.get_by_activity(activity)
+
+ # Add local posts to search index
+ if local, do: Pleroma.Search.add_to_index(activity)
{:ok, activity}
else
@@ -163,7 +175,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
id: "pleroma:fakeid"
}
- Pleroma.Web.RichMedia.Helpers.fetch_data_for_activity(activity)
+ Pleroma.Web.RichMedia.Card.get_by_activity(activity)
{:ok, activity}
{:remote_limit_pass, _} ->
@@ -299,11 +311,13 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
with {:ok, activity} <- insert(create_data, local, fake),
{:fake, false, activity} <- {:fake, fake, activity},
_ <- increase_replies_count_if_reply(create_data),
+ _ <- increase_quotes_count_if_quote(create_data),
{:quick_insert, false, activity} <- {:quick_insert, quick_insert?, activity},
{:ok, _actor} <- increase_note_count_if_public(actor, activity),
{:ok, _actor} <- update_last_status_at_if_public(actor, activity),
_ <- notify_and_stream(activity),
:ok <- maybe_schedule_poll_notifications(activity),
+ :ok <- maybe_handle_group_posts(activity),
:ok <- maybe_federate(activity) do
{:ok, activity}
else
@@ -455,6 +469,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|> maybe_preload_objects(opts)
|> maybe_preload_bookmarks(opts)
|> maybe_set_thread_muted_field(opts)
+ |> restrict_unauthenticated(opts[:user])
|> restrict_blocked(opts)
|> restrict_blockers_visibility(opts)
|> restrict_recipients(recipients, opts[:user])
@@ -482,7 +497,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
end
@spec fetch_latest_direct_activity_id_for_context(String.t(), keyword() | map()) ::
- FlakeId.Ecto.CompatType.t() | nil
+ Ecto.UUID.t() | nil
def fetch_latest_direct_activity_id_for_context(context, opts \\ %{}) do
context
|> fetch_activities_for_context_query(Map.merge(%{skip_preload: true}, opts))
@@ -1215,6 +1230,35 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
defp restrict_filtered(query, _), do: query
+ defp restrict_unauthenticated(query, nil) do
+ local = Config.restrict_unauthenticated_access?(:activities, :local)
+ remote = Config.restrict_unauthenticated_access?(:activities, :remote)
+
+ cond do
+ local and remote ->
+ from(activity in query, where: false)
+
+ local ->
+ from(activity in query, where: activity.local == false)
+
+ remote ->
+ from(activity in query, where: activity.local == true)
+
+ true ->
+ query
+ end
+ end
+
+ defp restrict_unauthenticated(query, _), do: query
+
+ defp restrict_quote_url(query, %{quote_url: quote_url}) do
+ from([_activity, object] in query,
+ where: fragment("(?)->'quoteUrl' = ?", object.data, ^quote_url)
+ )
+ end
+
+ defp restrict_quote_url(query, _), do: query
+
defp exclude_poll_votes(query, %{include_poll_votes: true}), do: query
defp exclude_poll_votes(query, _) do
@@ -1377,6 +1421,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|> restrict_instance(opts)
|> restrict_announce_object_actor(opts)
|> restrict_filtered(opts)
+ |> restrict_quote_url(opts)
|> maybe_restrict_deactivated_users(opts)
|> exclude_poll_votes(opts)
|> exclude_chat_messages(opts)
@@ -1547,7 +1592,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
%{
ap_id: data["id"],
uri: get_actor_url(data["url"]),
- ap_enabled: true,
banner: normalize_image(data["image"]),
fields: fields,
emoji: emojis,
@@ -1652,9 +1696,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
Fetcher.fetch_and_contain_remote_object_from_id(first) do
{:ok, false}
else
- {:error, {:ok, %{status: code}}} when code in [401, 403] -> {:ok, true}
- {:error, _} = e -> e
- e -> {:error, e}
+ {:error, _} -> {:ok, true}
end
end
@@ -1668,7 +1710,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
end
end
- def fetch_and_prepare_user_from_ap_id(ap_id, additional \\ []) do
+ defp fetch_and_prepare_user_from_ap_id(ap_id, additional) do
with {:ok, data} <- Fetcher.fetch_and_contain_remote_object_from_id(ap_id),
{:ok, data} <- user_data_from_user_object(data, additional) do
{:ok, maybe_update_follow_information(data)}
@@ -1721,6 +1763,11 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
end)
end
+ def pin_data_from_featured_collection(obj) do
+ Logger.error("Could not parse featured collection #{inspect(obj)}")
+ %{}
+ end
+
def fetch_and_prepare_featured_from_ap_id(nil) do
{:ok, %{}}
end
@@ -1751,24 +1798,20 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
def make_user_from_ap_id(ap_id, additional \\ []) do
user = User.get_cached_by_ap_id(ap_id)
- if user && !User.ap_enabled?(user) do
- Transmogrifier.upgrade_user_from_ap_id(ap_id)
- else
- with {:ok, data} <- fetch_and_prepare_user_from_ap_id(ap_id, additional) do
- {:ok, _pid} = Task.start(fn -> pinned_fetch_task(data) end)
+ with {:ok, data} <- fetch_and_prepare_user_from_ap_id(ap_id, additional) do
+ {:ok, _pid} = Task.start(fn -> pinned_fetch_task(data) end)
- if user do
- user
- |> User.remote_user_changeset(data)
- |> User.update_and_set_cache()
- else
- maybe_handle_clashing_nickname(data)
+ if user do
+ user
+ |> User.remote_user_changeset(data)
+ |> User.update_and_set_cache()
+ else
+ maybe_handle_clashing_nickname(data)
- data
- |> User.remote_user_changeset()
- |> Repo.insert()
- |> User.set_cache()
- end
+ data
+ |> User.remote_user_changeset()
+ |> Repo.insert()
+ |> User.set_cache()
end
end
end
diff --git a/lib/pleroma/web/activity_pub/activity_pub/persisting.ex b/lib/pleroma/web/activity_pub/activity_pub/persisting.ex
index 3dbfdee..3dbfdee 100755..100644
--- a/lib/pleroma/web/activity_pub/activity_pub/persisting.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub/persisting.ex
diff --git a/lib/pleroma/web/activity_pub/activity_pub/streaming.ex b/lib/pleroma/web/activity_pub/activity_pub/streaming.ex
index d735817..d735817 100755..100644
--- a/lib/pleroma/web/activity_pub/activity_pub/streaming.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub/streaming.ex
diff --git a/lib/pleroma/web/activity_pub/activity_pub_controller.ex b/lib/pleroma/web/activity_pub/activity_pub_controller.ex
index 1357c37..e38a949 100755..100644
--- a/lib/pleroma/web/activity_pub/activity_pub_controller.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub_controller.ex
@@ -273,12 +273,17 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
end
def inbox(%{assigns: %{valid_signature: true}} = conn, %{"nickname" => nickname} = params) do
- with %User{} = recipient <- User.get_cached_by_nickname(nickname),
- {:ok, %User{} = actor} <- User.get_or_fetch_by_ap_id(params["actor"]),
+ with %User{is_active: true} = recipient <- User.get_cached_by_nickname(nickname),
+ {:ok, %User{is_active: true} = actor} <- User.get_or_fetch_by_ap_id(params["actor"]),
true <- Utils.recipient_in_message(recipient, actor, params),
params <- Utils.maybe_splice_recipient(recipient.ap_id, params) do
Federator.incoming_ap_doc(params)
json(conn, "ok")
+ else
+ _ ->
+ conn
+ |> put_status(:bad_request)
+ |> json("Invalid request.")
end
end
@@ -287,10 +292,9 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
json(conn, "ok")
end
- def inbox(%{assigns: %{valid_signature: false}} = conn, _params) do
- conn
- |> put_status(:bad_request)
- |> json("Invalid HTTP Signature")
+ def inbox(%{assigns: %{valid_signature: false}, req_headers: req_headers} = conn, params) do
+ Federator.incoming_ap_doc(%{req_headers: req_headers, params: params})
+ json(conn, "ok")
end
# POST /relay/inbox -or- POST /internal/fetch/inbox
@@ -476,7 +480,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
|> json(message)
e ->
- Logger.warn(fn -> "AP C2S: #{inspect(e)}" end)
+ Logger.warning(fn -> "AP C2S: #{inspect(e)}" end)
conn
|> put_status(:bad_request)
diff --git a/lib/pleroma/web/activity_pub/builder.ex b/lib/pleroma/web/activity_pub/builder.ex
index 5320475..2a1e562 100755..100644
--- a/lib/pleroma/web/activity_pub/builder.ex
+++ b/lib/pleroma/web/activity_pub/builder.ex
@@ -9,6 +9,7 @@ defmodule Pleroma.Web.ActivityPub.Builder do
This module encodes our addressing policies and general shape of our objects.
"""
+ alias Pleroma.Activity
alias Pleroma.Emoji
alias Pleroma.Object
alias Pleroma.User
@@ -16,6 +17,7 @@ defmodule Pleroma.Web.ActivityPub.Builder do
alias Pleroma.Web.ActivityPub.Utils
alias Pleroma.Web.ActivityPub.Visibility
alias Pleroma.Web.CommonAPI.ActivityDraft
+ alias Pleroma.Web.Endpoint
require Pleroma.Constants
@@ -54,13 +56,87 @@ defmodule Pleroma.Web.ActivityPub.Builder do
{:ok, data, []}
end
+ defp unicode_emoji_react(_object, data, emoji) do
+ data
+ |> Map.put("content", emoji)
+ |> Map.put("type", "EmojiReact")
+ end
+
+ defp add_emoji_content(data, emoji, url) do
+ tag = [
+ %{
+ "id" => url,
+ "type" => "Emoji",
+ "name" => Emoji.maybe_quote(emoji),
+ "icon" => %{
+ "type" => "Image",
+ "url" => url
+ }
+ }
+ ]
+
+ data
+ |> Map.put("content", Emoji.maybe_quote(emoji))
+ |> Map.put("type", "EmojiReact")
+ |> Map.put("tag", tag)
+ end
+
+ defp remote_custom_emoji_react(
+ %{data: %{"reactions" => existing_reactions}},
+ data,
+ emoji
+ ) do
+ [emoji_code, instance] = String.split(Emoji.maybe_strip_name(emoji), "@")
+
+ matching_reaction =
+ Enum.find(
+ existing_reactions,
+ fn [name, _, url] ->
+ if url != nil do
+ url = URI.parse(url)
+ url.host == instance && name == emoji_code
+ end
+ end
+ )
+
+ if matching_reaction do
+ [name, _, url] = matching_reaction
+ add_emoji_content(data, name, url)
+ else
+ {:error, "Could not react"}
+ end
+ end
+
+ defp remote_custom_emoji_react(_object, _data, _emoji) do
+ {:error, "Could not react"}
+ end
+
+ defp local_custom_emoji_react(data, emoji) do
+ with %{file: path} = emojo <- Emoji.get(emoji) do
+ url = "#{Endpoint.url()}#{path}"
+ add_emoji_content(data, emojo.code, url)
+ else
+ _ -> {:error, "Emoji does not exist"}
+ end
+ end
+
+ defp custom_emoji_react(object, data, emoji) do
+ if String.contains?(emoji, "@") do
+ remote_custom_emoji_react(object, data, emoji)
+ else
+ local_custom_emoji_react(data, emoji)
+ end
+ end
+
@spec emoji_react(User.t(), Object.t(), String.t()) :: {:ok, map(), keyword()}
def emoji_react(actor, object, emoji) do
with {:ok, data, meta} <- object_action(actor, object) do
data =
- data
- |> Map.put("content", emoji)
- |> Map.put("type", "EmojiReact")
+ if Emoji.unicode?(emoji) do
+ unicode_emoji_react(object, data, emoji)
+ else
+ custom_emoji_react(object, data, emoji)
+ end
{:ok, data, meta}
end
@@ -142,6 +218,7 @@ defmodule Pleroma.Web.ActivityPub.Builder do
"tag" => Keyword.values(draft.tags) |> Enum.uniq()
}
|> add_in_reply_to(draft.in_reply_to)
+ |> add_quote(draft.quote_post)
|> Map.merge(draft.extra)
{:ok, data, []}
@@ -157,6 +234,16 @@ defmodule Pleroma.Web.ActivityPub.Builder do
end
end
+ defp add_quote(object, nil), do: object
+
+ defp add_quote(object, quote_post) do
+ with %Object{} = quote_object <- Object.normalize(quote_post, fetch: false) do
+ Map.put(object, "quoteUrl", quote_object.data["id"])
+ else
+ _ -> object
+ end
+ end
+
def chat_message(actor, recipient, content, opts \\ []) do
basic = %{
"id" => Utils.generate_object_id(),
@@ -261,7 +348,7 @@ defmodule Pleroma.Web.ActivityPub.Builder do
actor.ap_id == Relay.ap_id() ->
[actor.follower_address]
- public? and Visibility.is_local_public?(object) ->
+ public? and Visibility.local_public?(object) ->
[actor.follower_address, object.data["actor"], Utils.as_local_public()]
public? ->
@@ -289,7 +376,7 @@ defmodule Pleroma.Web.ActivityPub.Builder do
# Address the actor of the object, and our actor's follower collection if the post is public.
to =
- if Visibility.is_public?(object) do
+ if Visibility.public?(object) do
[actor.follower_address, object.data["actor"]]
else
[object.data["actor"]]
diff --git a/lib/pleroma/web/activity_pub/internal_fetch_actor.ex b/lib/pleroma/web/activity_pub/internal_fetch_actor.ex
index 0837238..0837238 100755..100644
--- a/lib/pleroma/web/activity_pub/internal_fetch_actor.ex
+++ b/lib/pleroma/web/activity_pub/internal_fetch_actor.ex
diff --git a/lib/pleroma/web/activity_pub/mrf.ex b/lib/pleroma/web/activity_pub/mrf.ex
index ff9f844..1071f8e 100755..100644
--- a/lib/pleroma/web/activity_pub/mrf.ex
+++ b/lib/pleroma/web/activity_pub/mrf.ex
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF do
@@ -54,6 +54,8 @@ defmodule Pleroma.Web.ActivityPub.MRF do
@required_description_keys [:key, :related_policy]
def filter_one(policy, message) do
+ Code.ensure_loaded(policy)
+
should_plug_history? =
if function_exported?(policy, :history_awareness, 0) do
policy.history_awareness()
@@ -137,7 +139,16 @@ defmodule Pleroma.Web.ActivityPub.MRF do
@spec subdomains_regex([String.t()]) :: [Regex.t()]
def subdomains_regex(domains) when is_list(domains) do
- for domain <- domains, do: ~r(^#{String.replace(domain, "*.", "(.*\\.)*")}$)i
+ for domain <- domains do
+ try do
+ target = String.replace(domain, "*.", "(.*\\.)*")
+ ~r<^#{target}$>i
+ rescue
+ e ->
+ Logger.error("MRF: Invalid subdomain Regex: #{domain}")
+ reraise e, __STACKTRACE__
+ end
+ end
end
@spec subdomain_match?([Regex.t()], String.t()) :: boolean()
@@ -188,6 +199,8 @@ defmodule Pleroma.Web.ActivityPub.MRF do
def config_descriptions(policies) do
Enum.reduce(policies, @mrf_config_descriptions, fn policy, acc ->
+ Code.ensure_loaded(policy)
+
if function_exported?(policy, :config_description, 0) do
description =
@default_description
@@ -199,7 +212,7 @@ defmodule Pleroma.Web.ActivityPub.MRF do
if Enum.all?(@required_description_keys, &Map.has_key?(description, &1)) do
[description | acc]
else
- Logger.warn(
+ Logger.warning(
"#{policy} config description doesn't have one or all required keys #{inspect(@required_description_keys)}"
)
diff --git a/lib/pleroma/web/activity_pub/mrf/activity_expiration_policy.ex b/lib/pleroma/web/activity_pub/mrf/activity_expiration_policy.ex
index 88f6ca0..88f6ca0 100755..100644
--- a/lib/pleroma/web/activity_pub/mrf/activity_expiration_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/activity_expiration_policy.ex
diff --git a/lib/pleroma/web/activity_pub/mrf/anti_followbot_policy.ex b/lib/pleroma/web/activity_pub/mrf/anti_followbot_policy.ex
index 97d75ec..df4ba81 100755..100644
--- a/lib/pleroma/web/activity_pub/mrf/anti_followbot_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/anti_followbot_policy.ex
@@ -56,8 +56,6 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicy do
nick_score + name_score + actor_type_score
end
- defp determine_if_followbot(_), do: 0.0
-
defp bot_allowed?(%{"object" => target}, bot_actor) do
%User{} = user = normalize_by_ap_id(target)
diff --git a/lib/pleroma/web/activity_pub/mrf/anti_link_spam_policy.ex b/lib/pleroma/web/activity_pub/mrf/anti_link_spam_policy.ex
index 3ec9c52..3ec9c52 100755..100644
--- a/lib/pleroma/web/activity_pub/mrf/anti_link_spam_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/anti_link_spam_policy.ex
diff --git a/lib/pleroma/web/activity_pub/mrf/drop_policy.ex b/lib/pleroma/web/activity_pub/mrf/drop_policy.ex
index ad09368..ad09368 100755..100644
--- a/lib/pleroma/web/activity_pub/mrf/drop_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/drop_policy.ex
diff --git a/lib/pleroma/web/activity_pub/mrf/emoji_policy.ex b/lib/pleroma/web/activity_pub/mrf/emoji_policy.ex
new file mode 100644
index 0000000..f884962
--- /dev/null
+++ b/lib/pleroma/web/activity_pub/mrf/emoji_policy.ex
@@ -0,0 +1,281 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.MRF.EmojiPolicy do
+ require Pleroma.Constants
+
+ alias Pleroma.Object.Updater
+ alias Pleroma.Web.ActivityPub.MRF.Utils
+
+ @moduledoc "Reject or force-unlisted emojis with certain URLs or names"
+
+ @behaviour Pleroma.Web.ActivityPub.MRF.Policy
+
+ defp config_remove_url do
+ Pleroma.Config.get([:mrf_emoji, :remove_url], [])
+ end
+
+ defp config_remove_shortcode do
+ Pleroma.Config.get([:mrf_emoji, :remove_shortcode], [])
+ end
+
+ defp config_unlist_url do
+ Pleroma.Config.get([:mrf_emoji, :federated_timeline_removal_url], [])
+ end
+
+ defp config_unlist_shortcode do
+ Pleroma.Config.get([:mrf_emoji, :federated_timeline_removal_shortcode], [])
+ end
+
+ @impl Pleroma.Web.ActivityPub.MRF.Policy
+ def history_awareness, do: :manual
+
+ @impl Pleroma.Web.ActivityPub.MRF.Policy
+ def filter(%{"type" => type, "object" => %{"type" => objtype} = object} = message)
+ when type in ["Create", "Update"] and objtype in Pleroma.Constants.status_object_types() do
+ with {:ok, object} <-
+ Updater.do_with_history(object, fn object ->
+ {:ok, process_remove(object, :url, config_remove_url())}
+ end),
+ {:ok, object} <-
+ Updater.do_with_history(object, fn object ->
+ {:ok, process_remove(object, :shortcode, config_remove_shortcode())}
+ end),
+ activity <- Map.put(message, "object", object),
+ activity <- maybe_delist(activity) do
+ {:ok, activity}
+ end
+ end
+
+ @impl Pleroma.Web.ActivityPub.MRF.Policy
+ def filter(%{"type" => type} = object) when type in Pleroma.Constants.actor_types() do
+ with object <- process_remove(object, :url, config_remove_url()),
+ object <- process_remove(object, :shortcode, config_remove_shortcode()) do
+ {:ok, object}
+ end
+ end
+
+ @impl Pleroma.Web.ActivityPub.MRF.Policy
+ def filter(%{"type" => "EmojiReact"} = object) do
+ with {:ok, _} <-
+ matched_emoji_checker(config_remove_url(), config_remove_shortcode()).(object) do
+ {:ok, object}
+ else
+ _ ->
+ {:reject, "[EmojiPolicy] Rejected for having disallowed emoji"}
+ end
+ end
+
+ @impl Pleroma.Web.ActivityPub.MRF.Policy
+ def filter(message) do
+ {:ok, message}
+ end
+
+ defp match_string?(string, pattern) when is_binary(pattern) do
+ string == pattern
+ end
+
+ defp match_string?(string, %Regex{} = pattern) do
+ String.match?(string, pattern)
+ end
+
+ defp match_any?(string, patterns) do
+ Enum.any?(patterns, &match_string?(string, &1))
+ end
+
+ defp url_from_tag(%{"icon" => %{"url" => url}}), do: url
+ defp url_from_tag(_), do: nil
+
+ defp url_from_emoji({_name, url}), do: url
+
+ defp shortcode_from_tag(%{"name" => name}) when is_binary(name), do: String.trim(name, ":")
+ defp shortcode_from_tag(_), do: nil
+
+ defp shortcode_from_emoji({name, _url}), do: name
+
+ defp process_remove(object, :url, patterns) do
+ process_remove_impl(object, &url_from_tag/1, &url_from_emoji/1, patterns)
+ end
+
+ defp process_remove(object, :shortcode, patterns) do
+ process_remove_impl(object, &shortcode_from_tag/1, &shortcode_from_emoji/1, patterns)
+ end
+
+ defp process_remove_impl(object, extract_from_tag, extract_from_emoji, patterns) do
+ object =
+ if object["tag"] do
+ Map.put(
+ object,
+ "tag",
+ Enum.filter(
+ object["tag"],
+ fn
+ %{"type" => "Emoji"} = tag ->
+ str = extract_from_tag.(tag)
+
+ if is_binary(str) do
+ not match_any?(str, patterns)
+ else
+ true
+ end
+
+ _ ->
+ true
+ end
+ )
+ )
+ else
+ object
+ end
+
+ object =
+ if object["emoji"] do
+ Map.put(
+ object,
+ "emoji",
+ object["emoji"]
+ |> Enum.reduce(%{}, fn {name, url} = emoji, acc ->
+ if not match_any?(extract_from_emoji.(emoji), patterns) do
+ Map.put(acc, name, url)
+ else
+ acc
+ end
+ end)
+ )
+ else
+ object
+ end
+
+ object
+ end
+
+ defp matched_emoji_checker(urls, shortcodes) do
+ fn object ->
+ if any_emoji_match?(object, &url_from_tag/1, &url_from_emoji/1, urls) or
+ any_emoji_match?(
+ object,
+ &shortcode_from_tag/1,
+ &shortcode_from_emoji/1,
+ shortcodes
+ ) do
+ {:matched, nil}
+ else
+ {:ok, %{}}
+ end
+ end
+ end
+
+ defp maybe_delist(%{"object" => object, "to" => to, "type" => "Create"} = activity) do
+ check = matched_emoji_checker(config_unlist_url(), config_unlist_shortcode())
+
+ should_delist? = fn object ->
+ with {:ok, _} <- Pleroma.Object.Updater.do_with_history(object, check) do
+ false
+ else
+ _ -> true
+ end
+ end
+
+ if Pleroma.Constants.as_public() in to and should_delist?.(object) do
+ to = List.delete(to, Pleroma.Constants.as_public())
+ cc = [Pleroma.Constants.as_public() | activity["cc"] || []]
+
+ activity
+ |> Map.put("to", to)
+ |> Map.put("cc", cc)
+ else
+ activity
+ end
+ end
+
+ defp maybe_delist(activity), do: activity
+
+ defp any_emoji_match?(object, extract_from_tag, extract_from_emoji, patterns) do
+ Kernel.||(
+ Enum.any?(
+ object["tag"] || [],
+ fn
+ %{"type" => "Emoji"} = tag ->
+ str = extract_from_tag.(tag)
+
+ if is_binary(str) do
+ match_any?(str, patterns)
+ else
+ false
+ end
+
+ _ ->
+ false
+ end
+ ),
+ (object["emoji"] || [])
+ |> Enum.any?(fn emoji -> match_any?(extract_from_emoji.(emoji), patterns) end)
+ )
+ end
+
+ @impl Pleroma.Web.ActivityPub.MRF.Policy
+ def describe do
+ mrf_emoji =
+ Pleroma.Config.get(:mrf_emoji, [])
+ |> Enum.map(fn {key, value} ->
+ {key, Enum.map(value, &Utils.describe_regex_or_string/1)}
+ end)
+ |> Enum.into(%{})
+
+ {:ok, %{mrf_emoji: mrf_emoji}}
+ end
+
+ @impl Pleroma.Web.ActivityPub.MRF.Policy
+ def config_description do
+ %{
+ key: :mrf_emoji,
+ related_policy: "Pleroma.Web.ActivityPub.MRF.EmojiPolicy",
+ label: "MRF Emoji",
+ description:
+ "Reject or force-unlisted emojis whose URLs or names match a keyword or [Regex](https://hexdocs.pm/elixir/Regex.html).",
+ children: [
+ %{
+ key: :remove_url,
+ type: {:list, :string},
+ description: """
+ A list of patterns which result in emoji whose URL matches being removed from the message. This will apply to statuses, emoji reactions, and user profiles.
+
+ Each pattern can be a string or [Regex](https://hexdocs.pm/elixir/Regex.html) in the format of `~r/PATTERN/`.
+ """,
+ suggestions: ["https://example.org/foo.png", ~r/example.org\/foo/iu]
+ },
+ %{
+ key: :remove_shortcode,
+ type: {:list, :string},
+ description: """
+ A list of patterns which result in emoji whose shortcode matches being removed from the message. This will apply to statuses, emoji reactions, and user profiles.
+
+ Each pattern can be a string or [Regex](https://hexdocs.pm/elixir/Regex.html) in the format of `~r/PATTERN/`.
+ """,
+ suggestions: ["foo", ~r/foo/iu]
+ },
+ %{
+ key: :federated_timeline_removal_url,
+ type: {:list, :string},
+ description: """
+ A list of patterns which result in message with emojis whose URLs match being removed from federated timelines (a.k.a unlisted). This will apply only to statuses.
+
+ Each pattern can be a string or [Regex](https://hexdocs.pm/elixir/Regex.html) in the format of `~r/PATTERN/`.
+ """,
+ suggestions: ["https://example.org/foo.png", ~r/example.org\/foo/iu]
+ },
+ %{
+ key: :federated_timeline_removal_shortcode,
+ type: {:list, :string},
+ description: """
+ A list of patterns which result in message with emojis whose shortcodes match being removed from federated timelines (a.k.a unlisted). This will apply only to statuses.
+
+ Each pattern can be a string or [Regex](https://hexdocs.pm/elixir/Regex.html) in the format of `~r/PATTERN/`.
+ """,
+ suggestions: ["foo", ~r/foo/iu]
+ }
+ ]
+ }
+ end
+end
diff --git a/lib/pleroma/web/activity_pub/mrf/ensure_re_prepended.ex b/lib/pleroma/web/activity_pub/mrf/ensure_re_prepended.ex
index a148cc1..a148cc1 100755..100644
--- a/lib/pleroma/web/activity_pub/mrf/ensure_re_prepended.ex
+++ b/lib/pleroma/web/activity_pub/mrf/ensure_re_prepended.ex
diff --git a/lib/pleroma/web/activity_pub/mrf/follow_bot_policy.ex b/lib/pleroma/web/activity_pub/mrf/follow_bot_policy.ex
index 5b6adbb..5a4a976 100755..100644
--- a/lib/pleroma/web/activity_pub/mrf/follow_bot_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/follow_bot_policy.ex
@@ -19,7 +19,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.FollowBotPolicy do
try_follow(follower, message)
else
nil ->
- Logger.warn(
+ Logger.warning(
"#{__MODULE__} skipped because of missing `:mrf_follow_bot, :follower_nickname` configuration, the :follower_nickname
account does not exist, or the account is not correctly configured as a bot."
)
diff --git a/lib/pleroma/web/activity_pub/mrf/force_bot_unlisted_policy.ex b/lib/pleroma/web/activity_pub/mrf/force_bot_unlisted_policy.ex
index 8cec8ea..8cec8ea 100755..100644
--- a/lib/pleroma/web/activity_pub/mrf/force_bot_unlisted_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/force_bot_unlisted_policy.ex
diff --git a/lib/pleroma/web/activity_pub/mrf/force_mention.ex b/lib/pleroma/web/activity_pub/mrf/force_mention.ex
new file mode 100644
index 0000000..3853489
--- /dev/null
+++ b/lib/pleroma/web/activity_pub/mrf/force_mention.ex
@@ -0,0 +1,59 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2024 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.MRF.ForceMention do
+ require Pleroma.Constants
+
+ alias Pleroma.Config
+ alias Pleroma.Object
+ alias Pleroma.User
+
+ @behaviour Pleroma.Web.ActivityPub.MRF.Policy
+
+ defp get_author(url) do
+ with %Object{data: %{"actor" => actor}} <- Object.normalize(url, fetch: false),
+ %User{ap_id: ap_id, nickname: nickname} <- User.get_cached_by_ap_id(actor) do
+ %{"type" => "Mention", "href" => ap_id, "name" => "@#{nickname}"}
+ else
+ _ -> nil
+ end
+ end
+
+ defp prepend_author(tags, _, false), do: tags
+
+ defp prepend_author(tags, nil, _), do: tags
+
+ defp prepend_author(tags, url, _) do
+ actor = get_author(url)
+
+ if not is_nil(actor) do
+ [actor | tags]
+ else
+ tags
+ end
+ end
+
+ @impl true
+ def filter(%{"type" => "Create", "object" => %{"tag" => tag} = object} = activity) do
+ tag =
+ tag
+ |> prepend_author(
+ object["inReplyTo"],
+ Config.get([:mrf_force_mention, :mention_parent, true])
+ )
+ |> prepend_author(
+ object["quoteUrl"],
+ Config.get([:mrf_force_mention, :mention_quoted, true])
+ )
+ |> Enum.uniq()
+
+ {:ok, put_in(activity["object"]["tag"], tag)}
+ end
+
+ @impl true
+ def filter(object), do: {:ok, object}
+
+ @impl true
+ def describe, do: {:ok, %{}}
+end
diff --git a/lib/pleroma/web/activity_pub/mrf/force_mentions_in_content.ex b/lib/pleroma/web/activity_pub/mrf/force_mentions_in_content.ex
index 7022456..5532093 100755..100644
--- a/lib/pleroma/web/activity_pub/mrf/force_mentions_in_content.ex
+++ b/lib/pleroma/web/activity_pub/mrf/force_mentions_in_content.ex
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.ForceMentionsInContent do
@@ -95,11 +95,13 @@ defmodule Pleroma.Web.ActivityPub.MRF.ForceMentionsInContent do
|> Enum.reject(&is_nil/1)
|> sort_replied_user(replied_to_user)
- explicitly_mentioned_uris = extract_mention_uris_from_content(content)
+ explicitly_mentioned_uris =
+ extract_mention_uris_from_content(content)
+ |> MapSet.new()
added_mentions =
- Enum.reduce(mention_users, "", fn %User{ap_id: uri} = user, acc ->
- unless uri in explicitly_mentioned_uris do
+ Enum.reduce(mention_users, "", fn %User{ap_id: ap_id, uri: uri} = user, acc ->
+ if MapSet.disjoint?(MapSet.new([ap_id, uri]), explicitly_mentioned_uris) do
acc <> Formatter.mention_from_user(user, %{mentions_format: :compact}) <> " "
else
acc
diff --git a/lib/pleroma/web/activity_pub/mrf/hashtag_policy.ex b/lib/pleroma/web/activity_pub/mrf/hashtag_policy.ex
index b73fd97..fdb9a9d 100755..100644
--- a/lib/pleroma/web/activity_pub/mrf/hashtag_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/hashtag_policy.ex
@@ -9,7 +9,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.HashtagPolicy do
alias Pleroma.Object
@moduledoc """
- Reject, TWKN-remove or Set-Sensitive messsages with specific hashtags (without the leading #)
+ Reject, TWKN-remove or Set-Sensitive messages with specific hashtags (without the leading #)
Note: This MRF Policy is always enabled, if you want to disable it you have to set empty lists.
"""
@@ -84,7 +84,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.HashtagPolicy do
if hashtags != [] do
with {:ok, message} <- check_reject(message, hashtags),
{:ok, message} <-
- (if "type" == "Create" do
+ (if type == "Create" do
check_ftl_removal(message, hashtags)
else
{:ok, message}
diff --git a/lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex b/lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex
index 80e235d..80e235d 100755..100644
--- a/lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex
diff --git a/lib/pleroma/web/activity_pub/mrf/inline_quote_policy.ex b/lib/pleroma/web/activity_pub/mrf/inline_quote_policy.ex
new file mode 100644
index 0000000..b7a01c2
--- /dev/null
+++ b/lib/pleroma/web/activity_pub/mrf/inline_quote_policy.ex
@@ -0,0 +1,77 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.MRF.InlineQuotePolicy do
+ @moduledoc "Force a quote line into the message content."
+ @behaviour Pleroma.Web.ActivityPub.MRF.Policy
+
+ defp build_inline_quote(template, url) do
+ quote_line = String.replace(template, "{url}", "<a href=\"#{url}\">#{url}</a>")
+
+ "<span class=\"quote-inline\"><br/><br/>#{quote_line}</span>"
+ end
+
+ defp has_inline_quote?(content, quote_url) do
+ cond do
+ # Does the quote URL exist in the content?
+ content =~ quote_url -> true
+ # Does the content already have a .quote-inline span?
+ content =~ "<span class=\"quote-inline\">" -> true
+ # No inline quote found
+ true -> false
+ end
+ end
+
+ defp filter_object(%{"quoteUrl" => quote_url} = object) do
+ content = object["content"] || ""
+
+ if has_inline_quote?(content, quote_url) do
+ object
+ else
+ template = Pleroma.Config.get([:mrf_inline_quote, :template])
+
+ content =
+ if String.ends_with?(content, "</p>"),
+ do:
+ String.trim_trailing(content, "</p>") <>
+ build_inline_quote(template, quote_url) <> "</p>",
+ else: content <> build_inline_quote(template, quote_url)
+
+ Map.put(object, "content", content)
+ end
+ end
+
+ @impl true
+ def filter(%{"object" => %{"quoteUrl" => _} = object} = activity) do
+ {:ok, Map.put(activity, "object", filter_object(object))}
+ end
+
+ @impl true
+ def filter(object), do: {:ok, object}
+
+ @impl true
+ def describe, do: {:ok, %{}}
+
+ @impl Pleroma.Web.ActivityPub.MRF.Policy
+ def history_awareness, do: :auto
+
+ @impl true
+ def config_description do
+ %{
+ key: :mrf_inline_quote,
+ related_policy: "Pleroma.Web.ActivityPub.MRF.InlineQuotePolicy",
+ label: "MRF Inline Quote Policy",
+ description: "Force quote url to appear in post content.",
+ children: [
+ %{
+ key: :template,
+ type: :string,
+ description:
+ "The template to append to the post. `{url}` will be replaced with the actual link to the quoted post.",
+ suggestions: ["<bdi>RT:</bdi> {url}"]
+ }
+ ]
+ }
+ end
+end
diff --git a/lib/pleroma/web/activity_pub/mrf/keyword_policy.ex b/lib/pleroma/web/activity_pub/mrf/keyword_policy.ex
index 687ec6c..729da4e 100755..100644
--- a/lib/pleroma/web/activity_pub/mrf/keyword_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/keyword_policy.ex
@@ -5,18 +5,17 @@
defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
require Pleroma.Constants
+ alias Pleroma.Web.ActivityPub.MRF.Utils
+
@moduledoc "Reject or Word-Replace messages with a keyword or regex"
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
- defp string_matches?(string, _) when not is_binary(string) do
- false
- end
defp string_matches?(string, pattern) when is_binary(pattern) do
String.contains?(string, pattern)
end
- defp string_matches?(string, pattern) do
+ defp string_matches?(string, %Regex{} = pattern) do
String.match?(string, pattern)
end
@@ -128,7 +127,6 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
@impl true
def describe do
- # This horror is needed to convert regex sigils to strings
mrf_keyword =
Pleroma.Config.get(:mrf_keyword, [])
|> Enum.map(fn {key, value} ->
@@ -136,21 +134,12 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
Enum.map(value, fn
{pattern, replacement} ->
%{
- "pattern" =>
- if not is_binary(pattern) do
- inspect(pattern)
- else
- pattern
- end,
+ "pattern" => Utils.describe_regex_or_string(pattern),
"replacement" => replacement
}
pattern ->
- if not is_binary(pattern) do
- inspect(pattern)
- else
- pattern
- end
+ Utils.describe_regex_or_string(pattern)
end)}
end)
|> Enum.into(%{})
diff --git a/lib/pleroma/web/activity_pub/mrf/media_proxy_warming_policy.ex b/lib/pleroma/web/activity_pub/mrf/media_proxy_warming_policy.ex
index c95d35b..c95d35b 100755..100644
--- a/lib/pleroma/web/activity_pub/mrf/media_proxy_warming_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/media_proxy_warming_policy.ex
diff --git a/lib/pleroma/web/activity_pub/mrf/mention_policy.ex b/lib/pleroma/web/activity_pub/mrf/mention_policy.ex
index 8aa4f34..8aa4f34 100755..100644
--- a/lib/pleroma/web/activity_pub/mrf/mention_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/mention_policy.ex
diff --git a/lib/pleroma/web/activity_pub/mrf/no_empty_policy.ex b/lib/pleroma/web/activity_pub/mrf/no_empty_policy.ex
index 855cda3..12bf4dd 100755..100644
--- a/lib/pleroma/web/activity_pub/mrf/no_empty_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/no_empty_policy.ex
@@ -10,9 +10,9 @@ defmodule Pleroma.Web.ActivityPub.MRF.NoEmptyPolicy do
@impl true
def filter(%{"actor" => actor} = object) do
- with true <- is_local?(actor),
- true <- is_eligible_type?(object),
- true <- is_note?(object),
+ with true <- local?(actor),
+ true <- eligible_type?(object),
+ true <- note?(object),
false <- has_attachment?(object),
true <- only_mentions?(object) do
{:reject, "[NoEmptyPolicy]"}
@@ -24,7 +24,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.NoEmptyPolicy do
def filter(object), do: {:ok, object}
- defp is_local?(actor) do
+ defp local?(actor) do
if actor |> String.starts_with?("#{Endpoint.url()}") do
true
else
@@ -59,11 +59,11 @@ defmodule Pleroma.Web.ActivityPub.MRF.NoEmptyPolicy do
defp only_mentions?(_), do: false
- defp is_note?(%{"object" => %{"type" => "Note"}}), do: true
- defp is_note?(_), do: false
+ defp note?(%{"object" => %{"type" => "Note"}}), do: true
+ defp note?(_), do: false
- defp is_eligible_type?(%{"type" => type}) when type in ["Create", "Update"], do: true
- defp is_eligible_type?(_), do: false
+ defp eligible_type?(%{"type" => type}) when type in ["Create", "Update"], do: true
+ defp eligible_type?(_), do: false
@impl true
def describe, do: {:ok, %{}}
diff --git a/lib/pleroma/web/activity_pub/mrf/no_op_policy.ex b/lib/pleroma/web/activity_pub/mrf/no_op_policy.ex
index 8840c4f..8840c4f 100755..100644
--- a/lib/pleroma/web/activity_pub/mrf/no_op_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/no_op_policy.ex
diff --git a/lib/pleroma/web/activity_pub/mrf/no_placeholder_text_policy.ex b/lib/pleroma/web/activity_pub/mrf/no_placeholder_text_policy.ex
index f81e9e5..f81e9e5 100755..100644
--- a/lib/pleroma/web/activity_pub/mrf/no_placeholder_text_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/no_placeholder_text_policy.ex
diff --git a/lib/pleroma/web/activity_pub/mrf/normalize_markup.ex b/lib/pleroma/web/activity_pub/mrf/normalize_markup.ex
index 2dfc9a9..2dfc9a9 100755..100644
--- a/lib/pleroma/web/activity_pub/mrf/normalize_markup.ex
+++ b/lib/pleroma/web/activity_pub/mrf/normalize_markup.ex
diff --git a/lib/pleroma/web/activity_pub/mrf/object_age_policy.ex b/lib/pleroma/web/activity_pub/mrf/object_age_policy.ex
index df1a6dc..df1a6dc 100755..100644
--- a/lib/pleroma/web/activity_pub/mrf/object_age_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/object_age_policy.ex
diff --git a/lib/pleroma/web/activity_pub/mrf/pipeline_filtering.ex b/lib/pleroma/web/activity_pub/mrf/pipeline_filtering.ex
index b2477fe..b2477fe 100755..100644
--- a/lib/pleroma/web/activity_pub/mrf/pipeline_filtering.ex
+++ b/lib/pleroma/web/activity_pub/mrf/pipeline_filtering.ex
diff --git a/lib/pleroma/web/activity_pub/mrf/policy.ex b/lib/pleroma/web/activity_pub/mrf/policy.ex
index 0234de4..1f34883 100755..100644
--- a/lib/pleroma/web/activity_pub/mrf/policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/policy.ex
@@ -3,8 +3,8 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.Policy do
- @callback filter(Map.t()) :: {:ok | :reject, Map.t()}
- @callback describe() :: {:ok | :error, Map.t()}
+ @callback filter(map()) :: {:ok | :reject, map()}
+ @callback describe() :: {:ok | :error, map()}
@callback config_description() :: %{
optional(:children) => [map()],
key: atom(),
diff --git a/lib/pleroma/web/activity_pub/mrf/quote_to_link_tag_policy.ex b/lib/pleroma/web/activity_pub/mrf/quote_to_link_tag_policy.ex
new file mode 100644
index 0000000..ac353f0
--- /dev/null
+++ b/lib/pleroma/web/activity_pub/mrf/quote_to_link_tag_policy.ex
@@ -0,0 +1,49 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.MRF.QuoteToLinkTagPolicy do
+ @moduledoc "Force a Link tag for posts quoting another post. (may break outgoing federation of quote posts with older Pleroma versions)"
+ @behaviour Pleroma.Web.ActivityPub.MRF.Policy
+
+ alias Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes
+
+ require Pleroma.Constants
+
+ @impl Pleroma.Web.ActivityPub.MRF.Policy
+ def filter(%{"object" => %{"quoteUrl" => _} = object} = activity) do
+ {:ok, Map.put(activity, "object", filter_object(object))}
+ end
+
+ @impl Pleroma.Web.ActivityPub.MRF.Policy
+ def filter(object), do: {:ok, object}
+
+ @impl Pleroma.Web.ActivityPub.MRF.Policy
+ def describe, do: {:ok, %{}}
+
+ @impl Pleroma.Web.ActivityPub.MRF.Policy
+ def history_awareness, do: :auto
+
+ defp filter_object(%{"quoteUrl" => quote_url} = object) do
+ tags = object["tag"] || []
+
+ if Enum.any?(tags, fn tag ->
+ CommonFixes.object_link_tag?(tag) and tag["href"] == quote_url
+ end) do
+ object
+ else
+ object
+ |> Map.put(
+ "tag",
+ tags ++
+ [
+ %{
+ "type" => "Link",
+ "mediaType" => Pleroma.Constants.activity_json_canonical_mime_type(),
+ "href" => quote_url
+ }
+ ]
+ )
+ end
+ end
+end
diff --git a/lib/pleroma/web/activity_pub/mrf/reject_non_public.ex b/lib/pleroma/web/activity_pub/mrf/reject_non_public.ex
index 9d4a7a4..9d4a7a4 100755..100644
--- a/lib/pleroma/web/activity_pub/mrf/reject_non_public.ex
+++ b/lib/pleroma/web/activity_pub/mrf/reject_non_public.ex
diff --git a/lib/pleroma/web/activity_pub/mrf/simple_policy.ex b/lib/pleroma/web/activity_pub/mrf/simple_policy.ex
index 829ddea..829ddea 100755..100644
--- a/lib/pleroma/web/activity_pub/mrf/simple_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/simple_policy.ex
diff --git a/lib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex b/lib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex
index f66c379..fa6b595 100755..100644
--- a/lib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex
@@ -34,14 +34,17 @@ defmodule Pleroma.Web.ActivityPub.MRF.StealEmojiPolicy do
|> Path.basename()
|> Path.extname()
- file_path = Path.join(emoji_dir_path, shortcode <> (extension || ".png"))
+ extension = if extension == "", do: ".png", else: extension
+
+ shortcode = Path.basename(shortcode)
+ file_path = Path.join(emoji_dir_path, shortcode <> extension)
case File.write(file_path, response.body) do
:ok ->
shortcode
e ->
- Logger.warn("MRF.StealEmojiPolicy: Failed to write to #{file_path}: #{inspect(e)}")
+ Logger.warning("MRF.StealEmojiPolicy: Failed to write to #{file_path}: #{inspect(e)}")
nil
end
else
@@ -53,7 +56,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.StealEmojiPolicy do
end
else
e ->
- Logger.warn("MRF.StealEmojiPolicy: Failed to fetch #{url}: #{inspect(e)}")
+ Logger.warning("MRF.StealEmojiPolicy: Failed to fetch #{url}: #{inspect(e)}")
nil
end
end
@@ -76,6 +79,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.StealEmojiPolicy do
new_emojis =
foreign_emojis
|> Enum.reject(fn {shortcode, _url} -> shortcode in installed_emoji end)
+ |> Enum.reject(fn {shortcode, _url} -> String.contains?(shortcode, ["/", "\\"]) end)
|> Enum.filter(fn {shortcode, _url} ->
reject_emoji? =
[:mrf_steal_emoji, :rejected_shortcodes]
diff --git a/lib/pleroma/web/activity_pub/mrf/subchain_policy.ex b/lib/pleroma/web/activity_pub/mrf/subchain_policy.ex
index fdb9e51..fdb9e51 100755..100644
--- a/lib/pleroma/web/activity_pub/mrf/subchain_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/subchain_policy.ex
diff --git a/lib/pleroma/web/activity_pub/mrf/tag_policy.ex b/lib/pleroma/web/activity_pub/mrf/tag_policy.ex
index 73760ca..73760ca 100755..100644
--- a/lib/pleroma/web/activity_pub/mrf/tag_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/tag_policy.ex
diff --git a/lib/pleroma/web/activity_pub/mrf/user_allow_list_policy.ex b/lib/pleroma/web/activity_pub/mrf/user_allow_list_policy.ex
index e14047d..e14047d 100755..100644
--- a/lib/pleroma/web/activity_pub/mrf/user_allow_list_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/user_allow_list_policy.ex
diff --git a/lib/pleroma/web/activity_pub/mrf/utils.ex b/lib/pleroma/web/activity_pub/mrf/utils.ex
new file mode 100644
index 0000000..f2dc9ee
--- /dev/null
+++ b/lib/pleroma/web/activity_pub/mrf/utils.ex
@@ -0,0 +1,15 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.MRF.Utils do
+ @spec describe_regex_or_string(String.t() | Regex.t()) :: String.t()
+ def describe_regex_or_string(pattern) do
+ # This horror is needed to convert regex sigils to strings
+ if not is_binary(pattern) do
+ inspect(pattern)
+ else
+ pattern
+ end
+ end
+end
diff --git a/lib/pleroma/web/activity_pub/mrf/vocabulary_policy.ex b/lib/pleroma/web/activity_pub/mrf/vocabulary_policy.ex
index d9deff3..d9deff3 100755..100644
--- a/lib/pleroma/web/activity_pub/mrf/vocabulary_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/vocabulary_policy.ex
diff --git a/lib/pleroma/web/activity_pub/object_validator.ex b/lib/pleroma/web/activity_pub/object_validator.ex
index 5bcd6da..b3043b9 100755..100644
--- a/lib/pleroma/web/activity_pub/object_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validator.ex
@@ -21,7 +21,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
alias Pleroma.Web.ActivityPub.ObjectValidators.AnnounceValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.AnswerValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidator
- alias Pleroma.Web.ActivityPub.ObjectValidators.AudioVideoValidator
+ alias Pleroma.Web.ActivityPub.ObjectValidators.AudioImageVideoValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.BlockValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.ChatMessageValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.CreateChatMessageValidator
@@ -102,7 +102,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
%{"type" => "Create", "object" => %{"type" => objtype} = object} = create_activity,
meta
)
- when objtype in ~w[Question Answer Audio Video Event Article Note Page] do
+ when objtype in ~w[Question Answer Audio Video Image Event Article Note Page] do
with {:ok, object_data} <- cast_and_apply_and_stringify_with_history(object),
meta = Keyword.put(meta, :object_data, object_data),
{:ok, create_activity} <-
@@ -115,13 +115,14 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
end
def validate(%{"type" => type} = object, meta)
- when type in ~w[Event Question Audio Video Article Note Page] do
+ when type in ~w[Event Question Audio Video Image Article Note Page] do
validator =
case type do
"Event" -> EventValidator
"Question" -> QuestionValidator
- "Audio" -> AudioVideoValidator
- "Video" -> AudioVideoValidator
+ "Audio" -> AudioImageVideoValidator
+ "Video" -> AudioImageVideoValidator
+ "Image" -> AudioImageVideoValidator
"Article" -> ArticleNotePageValidator
"Note" -> ArticleNotePageValidator
"Page" -> ArticleNotePageValidator
@@ -172,6 +173,9 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
{:object_validation, e} ->
e
+
+ {:error, %Ecto.Changeset{} = e} ->
+ {:error, e}
end
end
@@ -233,8 +237,8 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
AnswerValidator.cast_and_apply(object)
end
- def cast_and_apply(%{"type" => type} = object) when type in ~w[Audio Video] do
- AudioVideoValidator.cast_and_apply(object)
+ def cast_and_apply(%{"type" => type} = object) when type in ~w[Audio Image Video] do
+ AudioImageVideoValidator.cast_and_apply(object)
end
def cast_and_apply(%{"type" => "Event"} = object) do
diff --git a/lib/pleroma/web/activity_pub/object_validator/validating.ex b/lib/pleroma/web/activity_pub/object_validator/validating.ex
index b695946..b695946 100755..100644
--- a/lib/pleroma/web/activity_pub/object_validator/validating.ex
+++ b/lib/pleroma/web/activity_pub/object_validator/validating.ex
diff --git a/lib/pleroma/web/activity_pub/object_validators/accept_reject_validator.ex b/lib/pleroma/web/activity_pub/object_validators/accept_reject_validator.ex
index d611da0..d611da0 100755..100644
--- a/lib/pleroma/web/activity_pub/object_validators/accept_reject_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/accept_reject_validator.ex
diff --git a/lib/pleroma/web/activity_pub/object_validators/add_remove_validator.ex b/lib/pleroma/web/activity_pub/object_validators/add_remove_validator.ex
index 5202db7..db32595 100755..100644
--- a/lib/pleroma/web/activity_pub/object_validators/add_remove_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/add_remove_validator.ex
@@ -73,6 +73,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AddRemoveValidator do
end
defp maybe_refetch_user(%User{ap_id: ap_id}) do
- Pleroma.Web.ActivityPub.Transmogrifier.upgrade_user_from_ap_id(ap_id)
+ # Maybe it could use User.get_or_fetch_by_ap_id to avoid refreshing too often
+ User.fetch_by_ap_id(ap_id)
end
end
diff --git a/lib/pleroma/web/activity_pub/object_validators/announce_validator.ex b/lib/pleroma/web/activity_pub/object_validators/announce_validator.ex
index c2c7ba1..d021858 100755..100644
--- a/lib/pleroma/web/activity_pub/object_validators/announce_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/announce_validator.ex
@@ -82,7 +82,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AnnounceValidator do
object when is_binary(object) <- get_field(cng, :object),
%User{} = actor <- User.get_cached_by_ap_id(actor),
%Object{} = object <- Object.get_cached_by_ap_id(object),
- false <- Visibility.is_public?(object) do
+ false <- Visibility.public?(object) do
same_actor = object.data["actor"] == actor.ap_id
recipients = get_field(cng, :to) ++ get_field(cng, :cc)
local_public = Utils.as_local_public()
diff --git a/lib/pleroma/web/activity_pub/object_validators/answer_validator.ex b/lib/pleroma/web/activity_pub/object_validators/answer_validator.ex
index 2d9b8ba..2d9b8ba 100755..100644
--- a/lib/pleroma/web/activity_pub/object_validators/answer_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/answer_validator.ex
diff --git a/lib/pleroma/web/activity_pub/object_validators/article_note_page_validator.ex b/lib/pleroma/web/activity_pub/object_validators/article_note_page_validator.ex
index 2670e3f..1b5b2e8 100755..100644
--- a/lib/pleroma/web/activity_pub/object_validators/article_note_page_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/article_note_page_validator.ex
@@ -84,6 +84,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidator do
|> fix_tag()
|> fix_replies()
|> fix_attachments()
+ |> CommonFixes.fix_quote_url()
|> Transmogrifier.fix_emoji()
|> Transmogrifier.fix_content_map()
end
diff --git a/lib/pleroma/web/activity_pub/object_validators/attachment_validator.ex b/lib/pleroma/web/activity_pub/object_validators/attachment_validator.ex
index 398020b..72975f3 100755..100644
--- a/lib/pleroma/web/activity_pub/object_validators/attachment_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/attachment_validator.ex
@@ -12,13 +12,13 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator do
@primary_key false
embedded_schema do
field(:id, :string)
- field(:type, :string)
+ field(:type, :string, default: "Link")
field(:mediaType, ObjectValidators.MIME, default: "application/octet-stream")
field(:name, :string)
field(:blurhash, :string)
embeds_many :url, UrlObjectValidator, primary_key: false do
- field(:type, :string)
+ field(:type, :string, default: "Link")
field(:href, ObjectValidators.Uri)
field(:mediaType, ObjectValidators.MIME, default: "application/octet-stream")
field(:width, :integer)
diff --git a/lib/pleroma/web/activity_pub/object_validators/audio_video_validator.ex b/lib/pleroma/web/activity_pub/object_validators/audio_image_video_validator.ex
index 671a7ef..65ac6bb 100755..100644
--- a/lib/pleroma/web/activity_pub/object_validators/audio_video_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/audio_image_video_validator.ex
@@ -2,7 +2,7 @@
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
-defmodule Pleroma.Web.ActivityPub.ObjectValidators.AudioVideoValidator do
+defmodule Pleroma.Web.ActivityPub.ObjectValidators.AudioImageVideoValidator do
use Ecto.Schema
alias Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes
@@ -55,9 +55,14 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AudioVideoValidator do
url
|> Enum.concat(mpeg_url["tag"] || [])
|> Enum.find(fn
- %{"mediaType" => mime_type} -> String.starts_with?(mime_type, ["video/", "audio/"])
- %{"mimeType" => mime_type} -> String.starts_with?(mime_type, ["video/", "audio/"])
- _ -> false
+ %{"mediaType" => mime_type} ->
+ String.starts_with?(mime_type, ["video/", "audio/", "image/"])
+
+ %{"mimeType" => mime_type} ->
+ String.starts_with?(mime_type, ["video/", "audio/", "image/"])
+
+ _ ->
+ false
end)
end
@@ -94,6 +99,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AudioVideoValidator do
data
|> CommonFixes.fix_actor()
|> CommonFixes.fix_object_defaults()
+ |> CommonFixes.fix_quote_url()
|> Transmogrifier.fix_emoji()
|> fix_url()
|> fix_content()
@@ -110,7 +116,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AudioVideoValidator do
defp validate_data(data_cng) do
data_cng
- |> validate_inclusion(:type, ["Audio", "Video"])
+ |> validate_inclusion(:type, ~w[Audio Image Video])
|> validate_required([:id, :actor, :attributedTo, :type, :context])
|> CommonValidations.validate_any_presence([:cc, :to])
|> CommonValidations.validate_fields_match([:actor, :attributedTo])
diff --git a/lib/pleroma/web/activity_pub/object_validators/block_validator.ex b/lib/pleroma/web/activity_pub/object_validators/block_validator.ex
index 0de87a2..0de87a2 100755..100644
--- a/lib/pleroma/web/activity_pub/object_validators/block_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/block_validator.ex
diff --git a/lib/pleroma/web/activity_pub/object_validators/chat_message_validator.ex b/lib/pleroma/web/activity_pub/object_validators/chat_message_validator.ex
index efae48c..09e25be 100755..100644
--- a/lib/pleroma/web/activity_pub/object_validators/chat_message_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/chat_message_validator.ex
@@ -57,6 +57,11 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ChatMessageValidator do
|> Map.put("attachment", attachment)
end
+ def fix_attachment(%{"attachment" => attachment} = data) when attachment == [] do
+ data
+ |> Map.drop(["attachment"])
+ end
+
def fix_attachment(data), do: data
def changeset(struct, data) do
diff --git a/lib/pleroma/web/activity_pub/object_validators/common_fields.ex b/lib/pleroma/web/activity_pub/object_validators/common_fields.ex
index 7b60c13..1a5d026 100755..100644
--- a/lib/pleroma/web/activity_pub/object_validators/common_fields.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/common_fields.ex
@@ -27,7 +27,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonFields do
end
end
- # All objects except Answer and CHatMessage
+ # All objects except Answer and ChatMessage
defmacro object_fields do
quote bind_quoted: binding() do
field(:content, :string)
@@ -57,8 +57,10 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonFields do
field(:replies_count, :integer, default: 0)
field(:like_count, :integer, default: 0)
field(:announcement_count, :integer, default: 0)
+ field(:quotes_count, :integer, default: 0)
field(:inReplyTo, ObjectValidators.ObjectID)
- field(:url, ObjectValidators.Uri)
+ field(:quoteUrl, ObjectValidators.ObjectID)
+ field(:url, ObjectValidators.BareUri)
field(:likes, {:array, ObjectValidators.ObjectID}, default: [])
field(:announcements, {:array, ObjectValidators.ObjectID}, default: [])
diff --git a/lib/pleroma/web/activity_pub/object_validators/common_fixes.ex b/lib/pleroma/web/activity_pub/object_validators/common_fixes.ex
index add46d5..4699029 100755..100644
--- a/lib/pleroma/web/activity_pub/object_validators/common_fixes.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/common_fixes.ex
@@ -4,12 +4,15 @@
defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes do
alias Pleroma.EctoType.ActivityPub.ObjectValidators
+ alias Pleroma.Maps
alias Pleroma.Object
alias Pleroma.Object.Containment
alias Pleroma.User
alias Pleroma.Web.ActivityPub.Transmogrifier
alias Pleroma.Web.ActivityPub.Utils
+ require Pleroma.Constants
+
def cast_and_filter_recipients(message, field, follower_collection, field_fallback \\ []) do
{:ok, data} = ObjectValidators.Recipients.cast(message[field] || field_fallback)
@@ -22,6 +25,8 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes do
end
def fix_object_defaults(data) do
+ data = Maps.filter_empty_values(data)
+
context =
Utils.maybe_create_context(
data["context"] || data["conversation"] || data["inReplyTo"] || data["id"]
@@ -76,4 +81,48 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes do
Map.put(data, "to", to)
end
+
+ def fix_quote_url(%{"quoteUrl" => _quote_url} = data), do: data
+
+ # Fedibird
+ # https://github.com/fedibird/mastodon/commit/dbd7ae6cf58a92ec67c512296b4daaea0d01e6ac
+ def fix_quote_url(%{"quoteUri" => quote_url} = data) do
+ Map.put(data, "quoteUrl", quote_url)
+ end
+
+ # Old Fedibird (bug)
+ # https://github.com/fedibird/mastodon/issues/9
+ def fix_quote_url(%{"quoteURL" => quote_url} = data) do
+ Map.put(data, "quoteUrl", quote_url)
+ end
+
+ # Misskey fallback
+ def fix_quote_url(%{"_misskey_quote" => quote_url} = data) do
+ Map.put(data, "quoteUrl", quote_url)
+ end
+
+ def fix_quote_url(%{"tag" => [_ | _] = tags} = data) do
+ tag = Enum.find(tags, &object_link_tag?/1)
+
+ if not is_nil(tag) do
+ data
+ |> Map.put("quoteUrl", tag["href"])
+ else
+ data
+ end
+ end
+
+ def fix_quote_url(data), do: data
+
+ # https://codeberg.org/fediverse/fep/src/branch/main/fep/e232/fep-e232.md
+ def object_link_tag?(%{
+ "type" => "Link",
+ "mediaType" => media_type,
+ "href" => href
+ })
+ when media_type in Pleroma.Constants.activity_json_mime_types() and is_binary(href) do
+ true
+ end
+
+ def object_link_tag?(_), do: false
end
diff --git a/lib/pleroma/web/activity_pub/object_validators/common_validations.ex b/lib/pleroma/web/activity_pub/object_validators/common_validations.ex
index 1c5b1a0..1c5b1a0 100755..100644
--- a/lib/pleroma/web/activity_pub/object_validators/common_validations.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/common_validations.ex
diff --git a/lib/pleroma/web/activity_pub/object_validators/create_chat_message_validator.ex b/lib/pleroma/web/activity_pub/object_validators/create_chat_message_validator.ex
index b299647..b299647 100755..100644
--- a/lib/pleroma/web/activity_pub/object_validators/create_chat_message_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/create_chat_message_validator.ex
diff --git a/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex b/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex
index 2395abf..2395abf 100755..100644
--- a/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/create_generic_validator.ex
diff --git a/lib/pleroma/web/activity_pub/object_validators/delete_validator.ex b/lib/pleroma/web/activity_pub/object_validators/delete_validator.ex
index 4d8502a..4d8502a 100755..100644
--- a/lib/pleroma/web/activity_pub/object_validators/delete_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/delete_validator.ex
diff --git a/lib/pleroma/web/activity_pub/object_validators/emoji_react_validator.ex b/lib/pleroma/web/activity_pub/object_validators/emoji_react_validator.ex
index 0858281..65ba047 100755..100644
--- a/lib/pleroma/web/activity_pub/object_validators/emoji_react_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/emoji_react_validator.ex
@@ -5,8 +5,10 @@
defmodule Pleroma.Web.ActivityPub.ObjectValidators.EmojiReactValidator do
use Ecto.Schema
+ alias Pleroma.Emoji
alias Pleroma.Object
alias Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes
+ alias Pleroma.Web.ActivityPub.ObjectValidators.TagValidator
import Ecto.Changeset
import Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations
@@ -19,6 +21,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.EmojiReactValidator do
import Elixir.Pleroma.Web.ActivityPub.ObjectValidators.CommonFields
message_fields()
activity_fields()
+ embeds_many(:tag, TagValidator)
end
end
@@ -43,7 +46,8 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.EmojiReactValidator do
def changeset(struct, data) do
struct
- |> cast(data, __schema__(:fields))
+ |> cast(data, __schema__(:fields) -- [:tag])
+ |> cast_embed(:tag)
end
defp fix(data) do
@@ -53,12 +57,16 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.EmojiReactValidator do
|> CommonFixes.fix_actor()
|> CommonFixes.fix_activity_addressing()
- with %Object{} = object <- Object.normalize(data["object"]) do
- data
- |> CommonFixes.fix_activity_context(object)
- |> CommonFixes.fix_object_action_recipients(object)
- else
- _ -> data
+ data = Map.put_new(data, "tag", [])
+
+ case Object.normalize(data["object"]) do
+ %Object{} = object ->
+ data
+ |> CommonFixes.fix_activity_context(object)
+ |> CommonFixes.fix_object_action_recipients(object)
+
+ _ ->
+ data
end
end
@@ -66,10 +74,10 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.EmojiReactValidator do
new_emoji = Pleroma.Emoji.fully_qualify_emoji(emoji)
cond do
- Pleroma.Emoji.is_unicode_emoji?(emoji) ->
+ Pleroma.Emoji.unicode?(emoji) ->
data
- Pleroma.Emoji.is_unicode_emoji?(new_emoji) ->
+ Pleroma.Emoji.unicode?(new_emoji) ->
data |> Map.put("content", new_emoji)
true ->
@@ -82,11 +90,31 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.EmojiReactValidator do
defp validate_emoji(cng) do
content = get_field(cng, :content)
- if Pleroma.Emoji.is_unicode_emoji?(content) do
+ if Emoji.unicode?(content) || Emoji.custom?(content) do
cng
else
cng
- |> add_error(:content, "must be a single character emoji")
+ |> add_error(:content, "is not a valid emoji")
+ end
+ end
+
+ defp maybe_validate_tag_presence(cng) do
+ content = get_field(cng, :content)
+
+ if Emoji.unicode?(content) do
+ cng
+ else
+ tag = get_field(cng, :tag)
+ emoji_name = Emoji.maybe_strip_name(content)
+
+ case tag do
+ [%{name: ^emoji_name, type: "Emoji", icon: %{url: _}}] ->
+ cng
+
+ _ ->
+ cng
+ |> add_error(:tag, "does not contain an Emoji tag")
+ end
end
end
@@ -97,5 +125,6 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.EmojiReactValidator do
|> validate_actor_presence()
|> validate_object_presence()
|> validate_emoji()
+ |> maybe_validate_tag_presence()
end
end
diff --git a/lib/pleroma/web/activity_pub/object_validators/event_validator.ex b/lib/pleroma/web/activity_pub/object_validators/event_validator.ex
index ab204f6..ab204f6 100755..100644
--- a/lib/pleroma/web/activity_pub/object_validators/event_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/event_validator.ex
diff --git a/lib/pleroma/web/activity_pub/object_validators/follow_validator.ex b/lib/pleroma/web/activity_pub/object_validators/follow_validator.ex
index b3ca5b6..b3ca5b6 100755..100644
--- a/lib/pleroma/web/activity_pub/object_validators/follow_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/follow_validator.ex
diff --git a/lib/pleroma/web/activity_pub/object_validators/like_validator.ex b/lib/pleroma/web/activity_pub/object_validators/like_validator.ex
index bdc4d71..bdc4d71 100755..100644
--- a/lib/pleroma/web/activity_pub/object_validators/like_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/like_validator.ex
diff --git a/lib/pleroma/web/activity_pub/object_validators/question_options_validator.ex b/lib/pleroma/web/activity_pub/object_validators/question_options_validator.ex
index 541945f..8d7f7b9 100755..100644
--- a/lib/pleroma/web/activity_pub/object_validators/question_options_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/question_options_validator.ex
@@ -14,10 +14,10 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.QuestionOptionsValidator do
embeds_one :replies, Replies, primary_key: false do
field(:totalItems, :integer)
- field(:type, :string)
+ field(:type, :string, default: "Collection")
end
- field(:type, :string)
+ field(:type, :string, default: "Note")
end
def changeset(struct, data) do
diff --git a/lib/pleroma/web/activity_pub/object_validators/question_validator.ex b/lib/pleroma/web/activity_pub/object_validators/question_validator.ex
index ce33051..7f9d4d6 100755..100644
--- a/lib/pleroma/web/activity_pub/object_validators/question_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/question_validator.ex
@@ -29,6 +29,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.QuestionValidator do
field(:closed, ObjectValidators.DateTime)
field(:voters, {:array, ObjectValidators.ObjectID}, default: [])
+ field(:nonAnonymous, :boolean)
embeds_many(:anyOf, QuestionOptionsValidator)
embeds_many(:oneOf, QuestionOptionsValidator)
end
@@ -62,6 +63,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.QuestionValidator do
data
|> CommonFixes.fix_actor()
|> CommonFixes.fix_object_defaults()
+ |> CommonFixes.fix_quote_url()
|> Transmogrifier.fix_emoji()
|> fix_closed()
end
diff --git a/lib/pleroma/web/activity_pub/object_validators/tag_validator.ex b/lib/pleroma/web/activity_pub/object_validators/tag_validator.ex
index 9f15f19..47cf7b4 100755..100644
--- a/lib/pleroma/web/activity_pub/object_validators/tag_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/tag_validator.ex
@@ -9,15 +9,20 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.TagValidator do
import Ecto.Changeset
+ require Pleroma.Constants
+
@primary_key false
embedded_schema do
# Common
field(:type, :string)
field(:name, :string)
- # Mention, Hashtag
+ # Mention, Hashtag, Link
field(:href, ObjectValidators.Uri)
+ # Link
+ field(:mediaType, :string)
+
# Emoji
embeds_one :icon, IconObjectValidator, primary_key: false do
field(:type, :string)
@@ -68,6 +73,19 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.TagValidator do
|> validate_required([:type, :name, :icon])
end
+ def changeset(struct, %{"type" => "Link"} = data) do
+ struct
+ |> cast(data, [:type, :name, :mediaType, :href])
+ |> validate_inclusion(:mediaType, Pleroma.Constants.activity_json_mime_types())
+ |> validate_required([:type, :href, :mediaType])
+ end
+
+ def changeset(struct, %{"type" => _} = data) do
+ struct
+ |> cast(data, [])
+ |> Map.put(:action, :ignore)
+ end
+
def icon_changeset(struct, data) do
struct
|> cast(data, [:type, :url])
diff --git a/lib/pleroma/web/activity_pub/object_validators/undo_validator.ex b/lib/pleroma/web/activity_pub/object_validators/undo_validator.ex
index f030514..f030514 100755..100644
--- a/lib/pleroma/web/activity_pub/object_validators/undo_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/undo_validator.ex
diff --git a/lib/pleroma/web/activity_pub/object_validators/update_validator.ex b/lib/pleroma/web/activity_pub/object_validators/update_validator.ex
index 1e940a4..1e940a4 100755..100644
--- a/lib/pleroma/web/activity_pub/object_validators/update_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/update_validator.ex
diff --git a/lib/pleroma/web/activity_pub/pipeline.ex b/lib/pleroma/web/activity_pub/pipeline.ex
index ca8653a..40184bd 100755..100644
--- a/lib/pleroma/web/activity_pub/pipeline.ex
+++ b/lib/pleroma/web/activity_pub/pipeline.ex
@@ -62,7 +62,7 @@ defmodule Pleroma.Web.ActivityPub.Pipeline do
with {:ok, local} <- Keyword.fetch(meta, :local) do
do_not_federate = meta[:do_not_federate] || !config().get([:instance, :federating])
- if !do_not_federate and local and not Visibility.is_local_public?(activity) do
+ if !do_not_federate and local and not Visibility.local_public?(activity) do
activity =
if object = Keyword.get(meta, :object_data) do
%{activity | data: Map.put(activity.data, "object", object)}
diff --git a/lib/pleroma/web/activity_pub/publisher.ex b/lib/pleroma/web/activity_pub/publisher.ex
index 6c1ba76..a42b484 100755..100644
--- a/lib/pleroma/web/activity_pub/publisher.ex
+++ b/lib/pleroma/web/activity_pub/publisher.ex
@@ -13,13 +13,12 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
alias Pleroma.User
alias Pleroma.Web.ActivityPub.Relay
alias Pleroma.Web.ActivityPub.Transmogrifier
+ alias Pleroma.Workers.PublisherWorker
require Pleroma.Constants
import Pleroma.Web.ActivityPub.Visibility
- @behaviour Pleroma.Web.Federator.Publisher
-
require Logger
@moduledoc """
@@ -27,9 +26,47 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
"""
@doc """
+ Enqueue publishing a single activity.
+ """
+ @spec enqueue_one(map(), Keyword.t()) :: {:ok, %Oban.Job{}}
+ def enqueue_one(%{} = params, worker_args \\ []) do
+ PublisherWorker.enqueue(
+ "publish_one",
+ %{"params" => params},
+ worker_args
+ )
+ end
+
+ @doc """
+ Gathers a set of remote users given an IR envelope.
+ """
+ def remote_users(%User{id: user_id}, %{data: %{"to" => to} = data}) do
+ cc = Map.get(data, "cc", [])
+
+ bcc =
+ data
+ |> Map.get("bcc", [])
+ |> Enum.reduce([], fn ap_id, bcc ->
+ case Pleroma.List.get_by_ap_id(ap_id) do
+ %Pleroma.List{user_id: ^user_id} = list ->
+ {:ok, following} = Pleroma.List.get_following(list)
+ bcc ++ Enum.map(following, & &1.ap_id)
+
+ _ ->
+ bcc
+ end
+ end)
+
+ [to, cc, bcc]
+ |> Enum.concat()
+ |> Enum.map(&User.get_cached_by_ap_id/1)
+ |> Enum.filter(fn user -> user && !user.local end)
+ end
+
+ @doc """
Determine if an activity can be represented by running it through Transmogrifier.
"""
- def is_representable?(%Activity{} = activity) do
+ def representable?(%Activity{} = activity) do
with {:ok, _data} <- Transmogrifier.prepare_outgoing(activity.data) do
true
else
@@ -80,9 +117,27 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
result
else
- {_post_result, response} ->
+ {_post_result, %{status: code} = response} = e ->
+ unless params[:unreachable_since], do: Instances.set_unreachable(inbox)
+ Logger.metadata(activity: id, inbox: inbox, status: code)
+ Logger.error("Publisher failed to inbox #{inbox} with status #{code}")
+
+ case response do
+ %{status: 403} -> {:discard, :forbidden}
+ %{status: 404} -> {:discard, :not_found}
+ %{status: 410} -> {:discard, :not_found}
+ _ -> {:error, e}
+ end
+
+ {:error, :pool_full} ->
+ Logger.debug("Publisher snoozing worker job due to full connection pool")
+ {:snooze, 30}
+
+ e ->
unless params[:unreachable_since], do: Instances.set_unreachable(inbox)
- {:error, response}
+ Logger.metadata(activity: id, inbox: inbox)
+ Logger.error("Publisher failed to inbox #{inbox} #{inspect(e)}")
+ {:error, e}
end
end
@@ -103,22 +158,21 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
end
end
- defp should_federate?(inbox, public) do
- if public do
- true
- else
- %{host: host} = URI.parse(inbox)
+ def should_federate?(nil, _), do: false
+ def should_federate?(_, true), do: true
- quarantined_instances =
- Config.get([:instance, :quarantined_instances], [])
- |> Pleroma.Web.ActivityPub.MRF.instance_list_from_tuples()
- |> Pleroma.Web.ActivityPub.MRF.subdomains_regex()
+ def should_federate?(inbox, _) do
+ %{host: host} = URI.parse(inbox)
- !Pleroma.Web.ActivityPub.MRF.subdomain_match?(quarantined_instances, host)
- end
+ quarantined_instances =
+ Config.get([:instance, :quarantined_instances], [])
+ |> Pleroma.Web.ActivityPub.MRF.instance_list_from_tuples()
+ |> Pleroma.Web.ActivityPub.MRF.subdomains_regex()
+
+ !Pleroma.Web.ActivityPub.MRF.subdomain_match?(quarantined_instances, host)
end
- @spec recipients(User.t(), Activity.t()) :: list(User.t()) | []
+ @spec recipients(User.t(), Activity.t()) :: [[User.t()]]
defp recipients(actor, activity) do
followers =
if actor.follower_address in activity.recipients do
@@ -138,7 +192,10 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
[]
end
- Pleroma.Web.Federator.Publisher.remote_users(actor, activity) ++ followers ++ fetchers
+ mentioned = remote_users(actor, activity)
+ non_mentioned = (followers ++ fetchers) -- mentioned
+
+ [mentioned, non_mentioned]
end
defp get_cc_ap_ids(ap_id, recipients) do
@@ -192,45 +249,52 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
def publish(%User{} = actor, %{data: %{"bcc" => bcc}} = activity)
when is_list(bcc) and bcc != [] do
- public = is_public?(activity)
+ public = public?(activity)
{:ok, data} = Transmogrifier.prepare_outgoing(activity.data)
- recipients = recipients(actor, activity)
+ [priority_recipients, recipients] = recipients(actor, activity)
inboxes =
- recipients
- |> Enum.filter(&User.ap_enabled?/1)
- |> Enum.map(fn actor -> actor.inbox end)
- |> Enum.filter(fn inbox -> should_federate?(inbox, public) end)
- |> Instances.filter_reachable()
+ [priority_recipients, recipients]
+ |> Enum.map(fn recipients ->
+ recipients
+ |> Enum.map(fn %User{} = user ->
+ determine_inbox(activity, user)
+ end)
+ |> Enum.uniq()
+ |> Enum.filter(fn inbox -> should_federate?(inbox, public) end)
+ |> Instances.filter_reachable()
+ end)
Repo.checkout(fn ->
- Enum.each(inboxes, fn {inbox, unreachable_since} ->
- %User{ap_id: ap_id} = Enum.find(recipients, fn actor -> actor.inbox == inbox end)
-
- # Get all the recipients on the same host and add them to cc. Otherwise, a remote
- # instance would only accept a first message for the first recipient and ignore the rest.
- cc = get_cc_ap_ids(ap_id, recipients)
-
- json =
- data
- |> Map.put("cc", cc)
- |> Jason.encode!()
-
- Pleroma.Web.Federator.Publisher.enqueue_one(__MODULE__, %{
- inbox: inbox,
- json: json,
- actor_id: actor.id,
- id: activity.data["id"],
- unreachable_since: unreachable_since
- })
+ Enum.each(inboxes, fn inboxes ->
+ Enum.each(inboxes, fn {inbox, unreachable_since} ->
+ %User{ap_id: ap_id} = Enum.find(recipients, fn actor -> actor.inbox == inbox end)
+
+ # Get all the recipients on the same host and add them to cc. Otherwise, a remote
+ # instance would only accept a first message for the first recipient and ignore the rest.
+ cc = get_cc_ap_ids(ap_id, recipients)
+
+ json =
+ data
+ |> Map.put("cc", cc)
+ |> Jason.encode!()
+
+ __MODULE__.enqueue_one(%{
+ inbox: inbox,
+ json: json,
+ actor_id: actor.id,
+ id: activity.data["id"],
+ unreachable_since: unreachable_since
+ })
+ end)
end)
end)
end
# Publishes an activity to all relevant peers.
def publish(%User{} = actor, %Activity{} = activity) do
- public = is_public?(activity)
+ public = public?(activity)
if public && Config.get([:instance, :allow_relay]) do
Logger.debug(fn -> "Relaying #{activity.data["id"]} out" end)
@@ -240,26 +304,38 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
{:ok, data} = Transmogrifier.prepare_outgoing(activity.data)
json = Jason.encode!(data)
- recipients(actor, activity)
- |> Enum.filter(fn user -> User.ap_enabled?(user) end)
- |> Enum.map(fn %User{} = user ->
- determine_inbox(activity, user)
- end)
- |> Enum.uniq()
- |> Enum.filter(fn inbox -> should_federate?(inbox, public) end)
- |> Instances.filter_reachable()
- |> Enum.each(fn {inbox, unreachable_since} ->
- Pleroma.Web.Federator.Publisher.enqueue_one(
- __MODULE__,
- %{
- inbox: inbox,
- json: json,
- actor_id: actor.id,
- id: activity.data["id"],
- unreachable_since: unreachable_since
- }
- )
+ [priority_inboxes, inboxes] =
+ recipients(actor, activity)
+ |> Enum.map(fn recipients ->
+ recipients
+ |> Enum.map(fn %User{} = user ->
+ determine_inbox(activity, user)
+ end)
+ |> Enum.uniq()
+ |> Enum.filter(fn inbox -> should_federate?(inbox, public) end)
+ end)
+
+ inboxes = inboxes -- priority_inboxes
+
+ [{priority_inboxes, 0}, {inboxes, 1}]
+ |> Enum.each(fn {inboxes, priority} ->
+ inboxes
+ |> Instances.filter_reachable()
+ |> Enum.each(fn {inbox, unreachable_since} ->
+ __MODULE__.enqueue_one(
+ %{
+ inbox: inbox,
+ json: json,
+ actor_id: actor.id,
+ id: activity.data["id"],
+ unreachable_since: unreachable_since
+ },
+ priority: priority
+ )
+ end)
end)
+
+ :ok
end
def gather_webfinger_links(%User{} = user) do
diff --git a/lib/pleroma/web/activity_pub/relay.ex b/lib/pleroma/web/activity_pub/relay.ex
index 2010351..91a647f 100755..100644
--- a/lib/pleroma/web/activity_pub/relay.ex
+++ b/lib/pleroma/web/activity_pub/relay.ex
@@ -58,7 +58,7 @@ defmodule Pleroma.Web.ActivityPub.Relay do
@spec publish(any()) :: {:ok, Activity.t()} | {:error, any()}
def publish(%Activity{data: %{"type" => "Create"}} = activity) do
with %User{} = user <- get_actor(),
- true <- Visibility.is_public?(activity) do
+ true <- Visibility.public?(activity) do
CommonAPI.repeat(activity.id, user)
else
error -> format_error(error)
diff --git a/lib/pleroma/web/activity_pub/side_effects.ex b/lib/pleroma/web/activity_pub/side_effects.ex
index fc5dec3..7421b8e 100755..100644
--- a/lib/pleroma/web/activity_pub/side_effects.ex
+++ b/lib/pleroma/web/activity_pub/side_effects.ex
@@ -197,6 +197,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
# - Increase replies count
# - Set up ActivityExpiration
# - Set up notifications
+ # - Index incoming posts for search (if needed)
@impl true
def handle(%{data: %{"type" => "Create"}} = activity, meta) do
with {:ok, object, meta} <- handle_object_creation(meta[:object_data], activity, meta),
@@ -209,6 +210,10 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
Object.increase_replies_count(in_reply_to)
end
+ if quote_url = object.data["quoteUrl"] do
+ Object.increase_quotes_count(quote_url)
+ end
+
reply_depth = (meta[:depth] || 0) + 1
# FIXME: Force inReplyTo to replies
@@ -222,9 +227,11 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
end
end
- ConcurrentLimiter.limit(Pleroma.Web.RichMedia.Helpers, fn ->
- Task.start(fn -> Pleroma.Web.RichMedia.Helpers.fetch_data_for_activity(activity) end)
- end)
+ Pleroma.Web.RichMedia.Card.get_by_activity(activity)
+
+ Pleroma.Search.add_to_index(Map.put(activity, :object, object))
+
+ Utils.maybe_handle_group_posts(activity)
meta =
meta
@@ -249,7 +256,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
Utils.add_announce_to_object(object, announced_object)
- if !User.is_internal_user?(user) do
+ if !User.internal?(user) do
Notification.create_notifications(object)
ap_streamer().stream_out(object)
@@ -285,6 +292,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
# - Reduce the user note count
# - Reduce the reply count
# - Stream out the activity
+ # - Removes posts from search index (if needed)
@impl true
def handle(%{data: %{"type" => "Delete", "object" => deleted_object}} = object, meta) do
deleted_object =
@@ -294,9 +302,9 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
result =
case deleted_object do
%Object{} ->
- with {:ok, deleted_object, _activity} <- Object.delete(deleted_object),
+ with {_, {:ok, deleted_object, _activity}} <- {:object, Object.delete(deleted_object)},
{_, actor} when is_binary(actor) <- {:actor, deleted_object.data["actor"]},
- %User{} = user <- User.get_cached_by_ap_id(actor) do
+ {_, %User{} = user} <- {:user, User.get_cached_by_ap_id(actor)} do
User.remove_pinned_object_id(user, deleted_object.data["id"])
{:ok, user} = ActivityPub.decrease_note_count_if_public(user, deleted_object)
@@ -305,6 +313,10 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
Object.decrease_replies_count(in_reply_to)
end
+ if quote_url = deleted_object.data["quoteUrl"] do
+ Object.decrease_quotes_count(quote_url)
+ end
+
MessageReference.delete_for_object(deleted_object)
ap_streamer().stream_out(object)
@@ -314,6 +326,17 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
{:actor, _} ->
@logger.error("The object doesn't have an actor: #{inspect(deleted_object)}")
:no_object_actor
+
+ {:user, _} ->
+ @logger.error(
+ "The object's actor could not be resolved to a user: #{inspect(deleted_object)}"
+ )
+
+ :no_object_user
+
+ {:object, _} ->
+ @logger.error("The object could not be deleted: #{inspect(deleted_object)}")
+ {:error, object}
end
%User{} ->
@@ -323,6 +346,11 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
end
if result == :ok do
+ # Only remove from index when deleting actual objects, not users or anything else
+ with %Pleroma.Object{} <- deleted_object do
+ Pleroma.Search.remove_from_index(deleted_object)
+ end
+
{:ok, object, meta}
else
{:error, result}
@@ -496,7 +524,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
end
def handle_object_creation(%{"type" => objtype} = object, _activity, meta)
- when objtype in ~w[Audio Video Event Article Note Page] do
+ when objtype in ~w[Audio Video Image Event Article Note Page] do
with {:ok, object, meta} <- Pipeline.common_pipeline(object, meta) do
{:ok, object, meta}
end
@@ -550,7 +578,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
def handle_undoing(object), do: {:error, ["don't know how to handle", object]}
- @spec delete_object(Object.t()) :: :ok | {:error, Ecto.Changeset.t()}
+ @spec delete_object(Activity.t()) :: :ok | {:error, Ecto.Changeset.t()}
defp delete_object(object) do
with {:ok, _} <- Repo.delete(object), do: :ok
end
diff --git a/lib/pleroma/web/activity_pub/side_effects/handling.ex b/lib/pleroma/web/activity_pub/side_effects/handling.ex
index eb012f5..4751bb4 100755..100644
--- a/lib/pleroma/web/activity_pub/side_effects/handling.ex
+++ b/lib/pleroma/web/activity_pub/side_effects/handling.ex
@@ -4,5 +4,5 @@
defmodule Pleroma.Web.ActivityPub.SideEffects.Handling do
@callback handle(map(), keyword()) :: {:ok, map(), keyword()} | {:error, any()}
- @callback handle_after_transaction(map()) :: map()
+ @callback handle_after_transaction(keyword()) :: keyword()
end
diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex
index e4c04da..edfe73a 100755..100644
--- a/lib/pleroma/web/activity_pub/transmogrifier.ex
+++ b/lib/pleroma/web/activity_pub/transmogrifier.ex
@@ -20,11 +20,9 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
alias Pleroma.Web.ActivityPub.Utils
alias Pleroma.Web.ActivityPub.Visibility
alias Pleroma.Web.Federator
- alias Pleroma.Workers.TransmogrifierWorker
import Ecto.Query
- require Logger
require Pleroma.Constants
@doc """
@@ -156,8 +154,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|> Map.put("context", replied_object.data["context"] || object["conversation"])
|> Map.drop(["conversation", "inReplyToAtomUri"])
else
- e ->
- Logger.warn("Couldn't fetch #{inspect(in_reply_to_id)}, error: #{inspect(e)}")
+ _ ->
object
end
else
@@ -167,6 +164,26 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
def fix_in_reply_to(object, _options), do: object
+ def fix_quote_url_and_maybe_fetch(object, options \\ []) do
+ quote_url =
+ case Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes.fix_quote_url(object) do
+ %{"quoteUrl" => quote_url} -> quote_url
+ _ -> nil
+ end
+
+ with {:quoting?, true} <- {:quoting?, not is_nil(quote_url)},
+ {:ok, quoted_object} <- get_obj_helper(quote_url, options),
+ %Activity{} <- Activity.get_create_by_object_ap_id(quoted_object.data["id"]) do
+ Map.put(object, "quoteUrl", quoted_object.data["id"])
+ else
+ {:quoting?, _} ->
+ object
+
+ _ ->
+ object
+ end
+ end
+
defp prepare_in_reply_to(in_reply_to) do
cond do
is_bitstring(in_reply_to) ->
@@ -447,7 +464,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
%{"type" => "Create", "object" => %{"type" => objtype, "id" => obj_id}} = data,
options
)
- when objtype in ~w{Question Answer ChatMessage Audio Video Event Article Note Page} do
+ when objtype in ~w{Question Answer ChatMessage Audio Video Event Article Note Page Image} do
fetch_options = Keyword.put(options, :depth, (options[:depth] || 0) + 1)
object =
@@ -455,6 +472,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|> strip_internal_fields()
|> fix_type(fetch_options)
|> fix_in_reply_to(fetch_options)
+ |> fix_quote_url_and_maybe_fetch(fetch_options)
data = Map.put(data, "object", object)
options = Keyword.put(options, :local, false)
@@ -630,6 +648,16 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
def set_reply_to_uri(obj), do: obj
@doc """
+ Fedibird compatibility
+ https://github.com/fedibird/mastodon/commit/dbd7ae6cf58a92ec67c512296b4daaea0d01e6ac
+ """
+ def set_quote_url(%{"quoteUrl" => quote_url} = object) when is_binary(quote_url) do
+ Map.put(object, "quoteUri", quote_url)
+ end
+
+ def set_quote_url(obj), do: obj
+
+ @doc """
Serialized Mastodon-compatible `replies` collection containing _self-replies_.
Based on Mastodon's ActivityPub::NoteSerializer#replies.
"""
@@ -683,6 +711,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|> prepare_attachments
|> set_conversation
|> set_reply_to_uri
+ |> set_quote_url
|> set_replies
|> strip_internal_fields
|> strip_internal_tags
@@ -750,7 +779,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|> Object.normalize(fetch: false)
data =
- if Visibility.is_private?(object) && object.data["actor"] == ap_id do
+ if Visibility.private?(object) && object.data["actor"] == ap_id do
data |> Map.put("object", object |> Map.get(:data) |> prepare_object)
else
data |> maybe_fix_object_url
@@ -820,8 +849,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
relative_object do
Map.put(data, "object", external_url)
else
- {:fetch, e} ->
- Logger.error("Couldn't fetch #{object} #{inspect(e)}")
+ {:fetch, _} ->
data
_ ->
@@ -946,47 +974,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
defp strip_internal_tags(object), do: object
- def perform(:user_upgrade, user) do
- # we pass a fake user so that the followers collection is stripped away
- old_follower_address = User.ap_followers(%User{nickname: user.nickname})
-
- from(
- a in Activity,
- where: ^old_follower_address in a.recipients,
- update: [
- set: [
- recipients:
- fragment(
- "array_replace(?,?,?)",
- a.recipients,
- ^old_follower_address,
- ^user.follower_address
- )
- ]
- ]
- )
- |> Repo.update_all([])
- end
-
- def upgrade_user_from_ap_id(ap_id) do
- with %User{local: false} = user <- User.get_cached_by_ap_id(ap_id),
- {:ok, data} <- ActivityPub.fetch_and_prepare_user_from_ap_id(ap_id),
- {:ok, user} <- update_user(user, data) do
- {:ok, _pid} = Task.start(fn -> ActivityPub.pinned_fetch_task(user) end)
- TransmogrifierWorker.enqueue("user_upgrade", %{"user_id" => user.id})
- {:ok, user}
- else
- %User{} = user -> {:ok, user}
- e -> e
- end
- end
-
- defp update_user(user, data) do
- user
- |> User.remote_user_changeset(data)
- |> User.update_and_set_cache()
- end
-
def maybe_fix_user_url(%{"url" => url} = data) when is_map(url) do
Map.put(data, "url", url["href"])
end
diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex
index b898d6f..52cb64f 100755..100644
--- a/lib/pleroma/web/activity_pub/utils.ex
+++ b/lib/pleroma/web/activity_pub/utils.ex
@@ -7,6 +7,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
alias Ecto.UUID
alias Pleroma.Activity
alias Pleroma.Config
+ alias Pleroma.EctoType.ActivityPub.ObjectValidators.ObjectID
alias Pleroma.Maps
alias Pleroma.Notification
alias Pleroma.Object
@@ -31,7 +32,8 @@ defmodule Pleroma.Web.ActivityPub.Utils do
"Page",
"Question",
"Answer",
- "Audio"
+ "Audio",
+ "Image"
]
@strip_status_report_states ~w(closed resolved)
@supported_report_states ~w(open closed resolved)
@@ -165,7 +167,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
with true <- Config.get!([:instance, :federating]),
true <- type != "Block" || outgoing_blocks,
- false <- Visibility.is_local_public?(activity) do
+ false <- Visibility.local_public?(activity) do
Pleroma.Web.Federator.publish(activity)
end
@@ -275,7 +277,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
object_actor = User.get_cached_by_ap_id(object_actor_id)
to =
- if Visibility.is_public?(object) do
+ if Visibility.public?(object) do
[actor.follower_address, object.data["actor"]]
else
[object.data["actor"]]
@@ -325,21 +327,29 @@ defmodule Pleroma.Web.ActivityPub.Utils do
{:ok, Object.t()} | {:error, Ecto.Changeset.t()}
def add_emoji_reaction_to_object(
- %Activity{data: %{"content" => emoji, "actor" => actor}},
+ %Activity{data: %{"content" => emoji, "actor" => actor}} = activity,
object
) do
reactions = get_cached_emoji_reactions(object)
+ emoji = Pleroma.Emoji.maybe_strip_name(emoji)
+ url = maybe_emoji_url(emoji, activity)
new_reactions =
- case Enum.find_index(reactions, fn [candidate, _] -> emoji == candidate end) do
+ case Enum.find_index(reactions, fn [candidate, _, candidate_url] ->
+ if is_nil(candidate_url) do
+ emoji == candidate
+ else
+ url == candidate_url
+ end
+ end) do
nil ->
- reactions ++ [[emoji, [actor]]]
+ reactions ++ [[emoji, [actor], url]]
index ->
List.update_at(
reactions,
index,
- fn [emoji, users] -> [emoji, Enum.uniq([actor | users])] end
+ fn [emoji, users, url] -> [emoji, Enum.uniq([actor | users]), url] end
)
end
@@ -348,18 +358,40 @@ defmodule Pleroma.Web.ActivityPub.Utils do
update_element_in_object("reaction", new_reactions, object, count)
end
+ defp maybe_emoji_url(
+ name,
+ %Activity{
+ data: %{
+ "tag" => [
+ %{"type" => "Emoji", "name" => name, "icon" => %{"url" => url}}
+ ]
+ }
+ }
+ ),
+ do: url
+
+ defp maybe_emoji_url(_, _), do: nil
+
def emoji_count(reactions_list) do
- Enum.reduce(reactions_list, 0, fn [_, users], acc -> acc + length(users) end)
+ Enum.reduce(reactions_list, 0, fn [_, users, _], acc -> acc + length(users) end)
end
def remove_emoji_reaction_from_object(
- %Activity{data: %{"content" => emoji, "actor" => actor}},
+ %Activity{data: %{"content" => emoji, "actor" => actor}} = activity,
object
) do
+ emoji = Pleroma.Emoji.maybe_strip_name(emoji)
reactions = get_cached_emoji_reactions(object)
+ url = maybe_emoji_url(emoji, activity)
new_reactions =
- case Enum.find_index(reactions, fn [candidate, _] -> emoji == candidate end) do
+ case Enum.find_index(reactions, fn [candidate, _, candidate_url] ->
+ if is_nil(candidate_url) do
+ emoji == candidate
+ else
+ url == candidate_url
+ end
+ end) do
nil ->
reactions
@@ -367,9 +399,9 @@ defmodule Pleroma.Web.ActivityPub.Utils do
List.update_at(
reactions,
index,
- fn [emoji, users] -> [emoji, List.delete(users, actor)] end
+ fn [emoji, users, url] -> [emoji, List.delete(users, actor), url] end
)
- |> Enum.reject(fn [_, users] -> Enum.empty?(users) end)
+ |> Enum.reject(fn [_, users, _] -> Enum.empty?(users) end)
end
count = emoji_count(new_reactions)
@@ -377,11 +409,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
end
def get_cached_emoji_reactions(object) do
- if is_list(object.data["reactions"]) do
- object.data["reactions"]
- else
- []
- end
+ Object.get_emoji_reactions(object)
end
@spec add_like_to_object(Activity.t(), Object.t()) ::
@@ -489,17 +517,37 @@ defmodule Pleroma.Web.ActivityPub.Utils do
def get_latest_reaction(internal_activity_id, %{ap_id: ap_id}, emoji) do
%{data: %{"object" => object_ap_id}} = Activity.get_by_id(internal_activity_id)
+ emoji = Pleroma.Emoji.maybe_quote(emoji)
"EmojiReact"
|> Activity.Queries.by_type()
|> where(actor: ^ap_id)
- |> where([activity], fragment("?->>'content' = ?", activity.data, ^emoji))
+ |> custom_emoji_discriminator(emoji)
|> Activity.Queries.by_object_id(object_ap_id)
|> order_by([activity], fragment("? desc nulls last", activity.id))
|> limit(1)
|> Repo.one()
end
+ defp custom_emoji_discriminator(query, emoji) do
+ if String.contains?(emoji, "@") do
+ stripped = Pleroma.Emoji.maybe_strip_name(emoji)
+ [name, domain] = String.split(stripped, "@")
+ domain_pattern = "%/" <> domain <> "/%"
+ emoji_pattern = Pleroma.Emoji.maybe_quote(name)
+
+ query
+ |> where([activity], fragment("?->>'content' = ?
+ AND EXISTS (
+ SELECT FROM jsonb_array_elements(?->'tag') elem
+ WHERE elem->>'id' ILIKE ?
+ )", activity.data, ^emoji_pattern, activity.data, ^domain_pattern))
+ else
+ query
+ |> where([activity], fragment("?->>'content' = ?", activity.data, ^emoji))
+ end
+ end
+
#### Announce-related helpers
@doc """
@@ -728,10 +776,9 @@ defmodule Pleroma.Web.ActivityPub.Utils do
build_flag_object(object)
nil ->
- if %Object{} = object = Object.get_by_ap_id(id) do
- build_flag_object(object)
- else
- %{"id" => id, "deleted" => true}
+ case Object.get_by_ap_id(id) do
+ %Object{} = object -> build_flag_object(object)
+ _ -> %{"id" => id, "deleted" => true}
end
end
end
@@ -805,9 +852,11 @@ defmodule Pleroma.Web.ActivityPub.Utils do
[actor | reported_activities] = activity.data["object"]
stripped_activities =
- Enum.map(reported_activities, fn
- act when is_map(act) -> act["id"]
- act when is_binary(act) -> act
+ Enum.reduce(reported_activities, [], fn act, acc ->
+ case ObjectID.cast(act) do
+ {:ok, act} -> [act | acc]
+ _ -> acc
+ end
end)
new_data = put_in(activity.data, ["object"], [actor | stripped_activities])
@@ -885,4 +934,27 @@ defmodule Pleroma.Web.ActivityPub.Utils do
|> where([a, object: o], fragment("(?)->>'type' = 'Answer'", o.data))
|> Repo.all()
end
+
+ def maybe_handle_group_posts(activity) do
+ poster = User.get_cached_by_ap_id(activity.actor)
+
+ mentions =
+ activity.data["to"]
+ |> Enum.filter(&(&1 != activity.actor))
+
+ mentioned_local_groups =
+ User.get_all_by_ap_id(mentions)
+ |> Enum.filter(fn user ->
+ user.actor_type == "Group" and
+ user.local and
+ not User.blocks?(user, poster)
+ end)
+
+ mentioned_local_groups
+ |> Enum.each(fn group ->
+ Pleroma.Web.CommonAPI.repeat(activity.id, group)
+ end)
+
+ :ok
+ end
end
diff --git a/lib/pleroma/web/activity_pub/views/object_view.ex b/lib/pleroma/web/activity_pub/views/object_view.ex
index 63caa91..63caa91 100755..100644
--- a/lib/pleroma/web/activity_pub/views/object_view.ex
+++ b/lib/pleroma/web/activity_pub/views/object_view.ex
diff --git a/lib/pleroma/web/activity_pub/views/user_view.ex b/lib/pleroma/web/activity_pub/views/user_view.ex
index f69fca0..937e4fd 100755..100644
--- a/lib/pleroma/web/activity_pub/views/user_view.ex
+++ b/lib/pleroma/web/activity_pub/views/user_view.ex
@@ -46,6 +46,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
"following" => "#{user.ap_id}/following",
"followers" => "#{user.ap_id}/followers",
"inbox" => "#{user.ap_id}/inbox",
+ "outbox" => "#{user.ap_id}/outbox",
"name" => "Pleroma",
"summary" =>
"An internal service actor for this Pleroma instance. No user-serviceable parts inside.",
@@ -66,8 +67,13 @@ defmodule Pleroma.Web.ActivityPub.UserView do
def render("user.json", %{user: %User{nickname: nil} = user}),
do: render("service.json", %{user: user})
- def render("user.json", %{user: %User{nickname: "internal." <> _} = user}),
- do: render("service.json", %{user: user}) |> Map.put("preferredUsername", user.nickname)
+ def render("user.json", %{user: %User{nickname: "internal." <> _} = user}) do
+ render("service.json", %{user: user})
+ |> Map.merge(%{
+ "preferredUsername" => user.nickname,
+ "webfinger" => "acct:#{User.full_nickname(user)}"
+ })
+ end
def render("user.json", %{user: user}) do
{:ok, _, public_key} = Keys.keys_from_pem(user.keys)
@@ -120,7 +126,8 @@ defmodule Pleroma.Web.ActivityPub.UserView do
"discoverable" => user.is_discoverable,
"capabilities" => capabilities,
"alsoKnownAs" => user.also_known_as,
- "vcard:bday" => birthday
+ "vcard:bday" => birthday,
+ "webfinger" => "acct:#{User.full_nickname(user)}"
}
|> Map.merge(maybe_make_image(&User.avatar_url/2, "icon", user))
|> Map.merge(maybe_make_image(&User.banner_url/2, "image", user))
diff --git a/lib/pleroma/web/activity_pub/visibility.ex b/lib/pleroma/web/activity_pub/visibility.ex
index 7c57f88..97fc7fa 100755..100644
--- a/lib/pleroma/web/activity_pub/visibility.ex
+++ b/lib/pleroma/web/activity_pub/visibility.ex
@@ -11,28 +11,28 @@ defmodule Pleroma.Web.ActivityPub.Visibility do
require Pleroma.Constants
- @spec is_public?(Object.t() | Activity.t() | map()) :: boolean()
- def is_public?(%Object{data: %{"type" => "Tombstone"}}), do: false
- def is_public?(%Object{data: data}), do: is_public?(data)
- def is_public?(%Activity{data: %{"type" => "Move"}}), do: true
- def is_public?(%Activity{data: data}), do: is_public?(data)
- def is_public?(%{"directMessage" => true}), do: false
-
- def is_public?(data) do
+ @spec public?(Object.t() | Activity.t() | map()) :: boolean()
+ def public?(%Object{data: %{"type" => "Tombstone"}}), do: false
+ def public?(%Object{data: data}), do: public?(data)
+ def public?(%Activity{data: %{"type" => "Move"}}), do: true
+ def public?(%Activity{data: data}), do: public?(data)
+ def public?(%{"directMessage" => true}), do: false
+
+ def public?(data) do
Utils.label_in_message?(Pleroma.Constants.as_public(), data) or
Utils.label_in_message?(Utils.as_local_public(), data)
end
- def is_local_public?(%Object{data: data}), do: is_local_public?(data)
- def is_local_public?(%Activity{data: data}), do: is_local_public?(data)
+ def local_public?(%Object{data: data}), do: local_public?(data)
+ def local_public?(%Activity{data: data}), do: local_public?(data)
- def is_local_public?(data) do
+ def local_public?(data) do
Utils.label_in_message?(Utils.as_local_public(), data) and
not Utils.label_in_message?(Pleroma.Constants.as_public(), data)
end
- def is_private?(activity) do
- with false <- is_public?(activity),
+ def private?(activity) do
+ with false <- public?(activity),
%User{follower_address: follower_address} <-
User.get_cached_by_ap_id(activity.data["actor"]) do
follower_address in activity.data["to"]
@@ -41,20 +41,20 @@ defmodule Pleroma.Web.ActivityPub.Visibility do
end
end
- def is_announceable?(activity, user, public \\ true) do
- is_public?(activity) ||
- (!public && is_private?(activity) && activity.data["actor"] == user.ap_id)
+ def announceable?(activity, user, public \\ true) do
+ public?(activity) ||
+ (!public && private?(activity) && activity.data["actor"] == user.ap_id)
end
- def is_direct?(%Activity{data: %{"directMessage" => true}}), do: true
- def is_direct?(%Object{data: %{"directMessage" => true}}), do: true
+ def direct?(%Activity{data: %{"directMessage" => true}}), do: true
+ def direct?(%Object{data: %{"directMessage" => true}}), do: true
- def is_direct?(activity) do
- !is_public?(activity) && !is_private?(activity)
+ def direct?(activity) do
+ !public?(activity) && !private?(activity)
end
- def is_list?(%{data: %{"listMessage" => _}}), do: true
- def is_list?(_), do: false
+ def list?(%{data: %{"listMessage" => _}}), do: true
+ def list?(_), do: false
@spec visible_for_user?(Object.t() | Activity.t() | nil, User.t() | nil) :: boolean()
def visible_for_user?(%Object{data: %{"type" => "Tombstone"}}, _), do: false
@@ -77,7 +77,7 @@ defmodule Pleroma.Web.ActivityPub.Visibility do
when module in [Activity, Object] do
if restrict_unauthenticated_access?(message),
do: false,
- else: is_public?(message) and not is_local_public?(message)
+ else: public?(message) and not local_public?(message)
end
def visible_for_user?(%{__struct__: module} = message, user)
@@ -86,8 +86,8 @@ defmodule Pleroma.Web.ActivityPub.Visibility do
y = [message.data["actor"]] ++ message.data["to"] ++ (message.data["cc"] || [])
user_is_local = user.local
- federatable = not is_local_public?(message)
- (is_public?(message) || Enum.any?(x, &(&1 in y))) and (user_is_local || federatable)
+ federatable = not local_public?(message)
+ (public?(message) || Enum.any?(x, &(&1 in y))) and (user_is_local || federatable)
end
def entire_thread_visible_for_user?(%Activity{} = activity, %User{} = user) do
diff --git a/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex b/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex
index 1894000..1894000 100755..100644
--- a/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex
+++ b/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex
diff --git a/lib/pleroma/web/admin_api/controllers/announcement_controller.ex b/lib/pleroma/web/admin_api/controllers/announcement_controller.ex
index 6ad5fc1..6ad5fc1 100755..100644
--- a/lib/pleroma/web/admin_api/controllers/announcement_controller.ex
+++ b/lib/pleroma/web/admin_api/controllers/announcement_controller.ex
diff --git a/lib/pleroma/web/admin_api/controllers/chat_controller.ex b/lib/pleroma/web/admin_api/controllers/chat_controller.ex
index 298543f..298543f 100755..100644
--- a/lib/pleroma/web/admin_api/controllers/chat_controller.ex
+++ b/lib/pleroma/web/admin_api/controllers/chat_controller.ex
diff --git a/lib/pleroma/web/admin_api/controllers/config_controller.ex b/lib/pleroma/web/admin_api/controllers/config_controller.ex
index a03318c..2c9c272 100755..100644
--- a/lib/pleroma/web/admin_api/controllers/config_controller.ex
+++ b/lib/pleroma/web/admin_api/controllers/config_controller.ex
@@ -9,7 +9,7 @@ defmodule Pleroma.Web.AdminAPI.ConfigController do
alias Pleroma.ConfigDB
alias Pleroma.Web.Plugs.OAuthScopesPlug
- plug(Pleroma.Web.ApiSpec.CastAndValidate)
+ plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
plug(OAuthScopesPlug, %{scopes: ["admin:write"]} when action == :update)
plug(
@@ -76,7 +76,7 @@ defmodule Pleroma.Web.AdminAPI.ConfigController do
json(conn, translate_descriptions(descriptions))
end
- def show(conn, %{only_db: true}) do
+ def show(%{private: %{open_api_spex: %{params: %{only_db: true}}}} = conn, _) do
with :ok <- configurable_from_database() do
configs = Pleroma.Repo.all(ConfigDB)
@@ -128,7 +128,7 @@ defmodule Pleroma.Web.AdminAPI.ConfigController do
end
end
- def update(%{body_params: %{configs: configs}} = conn, _) do
+ def update(%{private: %{open_api_spex: %{body_params: %{configs: configs}}}} = conn, _) do
with :ok <- configurable_from_database() do
results =
configs
diff --git a/lib/pleroma/web/admin_api/controllers/fallback_controller.ex b/lib/pleroma/web/admin_api/controllers/fallback_controller.ex
index e72f45c..e72f45c 100755..100644
--- a/lib/pleroma/web/admin_api/controllers/fallback_controller.ex
+++ b/lib/pleroma/web/admin_api/controllers/fallback_controller.ex
diff --git a/lib/pleroma/web/admin_api/controllers/frontend_controller.ex b/lib/pleroma/web/admin_api/controllers/frontend_controller.ex
index b4dbb82..9e2ed4a 100755..100644
--- a/lib/pleroma/web/admin_api/controllers/frontend_controller.ex
+++ b/lib/pleroma/web/admin_api/controllers/frontend_controller.ex
@@ -18,13 +18,24 @@ defmodule Pleroma.Web.AdminAPI.FrontendController do
def index(conn, _params) do
installed = installed()
+ # FIrst get frontends from config,
+ # then add frontends that are installed but not in the config
frontends =
- [:frontends, :available]
- |> Config.get([])
+ Config.get([:frontends, :available], [])
|> Enum.map(fn {name, desc} ->
- Map.put(desc, "installed", name in installed)
+ desc
+ |> Map.put("installed", name in installed)
+ |> Map.put("installed_refs", installed_refs(name))
end)
+ frontends =
+ frontends ++
+ (installed
+ |> Enum.filter(fn n -> not Enum.any?(frontends, fn f -> f["name"] == n end) end)
+ |> Enum.map(fn name ->
+ %{"name" => name, "installed" => true, "installed_refs" => installed_refs(name)}
+ end))
+
render(conn, "index.json", frontends: frontends)
end
@@ -43,4 +54,12 @@ defmodule Pleroma.Web.AdminAPI.FrontendController do
[]
end
end
+
+ def installed_refs(name) do
+ if name in installed() do
+ File.ls!(Path.join(Pleroma.Frontend.dir(), name))
+ else
+ []
+ end
+ end
end
diff --git a/lib/pleroma/web/admin_api/controllers/instance_controller.ex b/lib/pleroma/web/admin_api/controllers/instance_controller.ex
index 117a722..117a722 100755..100644
--- a/lib/pleroma/web/admin_api/controllers/instance_controller.ex
+++ b/lib/pleroma/web/admin_api/controllers/instance_controller.ex
diff --git a/lib/pleroma/web/admin_api/controllers/instance_document_controller.ex b/lib/pleroma/web/admin_api/controllers/instance_document_controller.ex
index 990a943..d76a959 100755..100644
--- a/lib/pleroma/web/admin_api/controllers/instance_document_controller.ex
+++ b/lib/pleroma/web/admin_api/controllers/instance_document_controller.ex
@@ -9,7 +9,7 @@ defmodule Pleroma.Web.AdminAPI.InstanceDocumentController do
alias Pleroma.Web.Plugs.InstanceStatic
alias Pleroma.Web.Plugs.OAuthScopesPlug
- plug(Pleroma.Web.ApiSpec.CastAndValidate)
+ plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
action_fallback(Pleroma.Web.AdminAPI.FallbackController)
@@ -18,7 +18,7 @@ defmodule Pleroma.Web.AdminAPI.InstanceDocumentController do
plug(OAuthScopesPlug, %{scopes: ["admin:read"]} when action == :show)
plug(OAuthScopesPlug, %{scopes: ["admin:write"]} when action in [:update, :delete])
- def show(conn, %{name: document_name}) do
+ def show(%{private: %{open_api_spex: %{params: %{name: document_name}}}} = conn, _) do
with {:ok, url} <- InstanceDocument.get(document_name),
{:ok, content} <- File.read(InstanceStatic.file_path(url)) do
conn
@@ -27,13 +27,18 @@ defmodule Pleroma.Web.AdminAPI.InstanceDocumentController do
end
end
- def update(%{body_params: %{file: file}} = conn, %{name: document_name}) do
+ def update(
+ %{
+ private: %{open_api_spex: %{body_params: %{file: file}, params: %{name: document_name}}}
+ } = conn,
+ _
+ ) do
with {:ok, url} <- InstanceDocument.put(document_name, file.path) do
json(conn, %{"url" => url})
end
end
- def delete(conn, %{name: document_name}) do
+ def delete(%{private: %{open_api_spex: %{params: %{name: document_name}}}} = conn, _) do
with :ok <- InstanceDocument.delete(document_name) do
json(conn, %{})
end
diff --git a/lib/pleroma/web/admin_api/controllers/invite_controller.ex b/lib/pleroma/web/admin_api/controllers/invite_controller.ex
index c5d759b..7e3020f 100755..100644
--- a/lib/pleroma/web/admin_api/controllers/invite_controller.ex
+++ b/lib/pleroma/web/admin_api/controllers/invite_controller.ex
@@ -13,7 +13,7 @@ defmodule Pleroma.Web.AdminAPI.InviteController do
require Logger
- plug(Pleroma.Web.ApiSpec.CastAndValidate)
+ plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
plug(OAuthScopesPlug, %{scopes: ["admin:read:invites"]} when action == :index)
plug(
@@ -33,14 +33,14 @@ defmodule Pleroma.Web.AdminAPI.InviteController do
end
@doc "Create an account registration invite token"
- def create(%{body_params: params} = conn, _) do
+ def create(%{private: %{open_api_spex: %{body_params: params}}} = conn, _) do
{:ok, invite} = UserInviteToken.create_invite(params)
render(conn, "show.json", invite: invite)
end
@doc "Revokes invite by token"
- def revoke(%{body_params: %{token: token}} = conn, _) do
+ def revoke(%{private: %{open_api_spex: %{body_params: %{token: token}}}} = conn, _) do
with {:ok, invite} <- UserInviteToken.find_by_token(token),
{:ok, updated_invite} = UserInviteToken.update_invite(invite, %{used: true}) do
render(conn, "show.json", invite: updated_invite)
@@ -51,7 +51,13 @@ defmodule Pleroma.Web.AdminAPI.InviteController do
end
@doc "Sends registration invite via email"
- def email(%{assigns: %{user: user}, body_params: %{email: email} = params} = conn, _) do
+ def email(
+ %{
+ assigns: %{user: user},
+ private: %{open_api_spex: %{body_params: %{email: email} = params}}
+ } = conn,
+ _
+ ) do
with {_, false} <- {:registrations_open, Config.get([:instance, :registrations_open])},
{_, true} <- {:invites_enabled, Config.get([:instance, :invites_enabled])},
{:ok, invite_token} <- UserInviteToken.create_invite(),
diff --git a/lib/pleroma/web/admin_api/controllers/media_proxy_cache_controller.ex b/lib/pleroma/web/admin_api/controllers/media_proxy_cache_controller.ex
index 4d53f54..8b43ea9 100755..100644
--- a/lib/pleroma/web/admin_api/controllers/media_proxy_cache_controller.ex
+++ b/lib/pleroma/web/admin_api/controllers/media_proxy_cache_controller.ex
@@ -11,7 +11,7 @@ defmodule Pleroma.Web.AdminAPI.MediaProxyCacheController do
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
- plug(Pleroma.Web.ApiSpec.CastAndValidate)
+ plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
plug(
OAuthScopesPlug,
@@ -27,7 +27,7 @@ defmodule Pleroma.Web.AdminAPI.MediaProxyCacheController do
defdelegate open_api_operation(action), to: Spec.MediaProxyCacheOperation
- def index(%{assigns: %{user: _}} = conn, params) do
+ def index(%{assigns: %{user: _}, private: %{open_api_spex: %{params: params}}} = conn, _) do
entries = fetch_entries(params)
urls = paginate_entries(entries, params.page, params.page_size)
@@ -59,12 +59,19 @@ defmodule Pleroma.Web.AdminAPI.MediaProxyCacheController do
Enum.slice(entries, offset, page_size)
end
- def delete(%{assigns: %{user: _}, body_params: %{urls: urls}} = conn, _) do
+ def delete(
+ %{assigns: %{user: _}, private: %{open_api_spex: %{body_params: %{urls: urls}}}} = conn,
+ _
+ ) do
MediaProxy.remove_from_banned_urls(urls)
json(conn, %{})
end
- def purge(%{assigns: %{user: _}, body_params: %{urls: urls, ban: ban}} = conn, _) do
+ def purge(
+ %{assigns: %{user: _}, private: %{open_api_spex: %{body_params: %{urls: urls, ban: ban}}}} =
+ conn,
+ _
+ ) do
MediaProxy.Invalidation.purge(urls)
if ban do
diff --git a/lib/pleroma/web/admin_api/controllers/o_auth_app_controller.ex b/lib/pleroma/web/admin_api/controllers/o_auth_app_controller.ex
index 879e8b2..879e8b2 100755..100644
--- a/lib/pleroma/web/admin_api/controllers/o_auth_app_controller.ex
+++ b/lib/pleroma/web/admin_api/controllers/o_auth_app_controller.ex
diff --git a/lib/pleroma/web/admin_api/controllers/relay_controller.ex b/lib/pleroma/web/admin_api/controllers/relay_controller.ex
index 2e83fe1..1f36d3b 100755..100644
--- a/lib/pleroma/web/admin_api/controllers/relay_controller.ex
+++ b/lib/pleroma/web/admin_api/controllers/relay_controller.ex
@@ -11,7 +11,7 @@ defmodule Pleroma.Web.AdminAPI.RelayController do
require Logger
- plug(Pleroma.Web.ApiSpec.CastAndValidate)
+ plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
plug(
OAuthScopesPlug,
@@ -31,7 +31,13 @@ defmodule Pleroma.Web.AdminAPI.RelayController do
end
end
- def follow(%{assigns: %{user: admin}, body_params: %{relay_url: target}} = conn, _) do
+ def follow(
+ %{
+ assigns: %{user: admin},
+ private: %{open_api_spex: %{body_params: %{relay_url: target}}}
+ } = conn,
+ _
+ ) do
with {:ok, _message} <- Relay.follow(target) do
ModerationLog.insert_log(%{action: "relay_follow", actor: admin, target: target})
@@ -44,7 +50,13 @@ defmodule Pleroma.Web.AdminAPI.RelayController do
end
end
- def unfollow(%{assigns: %{user: admin}, body_params: %{relay_url: target} = params} = conn, _) do
+ def unfollow(
+ %{
+ assigns: %{user: admin},
+ private: %{open_api_spex: %{body_params: %{relay_url: target} = params}}
+ } = conn,
+ _
+ ) do
with {:ok, _message} <- Relay.unfollow(target, %{force: params[:force]}) do
ModerationLog.insert_log(%{action: "relay_unfollow", actor: admin, target: target})
diff --git a/lib/pleroma/web/admin_api/controllers/report_controller.ex b/lib/pleroma/web/admin_api/controllers/report_controller.ex
index 15cbbcc..89d8cc8 100755..100644
--- a/lib/pleroma/web/admin_api/controllers/report_controller.ex
+++ b/lib/pleroma/web/admin_api/controllers/report_controller.ex
@@ -18,7 +18,7 @@ defmodule Pleroma.Web.AdminAPI.ReportController do
require Logger
- plug(Pleroma.Web.ApiSpec.CastAndValidate)
+ plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
plug(OAuthScopesPlug, %{scopes: ["admin:read:reports"]} when action in [:index, :show])
plug(
@@ -31,13 +31,13 @@ defmodule Pleroma.Web.AdminAPI.ReportController do
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.Admin.ReportOperation
- def index(conn, params) do
+ def index(%{private: %{open_api_spex: %{params: params}}} = conn, _) do
reports = Utils.get_reports(params, params.page, params.page_size)
render(conn, "index.json", reports: reports)
end
- def show(conn, %{id: id}) do
+ def show(%{private: %{open_api_spex: %{params: %{id: id}}}} = conn, _) do
with %Activity{} = report <- Activity.get_report(id) do
render(conn, "show.json", Report.extract_report_info(report))
else
@@ -45,7 +45,13 @@ defmodule Pleroma.Web.AdminAPI.ReportController do
end
end
- def update(%{assigns: %{user: admin}, body_params: %{reports: reports}} = conn, _) do
+ def update(
+ %{
+ assigns: %{user: admin},
+ private: %{open_api_spex: %{body_params: %{reports: reports}}}
+ } = conn,
+ _
+ ) do
result =
Enum.map(reports, fn report ->
case CommonAPI.update_report_state(report.id, report.state) do
@@ -73,9 +79,13 @@ defmodule Pleroma.Web.AdminAPI.ReportController do
end
end
- def notes_create(%{assigns: %{user: user}, body_params: %{content: content}} = conn, %{
- id: report_id
- }) do
+ def notes_create(
+ %{
+ assigns: %{user: user},
+ private: %{open_api_spex: %{body_params: %{content: content}, params: %{id: report_id}}}
+ } = conn,
+ _
+ ) do
with {:ok, _} <- ReportNote.create(user.id, report_id, content),
report <- Activity.get_by_id_with_user_actor(report_id) do
ModerationLog.insert_log(%{
@@ -92,10 +102,20 @@ defmodule Pleroma.Web.AdminAPI.ReportController do
end
end
- def notes_delete(%{assigns: %{user: user}} = conn, %{
- id: note_id,
- report_id: report_id
- }) do
+ def notes_delete(
+ %{
+ assigns: %{user: user},
+ private: %{
+ open_api_spex: %{
+ params: %{
+ id: note_id,
+ report_id: report_id
+ }
+ }
+ }
+ } = conn,
+ _
+ ) do
with {:ok, note} <- ReportNote.destroy(note_id),
report <- Activity.get_by_id_with_user_actor(report_id) do
ModerationLog.insert_log(%{
diff --git a/lib/pleroma/web/admin_api/controllers/status_controller.ex b/lib/pleroma/web/admin_api/controllers/status_controller.ex
index 9a3d49b..9a3d49b 100755..100644
--- a/lib/pleroma/web/admin_api/controllers/status_controller.ex
+++ b/lib/pleroma/web/admin_api/controllers/status_controller.ex
diff --git a/lib/pleroma/web/admin_api/controllers/user_controller.ex b/lib/pleroma/web/admin_api/controllers/user_controller.ex
index 7b4ee46..9ac2753 100755..100644
--- a/lib/pleroma/web/admin_api/controllers/user_controller.ex
+++ b/lib/pleroma/web/admin_api/controllers/user_controller.ex
@@ -18,7 +18,7 @@ defmodule Pleroma.Web.AdminAPI.UserController do
@users_page_size 50
- plug(Pleroma.Web.ApiSpec.CastAndValidate)
+ plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
plug(
OAuthScopesPlug,
@@ -51,13 +51,22 @@ defmodule Pleroma.Web.AdminAPI.UserController do
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.Admin.UserOperation
- def delete(conn, %{nickname: nickname}) do
+ def delete(%{private: %{open_api_spex: %{params: %{nickname: nickname}}}} = conn, _) do
conn
- |> Map.put(:body_params, %{nicknames: [nickname]})
- |> delete(%{})
+ |> do_deletes([nickname])
end
- def delete(%{assigns: %{user: admin}, body_params: %{nicknames: nicknames}} = conn, _) do
+ def delete(
+ %{
+ private: %{open_api_spex: %{body_params: %{nicknames: nicknames}}}
+ } = conn,
+ _
+ ) do
+ conn
+ |> do_deletes(nicknames)
+ end
+
+ defp do_deletes(%{assigns: %{user: admin}} = conn, nicknames) when is_list(nicknames) do
users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
Enum.each(users, fn user ->
@@ -77,9 +86,13 @@ defmodule Pleroma.Web.AdminAPI.UserController do
def follow(
%{
assigns: %{user: admin},
- body_params: %{
- follower: follower_nick,
- followed: followed_nick
+ private: %{
+ open_api_spex: %{
+ body_params: %{
+ follower: follower_nick,
+ followed: followed_nick
+ }
+ }
}
} = conn,
_
@@ -102,9 +115,13 @@ defmodule Pleroma.Web.AdminAPI.UserController do
def unfollow(
%{
assigns: %{user: admin},
- body_params: %{
- follower: follower_nick,
- followed: followed_nick
+ private: %{
+ open_api_spex: %{
+ body_params: %{
+ follower: follower_nick,
+ followed: followed_nick
+ }
+ }
}
} = conn,
_
@@ -124,7 +141,13 @@ defmodule Pleroma.Web.AdminAPI.UserController do
json(conn, "ok")
end
- def create(%{assigns: %{user: admin}, body_params: %{users: users}} = conn, _) do
+ def create(
+ %{
+ assigns: %{user: admin},
+ private: %{open_api_spex: %{body_params: %{users: users}}}
+ } = conn,
+ _
+ ) do
changesets =
users
|> Enum.map(fn %{nickname: nickname, email: email, password: password} ->
@@ -178,7 +201,13 @@ defmodule Pleroma.Web.AdminAPI.UserController do
end
end
- def show(%{assigns: %{user: admin}} = conn, %{nickname: nickname}) do
+ def show(
+ %{
+ assigns: %{user: admin},
+ private: %{open_api_spex: %{params: %{nickname: nickname}}}
+ } = conn,
+ _
+ ) do
with %User{} = user <- User.get_cached_by_nickname_or_id(nickname, for: admin) do
render(conn, "show.json", %{user: user})
else
@@ -186,7 +215,11 @@ defmodule Pleroma.Web.AdminAPI.UserController do
end
end
- def toggle_activation(%{assigns: %{user: admin}} = conn, %{nickname: nickname}) do
+ def toggle_activation(
+ %{assigns: %{user: admin}, private: %{open_api_spex: %{params: %{nickname: nickname}}}} =
+ conn,
+ _
+ ) do
user = User.get_cached_by_nickname(nickname)
{:ok, updated_user} = User.set_activation(user, !user.is_active)
@@ -202,7 +235,13 @@ defmodule Pleroma.Web.AdminAPI.UserController do
render(conn, "show.json", user: updated_user)
end
- def activate(%{assigns: %{user: admin}, body_params: %{nicknames: nicknames}} = conn, _) do
+ def activate(
+ %{
+ assigns: %{user: admin},
+ private: %{open_api_spex: %{body_params: %{nicknames: nicknames}}}
+ } = conn,
+ _
+ ) do
users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
{:ok, updated_users} = User.set_activation(users, true)
@@ -212,10 +251,16 @@ defmodule Pleroma.Web.AdminAPI.UserController do
action: "activate"
})
- render(conn, "index.json", users: Keyword.values(updated_users))
+ render(conn, "index.json", users: updated_users)
end
- def deactivate(%{assigns: %{user: admin}, body_params: %{nicknames: nicknames}} = conn, _) do
+ def deactivate(
+ %{
+ assigns: %{user: admin},
+ private: %{open_api_spex: %{body_params: %{nicknames: nicknames}}}
+ } = conn,
+ _
+ ) do
users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
{:ok, updated_users} = User.set_activation(users, false)
@@ -225,10 +270,16 @@ defmodule Pleroma.Web.AdminAPI.UserController do
action: "deactivate"
})
- render(conn, "index.json", users: Keyword.values(updated_users))
+ render(conn, "index.json", users: updated_users)
end
- def approve(%{assigns: %{user: admin}, body_params: %{nicknames: nicknames}} = conn, _) do
+ def approve(
+ %{
+ assigns: %{user: admin},
+ private: %{open_api_spex: %{body_params: %{nicknames: nicknames}}}
+ } = conn,
+ _
+ ) do
users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
{:ok, updated_users} = User.approve(users)
@@ -241,7 +292,13 @@ defmodule Pleroma.Web.AdminAPI.UserController do
render(conn, "index.json", users: updated_users)
end
- def suggest(%{assigns: %{user: admin}, body_params: %{nicknames: nicknames}} = conn, _) do
+ def suggest(
+ %{
+ assigns: %{user: admin},
+ private: %{open_api_spex: %{body_params: %{nicknames: nicknames}}}
+ } = conn,
+ _
+ ) do
users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
{:ok, updated_users} = User.set_suggestion(users, true)
@@ -254,7 +311,13 @@ defmodule Pleroma.Web.AdminAPI.UserController do
render(conn, "index.json", users: updated_users)
end
- def unsuggest(%{assigns: %{user: admin}, body_params: %{nicknames: nicknames}} = conn, _) do
+ def unsuggest(
+ %{
+ assigns: %{user: admin},
+ private: %{open_api_spex: %{body_params: %{nicknames: nicknames}}}
+ } = conn,
+ _
+ ) do
users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
{:ok, updated_users} = User.set_suggestion(users, false)
@@ -267,7 +330,7 @@ defmodule Pleroma.Web.AdminAPI.UserController do
render(conn, "index.json", users: updated_users)
end
- def index(conn, params) do
+ def index(%{private: %{open_api_spex: %{params: params}}} = conn, _) do
{page, page_size} = page_params(params)
filters = maybe_parse_filters(params[:filters])
diff --git a/lib/pleroma/web/admin_api/report.ex b/lib/pleroma/web/admin_api/report.ex
index fa89e34..fa89e34 100755..100644
--- a/lib/pleroma/web/admin_api/report.ex
+++ b/lib/pleroma/web/admin_api/report.ex
diff --git a/lib/pleroma/web/admin_api/search.ex b/lib/pleroma/web/admin_api/search.ex
index f5195ac..f5195ac 100755..100644
--- a/lib/pleroma/web/admin_api/search.ex
+++ b/lib/pleroma/web/admin_api/search.ex
diff --git a/lib/pleroma/web/admin_api/views/account_view.ex b/lib/pleroma/web/admin_api/views/account_view.ex
index 2801522..2801522 100755..100644
--- a/lib/pleroma/web/admin_api/views/account_view.ex
+++ b/lib/pleroma/web/admin_api/views/account_view.ex
diff --git a/lib/pleroma/web/admin_api/views/announcement_view.ex b/lib/pleroma/web/admin_api/views/announcement_view.ex
index a35bd60..a35bd60 100755..100644
--- a/lib/pleroma/web/admin_api/views/announcement_view.ex
+++ b/lib/pleroma/web/admin_api/views/announcement_view.ex
diff --git a/lib/pleroma/web/admin_api/views/chat_view.ex b/lib/pleroma/web/admin_api/views/chat_view.ex
index d58bf8e..d58bf8e 100755..100644
--- a/lib/pleroma/web/admin_api/views/chat_view.ex
+++ b/lib/pleroma/web/admin_api/views/chat_view.ex
diff --git a/lib/pleroma/web/admin_api/views/config_view.ex b/lib/pleroma/web/admin_api/views/config_view.ex
index f582ad4..f582ad4 100755..100644
--- a/lib/pleroma/web/admin_api/views/config_view.ex
+++ b/lib/pleroma/web/admin_api/views/config_view.ex
diff --git a/lib/pleroma/web/admin_api/views/frontend_view.ex b/lib/pleroma/web/admin_api/views/frontend_view.ex
index 0ca3d67..ae40165 100755..100644
--- a/lib/pleroma/web/admin_api/views/frontend_view.ex
+++ b/lib/pleroma/web/admin_api/views/frontend_view.ex
@@ -15,7 +15,8 @@ defmodule Pleroma.Web.AdminAPI.FrontendView do
git: frontend["git"],
build_url: frontend["build_url"],
ref: frontend["ref"],
- installed: frontend["installed"]
+ installed: frontend["installed"],
+ installed_refs: frontend["installed_refs"]
}
end
end
diff --git a/lib/pleroma/web/admin_api/views/invite_view.ex b/lib/pleroma/web/admin_api/views/invite_view.ex
index 76cee3b..76cee3b 100755..100644
--- a/lib/pleroma/web/admin_api/views/invite_view.ex
+++ b/lib/pleroma/web/admin_api/views/invite_view.ex
diff --git a/lib/pleroma/web/admin_api/views/media_proxy_cache_view.ex b/lib/pleroma/web/admin_api/views/media_proxy_cache_view.ex
index b46f54e..b46f54e 100755..100644
--- a/lib/pleroma/web/admin_api/views/media_proxy_cache_view.ex
+++ b/lib/pleroma/web/admin_api/views/media_proxy_cache_view.ex
diff --git a/lib/pleroma/web/admin_api/views/moderation_log_view.ex b/lib/pleroma/web/admin_api/views/moderation_log_view.ex
index 1f25f19..1f25f19 100755..100644
--- a/lib/pleroma/web/admin_api/views/moderation_log_view.ex
+++ b/lib/pleroma/web/admin_api/views/moderation_log_view.ex
diff --git a/lib/pleroma/web/admin_api/views/o_auth_app_view.ex b/lib/pleroma/web/admin_api/views/o_auth_app_view.ex
index d1aef0e..d1aef0e 100755..100644
--- a/lib/pleroma/web/admin_api/views/o_auth_app_view.ex
+++ b/lib/pleroma/web/admin_api/views/o_auth_app_view.ex
diff --git a/lib/pleroma/web/admin_api/views/report_view.ex b/lib/pleroma/web/admin_api/views/report_view.ex
index b761dbb..b761dbb 100755..100644
--- a/lib/pleroma/web/admin_api/views/report_view.ex
+++ b/lib/pleroma/web/admin_api/views/report_view.ex
diff --git a/lib/pleroma/web/admin_api/views/status_view.ex b/lib/pleroma/web/admin_api/views/status_view.ex
index 03b5c44..03b5c44 100755..100644
--- a/lib/pleroma/web/admin_api/views/status_view.ex
+++ b/lib/pleroma/web/admin_api/views/status_view.ex
diff --git a/lib/pleroma/web/admin_api/views/user_view.ex b/lib/pleroma/web/admin_api/views/user_view.ex
index f198921..f198921 100755..100644
--- a/lib/pleroma/web/admin_api/views/user_view.ex
+++ b/lib/pleroma/web/admin_api/views/user_view.ex
diff --git a/lib/pleroma/web/api_spec.ex b/lib/pleroma/web/api_spec.ex
index cae4241..10d2215 100755..100644
--- a/lib/pleroma/web/api_spec.ex
+++ b/lib/pleroma/web/api_spec.ex
@@ -10,6 +10,14 @@ defmodule Pleroma.Web.ApiSpec do
@behaviour OpenApi
+ defp streaming_paths do
+ %{
+ "/api/v1/streaming" => %OpenApiSpex.PathItem{
+ get: Pleroma.Web.ApiSpec.StreamingOperation.streaming_operation()
+ }
+ }
+ end
+
@impl OpenApi
def spec(opts \\ []) do
%OpenApi{
@@ -35,7 +43,7 @@ defmodule Pleroma.Web.ApiSpec do
- [Mastodon API documentation](https://docs.joinmastodon.org/client/intro/)
- [Differences in Mastodon API responses from vanilla Mastodon](https://docs-develop.pleroma.social/backend/development/API/differences_in_mastoapi_responses/)
- Please report such occurences on our [issue tracker](https://git.pleroma.social/pleroma/pleroma/-/issues). Feel free to submit API questions or proposals there too!
+ Please report such occurrences on our [issue tracker](https://git.pleroma.social/pleroma/pleroma/-/issues). Feel free to submit API questions or proposals there too!
""",
# Strip environment from the version
version: Application.spec(:pleroma, :vsn) |> to_string() |> String.replace(~r/\+.*$/, ""),
@@ -45,7 +53,7 @@ defmodule Pleroma.Web.ApiSpec do
}
},
# populate the paths from a phoenix router
- paths: OpenApiSpex.Paths.from_router(Router),
+ paths: Map.merge(streaming_paths(), OpenApiSpex.Paths.from_router(Router)),
components: %OpenApiSpex.Components{
parameters: %{
"accountIdOrNickname" =>
@@ -86,16 +94,17 @@ defmodule Pleroma.Web.ApiSpec do
"tags" => [
"Chat administration",
"Emoji pack administration",
- "Frontend managment",
+ "Frontend management",
"Instance configuration",
"Instance documents",
"Invites",
"MediaProxy cache",
- "OAuth application managment",
+ "OAuth application management",
"Relays",
- "Report managment",
+ "Report management",
"Status administration",
- "User administration"
+ "User administration",
+ "Announcement management"
]
},
%{"name" => "Applications", "tags" => ["Applications", "Push subscriptions"]},
@@ -110,10 +119,12 @@ defmodule Pleroma.Web.ApiSpec do
"Follow requests",
"Mascot",
"Markers",
- "Notifications"
+ "Notifications",
+ "Filters",
+ "Settings"
]
},
- %{"name" => "Instance", "tags" => ["Custom emojis"]},
+ %{"name" => "Instance", "tags" => ["Custom emojis", "Instance misc"]},
%{"name" => "Messaging", "tags" => ["Chats", "Conversations"]},
%{
"name" => "Statuses",
@@ -125,10 +136,22 @@ defmodule Pleroma.Web.ApiSpec do
"Retrieve status information",
"Scheduled statuses",
"Search",
- "Status actions"
+ "Status actions",
+ "Media attachments",
+ "Bookmark folders"
]
},
- %{"name" => "Miscellaneous", "tags" => ["Emoji packs", "Reports", "Suggestions"]}
+ %{
+ "name" => "Miscellaneous",
+ "tags" => [
+ "Emoji packs",
+ "Reports",
+ "Suggestions",
+ "Announcements",
+ "Remote interaction",
+ "Others"
+ ]
+ }
]
}
}
diff --git a/lib/pleroma/web/api_spec/cast_and_validate.ex b/lib/pleroma/web/api_spec/cast_and_validate.ex
index add59eb..f3e8e09 100755..100644
--- a/lib/pleroma/web/api_spec/cast_and_validate.ex
+++ b/lib/pleroma/web/api_spec/cast_and_validate.ex
@@ -27,10 +27,12 @@ defmodule Pleroma.Web.ApiSpec.CastAndValidate do
@impl Plug
- def call(conn, %{operation_id: operation_id, render_error: render_error}) do
+ def call(conn, %{operation_id: operation_id, render_error: render_error} = opts) do
{spec, operation_lookup} = PutApiSpec.get_spec_and_operation_lookup(conn)
operation = operation_lookup[operation_id]
+ cast_opts = opts |> Map.take([:replace_params]) |> Map.to_list()
+
content_type =
case Conn.get_req_header(conn, "content-type") do
[header_value | _] ->
@@ -44,7 +46,7 @@ defmodule Pleroma.Web.ApiSpec.CastAndValidate do
conn = Conn.put_private(conn, :operation_id, operation_id)
- case cast_and_validate(spec, operation, conn, content_type, strict?()) do
+ case cast_and_validate(spec, operation, conn, content_type, strict?(), cast_opts) do
{:ok, conn} ->
conn
@@ -94,11 +96,11 @@ defmodule Pleroma.Web.ApiSpec.CastAndValidate do
def call(conn, opts), do: OpenApiSpex.Plug.CastAndValidate.call(conn, opts)
- defp cast_and_validate(spec, operation, conn, content_type, true = _strict) do
- OpenApiSpex.cast_and_validate(spec, operation, conn, content_type)
+ defp cast_and_validate(spec, operation, conn, content_type, true = _strict, cast_opts) do
+ OpenApiSpex.cast_and_validate(spec, operation, conn, content_type, cast_opts)
end
- defp cast_and_validate(spec, operation, conn, content_type, false = _strict) do
+ defp cast_and_validate(spec, operation, conn, content_type, false = _strict, cast_opts) do
case OpenApiSpex.cast_and_validate(spec, operation, conn, content_type) do
{:ok, conn} ->
{:ok, conn}
@@ -123,7 +125,7 @@ defmodule Pleroma.Web.ApiSpec.CastAndValidate do
end)
conn = %Conn{conn | query_params: query_params}
- OpenApiSpex.cast_and_validate(spec, operation, conn, content_type)
+ OpenApiSpex.cast_and_validate(spec, operation, conn, content_type, cast_opts)
end
end
diff --git a/lib/pleroma/web/api_spec/helpers.ex b/lib/pleroma/web/api_spec/helpers.ex
index f20a916..7257253 100755..100644
--- a/lib/pleroma/web/api_spec/helpers.ex
+++ b/lib/pleroma/web/api_spec/helpers.ex
@@ -62,7 +62,7 @@ defmodule Pleroma.Web.ApiSpec.Helpers do
Operation.parameter(
:with_relationships,
:query,
- BooleanLike,
+ BooleanLike.schema(),
"Embed relationships into accounts. **If this parameter is not set account's `pleroma.relationship` is going to be `null`.**"
)
end
diff --git a/lib/pleroma/web/api_spec/operations/account_operation.ex b/lib/pleroma/web/api_spec/operations/account_operation.ex
index aabe988..36025e4 100755..100644
--- a/lib/pleroma/web/api_spec/operations/account_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/account_operation.ex
@@ -122,22 +122,27 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
parameters:
[
%Reference{"$ref": "#/components/parameters/accountIdOrNickname"},
- Operation.parameter(:pinned, :query, BooleanLike, "Include only pinned statuses"),
+ Operation.parameter(
+ :pinned,
+ :query,
+ BooleanLike.schema(),
+ "Include only pinned statuses"
+ ),
Operation.parameter(:tagged, :query, :string, "With tag"),
Operation.parameter(
:only_media,
:query,
- BooleanLike,
+ BooleanLike.schema(),
"Include only statuses with media attached"
),
Operation.parameter(
:with_muted,
:query,
- BooleanLike,
+ BooleanLike.schema(),
"Include statuses from muted accounts."
),
- Operation.parameter(:exclude_reblogs, :query, BooleanLike, "Exclude reblogs"),
- Operation.parameter(:exclude_replies, :query, BooleanLike, "Exclude replies"),
+ Operation.parameter(:exclude_reblogs, :query, BooleanLike.schema(), "Exclude reblogs"),
+ Operation.parameter(:exclude_replies, :query, BooleanLike.schema(), "Exclude replies"),
Operation.parameter(
:exclude_visibilities,
:query,
@@ -147,7 +152,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
Operation.parameter(
:with_muted,
:query,
- BooleanLike,
+ BooleanLike.schema(),
"Include reactions from muted accounts."
)
] ++ pagination_params(),
@@ -347,7 +352,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
summary: "Endorse",
operationId: "AccountController.endorse",
security: [%{"oAuth" => ["follow", "write:accounts"]}],
- description: "Addds the given account to endorsed accounts list.",
+ description: "Adds the given account to endorsed accounts list.",
parameters: [%Reference{"$ref": "#/components/parameters/accountIdOrNickname"}],
responses: %{
200 => Operation.response("Relationship", "application/json", AccountRelationship),
@@ -452,7 +457,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
operationId: "AccountController.blocks",
description: "View your blocks. See also accounts/:id/{block,unblock}",
security: [%{"oAuth" => ["read:blocks"]}],
- parameters: pagination_params(),
+ parameters: [with_relationships_param() | pagination_params()],
responses: %{
200 => Operation.response("Accounts", "application/json", array_of_accounts())
}
@@ -461,7 +466,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
def lookup_operation do
%Operation{
- tags: ["Account lookup"],
+ tags: ["Retrieve account information"],
summary: "Find a user by nickname",
operationId: "AccountController.lookup",
parameters: [
diff --git a/lib/pleroma/web/api_spec/operations/admin/announcement_operation.ex b/lib/pleroma/web/api_spec/operations/admin/announcement_operation.ex
index 58a039e..49850e5 100755..100644
--- a/lib/pleroma/web/api_spec/operations/admin/announcement_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/admin/announcement_operation.ex
@@ -17,7 +17,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.AnnouncementOperation do
def index_operation do
%Operation{
- tags: ["Announcement managment"],
+ tags: ["Announcement management"],
summary: "Retrieve a list of announcements",
operationId: "AdminAPI.AnnouncementController.index",
security: [%{"oAuth" => ["admin:read"]}],
@@ -46,7 +46,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.AnnouncementOperation do
def show_operation do
%Operation{
- tags: ["Announcement managment"],
+ tags: ["Announcement management"],
summary: "Display one announcement",
operationId: "AdminAPI.AnnouncementController.show",
security: [%{"oAuth" => ["admin:read"]}],
@@ -69,7 +69,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.AnnouncementOperation do
def delete_operation do
%Operation{
- tags: ["Announcement managment"],
+ tags: ["Announcement management"],
summary: "Delete one announcement",
operationId: "AdminAPI.AnnouncementController.delete",
security: [%{"oAuth" => ["admin:write"]}],
@@ -92,7 +92,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.AnnouncementOperation do
def create_operation do
%Operation{
- tags: ["Announcement managment"],
+ tags: ["Announcement management"],
summary: "Create one announcement",
operationId: "AdminAPI.AnnouncementController.create",
security: [%{"oAuth" => ["admin:write"]}],
@@ -107,7 +107,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.AnnouncementOperation do
def change_operation do
%Operation{
- tags: ["Announcement managment"],
+ tags: ["Announcement management"],
summary: "Change one announcement",
operationId: "AdminAPI.AnnouncementController.change",
security: [%{"oAuth" => ["admin:write"]}],
diff --git a/lib/pleroma/web/api_spec/operations/admin/chat_operation.ex b/lib/pleroma/web/api_spec/operations/admin/chat_operation.ex
index 2a274e0..2a274e0 100755..100644
--- a/lib/pleroma/web/api_spec/operations/admin/chat_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/admin/chat_operation.ex
diff --git a/lib/pleroma/web/api_spec/operations/admin/config_operation.ex b/lib/pleroma/web/api_spec/operations/admin/config_operation.ex
index 487dd5c..487dd5c 100755..100644
--- a/lib/pleroma/web/api_spec/operations/admin/config_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/admin/config_operation.ex
diff --git a/lib/pleroma/web/api_spec/operations/admin/frontend_operation.ex b/lib/pleroma/web/api_spec/operations/admin/frontend_operation.ex
index 4bfe5ac..e17881b 100755..100644
--- a/lib/pleroma/web/api_spec/operations/admin/frontend_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/admin/frontend_operation.ex
@@ -16,7 +16,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.FrontendOperation do
def index_operation do
%Operation{
- tags: ["Frontend managment"],
+ tags: ["Frontend management"],
summary: "Retrieve a list of available frontends",
operationId: "AdminAPI.FrontendController.index",
security: [%{"oAuth" => ["admin:read"]}],
@@ -29,7 +29,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.FrontendOperation do
def install_operation do
%Operation{
- tags: ["Frontend managment"],
+ tags: ["Frontend management"],
summary: "Install a frontend",
operationId: "AdminAPI.FrontendController.install",
security: [%{"oAuth" => ["admin:read"]}],
@@ -51,8 +51,9 @@ defmodule Pleroma.Web.ApiSpec.Admin.FrontendOperation do
name: %Schema{type: :string},
git: %Schema{type: :string, format: :uri, nullable: true},
build_url: %Schema{type: :string, format: :uri, nullable: true},
- ref: %Schema{type: :string},
- installed: %Schema{type: :boolean}
+ ref: %Schema{type: :string, nullable: true},
+ installed: %Schema{type: :boolean},
+ installed_refs: %Schema{type: :array, items: %Schema{type: :string}}
}
}
}
diff --git a/lib/pleroma/web/api_spec/operations/admin/instance_document_operation.ex b/lib/pleroma/web/api_spec/operations/admin/instance_document_operation.ex
index fc0de49..fc0de49 100755..100644
--- a/lib/pleroma/web/api_spec/operations/admin/instance_document_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/admin/instance_document_operation.ex
diff --git a/lib/pleroma/web/api_spec/operations/admin/invite_operation.ex b/lib/pleroma/web/api_spec/operations/admin/invite_operation.ex
index e4a9ffa..e4a9ffa 100755..100644
--- a/lib/pleroma/web/api_spec/operations/admin/invite_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/admin/invite_operation.ex
diff --git a/lib/pleroma/web/api_spec/operations/admin/media_proxy_cache_operation.ex b/lib/pleroma/web/api_spec/operations/admin/media_proxy_cache_operation.ex
index 0b1eb39..0b1eb39 100755..100644
--- a/lib/pleroma/web/api_spec/operations/admin/media_proxy_cache_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/admin/media_proxy_cache_operation.ex
diff --git a/lib/pleroma/web/api_spec/operations/admin/o_auth_app_operation.ex b/lib/pleroma/web/api_spec/operations/admin/o_auth_app_operation.ex
index 1a05aff..2b2496c 100755..100644
--- a/lib/pleroma/web/api_spec/operations/admin/o_auth_app_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/admin/o_auth_app_operation.ex
@@ -17,7 +17,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.OAuthAppOperation do
def index_operation do
%Operation{
summary: "Retrieve a list of OAuth applications",
- tags: ["OAuth application managment"],
+ tags: ["OAuth application management"],
operationId: "AdminAPI.OAuthAppController.index",
security: [%{"oAuth" => ["admin:write"]}],
parameters: [
@@ -69,7 +69,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.OAuthAppOperation do
def create_operation do
%Operation{
- tags: ["OAuth application managment"],
+ tags: ["OAuth application management"],
summary: "Create an OAuth application",
operationId: "AdminAPI.OAuthAppController.create",
requestBody: request_body("Parameters", create_request()),
@@ -84,7 +84,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.OAuthAppOperation do
def update_operation do
%Operation{
- tags: ["OAuth application managment"],
+ tags: ["OAuth application management"],
summary: "Update OAuth application",
operationId: "AdminAPI.OAuthAppController.update",
parameters: [id_param() | admin_api_params()],
@@ -102,7 +102,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.OAuthAppOperation do
def delete_operation do
%Operation{
- tags: ["OAuth application managment"],
+ tags: ["OAuth application management"],
summary: "Delete OAuth application",
operationId: "AdminAPI.OAuthAppController.delete",
parameters: [id_param() | admin_api_params()],
diff --git a/lib/pleroma/web/api_spec/operations/admin/relay_operation.ex b/lib/pleroma/web/api_spec/operations/admin/relay_operation.ex
index 8b241bd..8b241bd 100755..100644
--- a/lib/pleroma/web/api_spec/operations/admin/relay_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/admin/relay_operation.ex
diff --git a/lib/pleroma/web/api_spec/operations/admin/report_operation.ex b/lib/pleroma/web/api_spec/operations/admin/report_operation.ex
index 312e091..fbb6896 100755..100644
--- a/lib/pleroma/web/api_spec/operations/admin/report_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/admin/report_operation.ex
@@ -19,7 +19,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.ReportOperation do
def index_operation do
%Operation{
- tags: ["Report managment"],
+ tags: ["Report management"],
summary: "Retrieve a list of reports",
operationId: "AdminAPI.ReportController.index",
security: [%{"oAuth" => ["admin:read:reports"]}],
@@ -69,7 +69,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.ReportOperation do
def show_operation do
%Operation{
- tags: ["Report managment"],
+ tags: ["Report management"],
summary: "Retrieve a report",
operationId: "AdminAPI.ReportController.show",
parameters: [id_param() | admin_api_params()],
@@ -83,7 +83,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.ReportOperation do
def update_operation do
%Operation{
- tags: ["Report managment"],
+ tags: ["Report management"],
summary: "Change state of specified reports",
operationId: "AdminAPI.ReportController.update",
security: [%{"oAuth" => ["admin:write:reports"]}],
@@ -99,7 +99,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.ReportOperation do
def notes_create_operation do
%Operation{
- tags: ["Report managment"],
+ tags: ["Report management"],
summary: "Add a note to the report",
operationId: "AdminAPI.ReportController.notes_create",
parameters: [id_param() | admin_api_params()],
@@ -120,7 +120,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.ReportOperation do
def notes_delete_operation do
%Operation{
- tags: ["Report managment"],
+ tags: ["Report management"],
summary: "Delete note attached to the report",
operationId: "AdminAPI.ReportController.notes_delete",
parameters: [
@@ -141,7 +141,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.ReportOperation do
end
def id_param do
- Operation.parameter(:id, :path, FlakeID, "Report ID",
+ Operation.parameter(:id, :path, FlakeID.schema(), "Report ID",
example: "9umDrYheeY451cQnEe",
required: true
)
diff --git a/lib/pleroma/web/api_spec/operations/admin/status_operation.ex b/lib/pleroma/web/api_spec/operations/admin/status_operation.ex
index 229912d..17383f1 100755..100644
--- a/lib/pleroma/web/api_spec/operations/admin/status_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/admin/status_operation.ex
@@ -70,7 +70,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.StatusOperation do
def show_operation do
%Operation{
- tags: ["Status adminitration)"],
+ tags: ["Status administration"],
summary: "Get status",
operationId: "AdminAPI.StatusController.show",
parameters: [id_param() | admin_api_params()],
@@ -84,7 +84,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.StatusOperation do
def update_operation do
%Operation{
- tags: ["Status adminitration)"],
+ tags: ["Status administration"],
summary: "Change the scope of a status",
operationId: "AdminAPI.StatusController.update",
parameters: [id_param() | admin_api_params()],
@@ -99,7 +99,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.StatusOperation do
def delete_operation do
%Operation{
- tags: ["Status adminitration)"],
+ tags: ["Status administration"],
summary: "Delete status",
operationId: "AdminAPI.StatusController.delete",
parameters: [id_param() | admin_api_params()],
@@ -143,7 +143,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.StatusOperation do
}
},
tags: %Schema{type: :string},
- is_confirmed: %Schema{type: :string}
+ is_confirmed: %Schema{type: :boolean}
}
}
end
diff --git a/lib/pleroma/web/api_spec/operations/admin/user_operation.ex b/lib/pleroma/web/api_spec/operations/admin/user_operation.ex
index a5179ac..a5179ac 100755..100644
--- a/lib/pleroma/web/api_spec/operations/admin/user_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/admin/user_operation.ex
diff --git a/lib/pleroma/web/api_spec/operations/announcement_operation.ex b/lib/pleroma/web/api_spec/operations/announcement_operation.ex
index 71be000..6f70319 100755..100644
--- a/lib/pleroma/web/api_spec/operations/announcement_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/announcement_operation.ex
@@ -15,7 +15,7 @@ defmodule Pleroma.Web.ApiSpec.AnnouncementOperation do
def index_operation do
%Operation{
- tags: ["Announcement"],
+ tags: ["Announcements"],
summary: "Retrieve a list of announcements",
operationId: "MastodonAPI.AnnouncementController.index",
security: [%{"oAuth" => []}],
@@ -28,7 +28,7 @@ defmodule Pleroma.Web.ApiSpec.AnnouncementOperation do
def mark_read_operation do
%Operation{
- tags: ["Announcement"],
+ tags: ["Announcements"],
summary: "Mark one announcement as read",
operationId: "MastodonAPI.AnnouncementController.mark_read",
security: [%{"oAuth" => ["write:accounts"]}],
diff --git a/lib/pleroma/web/api_spec/operations/app_operation.ex b/lib/pleroma/web/api_spec/operations/app_operation.ex
index dfa2237..dfa2237 100755..100644
--- a/lib/pleroma/web/api_spec/operations/app_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/app_operation.ex
diff --git a/lib/pleroma/web/api_spec/operations/chat_operation.ex b/lib/pleroma/web/api_spec/operations/chat_operation.ex
index cf6a055..f56e57a 100755..100644
--- a/lib/pleroma/web/api_spec/operations/chat_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/chat_operation.ex
@@ -137,7 +137,12 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do
"Deprecated due to no support for pagination. Using [/api/v2/pleroma/chats](#operation/ChatController.index2) instead is recommended.",
operationId: "ChatController.index",
parameters: [
- Operation.parameter(:with_muted, :query, BooleanLike, "Include chats from muted users")
+ Operation.parameter(
+ :with_muted,
+ :query,
+ BooleanLike.schema(),
+ "Include chats from muted users"
+ )
],
responses: %{
200 => Operation.response("The chats of the user", "application/json", chats_response())
@@ -156,7 +161,12 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do
summary: "Retrieve list of chats",
operationId: "ChatController.index2",
parameters: [
- Operation.parameter(:with_muted, :query, BooleanLike, "Include chats from muted users")
+ Operation.parameter(
+ :with_muted,
+ :query,
+ BooleanLike.schema(),
+ "Include chats from muted users"
+ )
| pagination_params()
],
responses: %{
diff --git a/lib/pleroma/web/api_spec/operations/conversation_operation.ex b/lib/pleroma/web/api_spec/operations/conversation_operation.ex
index 82ccf41..82ccf41 100755..100644
--- a/lib/pleroma/web/api_spec/operations/conversation_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/conversation_operation.ex
diff --git a/lib/pleroma/web/api_spec/operations/custom_emoji_operation.ex b/lib/pleroma/web/api_spec/operations/custom_emoji_operation.ex
index 77823f1..77823f1 100755..100644
--- a/lib/pleroma/web/api_spec/operations/custom_emoji_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/custom_emoji_operation.ex
diff --git a/lib/pleroma/web/api_spec/operations/directory_operation.ex b/lib/pleroma/web/api_spec/operations/directory_operation.ex
index 55752fa..2eca176 100755..100644
--- a/lib/pleroma/web/api_spec/operations/directory_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/directory_operation.ex
@@ -17,7 +17,7 @@ defmodule Pleroma.Web.ApiSpec.DirectoryOperation do
def index_operation do
%Operation{
- tags: ["Directory"],
+ tags: ["Others"],
summary: "Profile directory",
operationId: "DirectoryController.index",
parameters:
@@ -29,7 +29,7 @@ defmodule Pleroma.Web.ApiSpec.DirectoryOperation do
"Order by recent activity or account creation",
required: nil
),
- Operation.parameter(:local, :query, BooleanLike, "Include local users only")
+ Operation.parameter(:local, :query, BooleanLike.schema(), "Include local users only")
] ++ pagination_params(),
responses: %{
200 =>
diff --git a/lib/pleroma/web/api_spec/operations/domain_block_operation.ex b/lib/pleroma/web/api_spec/operations/domain_block_operation.ex
index 2340fd9..2340fd9 100755..100644
--- a/lib/pleroma/web/api_spec/operations/domain_block_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/domain_block_operation.ex
diff --git a/lib/pleroma/web/api_spec/operations/emoji_reaction_operation.ex b/lib/pleroma/web/api_spec/operations/emoji_reaction_operation.ex
index 74341d6..8d6be89 100755..100644
--- a/lib/pleroma/web/api_spec/operations/emoji_reaction_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/emoji_reaction_operation.ex
@@ -21,7 +21,7 @@ defmodule Pleroma.Web.ApiSpec.EmojiReactionOperation do
summary:
"Get an object of emoji to account mappings with accounts that reacted to the post",
parameters: [
- Operation.parameter(:id, :path, FlakeID, "Status ID", required: true),
+ Operation.parameter(:id, :path, FlakeID.schema(), "Status ID", required: true),
Operation.parameter(:emoji, :path, :string, "Filter by a single unicode emoji",
required: nil
),
@@ -45,7 +45,7 @@ defmodule Pleroma.Web.ApiSpec.EmojiReactionOperation do
tags: ["Emoji reactions"],
summary: "React to a post with a unicode emoji",
parameters: [
- Operation.parameter(:id, :path, FlakeID, "Status ID", required: true),
+ Operation.parameter(:id, :path, FlakeID.schema(), "Status ID", required: true),
Operation.parameter(:emoji, :path, :string, "A single character unicode emoji",
required: true
)
@@ -64,7 +64,7 @@ defmodule Pleroma.Web.ApiSpec.EmojiReactionOperation do
tags: ["Emoji reactions"],
summary: "Remove a reaction to a post with a unicode emoji",
parameters: [
- Operation.parameter(:id, :path, FlakeID, "Status ID", required: true),
+ Operation.parameter(:id, :path, FlakeID.schema(), "Status ID", required: true),
Operation.parameter(:emoji, :path, :string, "A single character unicode emoji",
required: true
)
diff --git a/lib/pleroma/web/api_spec/operations/filter_operation.ex b/lib/pleroma/web/api_spec/operations/filter_operation.ex
index a1700b7..a1700b7 100755..100644
--- a/lib/pleroma/web/api_spec/operations/filter_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/filter_operation.ex
diff --git a/lib/pleroma/web/api_spec/operations/follow_request_operation.ex b/lib/pleroma/web/api_spec/operations/follow_request_operation.ex
index 72dc8b5..72dc8b5 100755..100644
--- a/lib/pleroma/web/api_spec/operations/follow_request_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/follow_request_operation.ex
diff --git a/lib/pleroma/web/api_spec/operations/instance_operation.ex b/lib/pleroma/web/api_spec/operations/instance_operation.ex
index 3c4b504..b6c411c 100755..100644
--- a/lib/pleroma/web/api_spec/operations/instance_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/instance_operation.ex
@@ -13,7 +13,7 @@ defmodule Pleroma.Web.ApiSpec.InstanceOperation do
def show_operation do
%Operation{
- tags: ["Instance"],
+ tags: ["Instance misc"],
summary: "Retrieve instance information",
description: "Information about the server",
operationId: "InstanceController.show",
@@ -23,9 +23,21 @@ defmodule Pleroma.Web.ApiSpec.InstanceOperation do
}
end
+ def show2_operation do
+ %Operation{
+ tags: ["Instance misc"],
+ summary: "Retrieve instance information",
+ description: "Information about the server",
+ operationId: "InstanceController.show2",
+ responses: %{
+ 200 => Operation.response("Instance", "application/json", instance2())
+ }
+ }
+ end
+
def peers_operation do
%Operation{
- tags: ["Instance"],
+ tags: ["Instance misc"],
summary: "Retrieve list of known instances",
operationId: "InstanceController.peers",
responses: %{
@@ -38,6 +50,15 @@ defmodule Pleroma.Web.ApiSpec.InstanceOperation do
%Schema{
type: :object,
properties: %{
+ accounts: %Schema{
+ type: :object,
+ properties: %{
+ max_featured_tags: %Schema{
+ type: :integer,
+ description: "The maximum number of featured tags allowed for each account."
+ }
+ }
+ },
uri: %Schema{type: :string, description: "The domain name of the instance"},
title: %Schema{type: :string, description: "The title of the website"},
description: %Schema{
@@ -89,7 +110,7 @@ defmodule Pleroma.Web.ApiSpec.InstanceOperation do
languages: %Schema{
type: :array,
items: %Schema{type: :string},
- description: "Primary langauges of the website and its staff"
+ description: "Primary languages of the website and its staff"
},
registrations: %Schema{type: :boolean, description: "Whether registrations are enabled"},
# Extra (not present in Mastodon):
@@ -165,6 +186,184 @@ defmodule Pleroma.Web.ApiSpec.InstanceOperation do
}
end
+ defp instance2 do
+ %Schema{
+ type: :object,
+ properties: %{
+ domain: %Schema{type: :string, description: "The domain name of the instance"},
+ title: %Schema{type: :string, description: "The title of the website"},
+ version: %Schema{
+ type: :string,
+ description: "The version of Pleroma installed on the instance"
+ },
+ source_url: %Schema{
+ type: :string,
+ description: "The version of Pleroma installed on the instance"
+ },
+ description: %Schema{
+ type: :string,
+ description: "Admin-defined description of the Pleroma site"
+ },
+ usage: %Schema{
+ type: :object,
+ description: "Instance usage statistics",
+ properties: %{
+ users: %Schema{
+ type: :object,
+ description: "User count statistics",
+ properties: %{
+ active_month: %Schema{
+ type: :integer,
+ description: "Monthly active users"
+ }
+ }
+ }
+ }
+ },
+ email: %Schema{
+ type: :string,
+ description: "An email that may be contacted for any inquiries",
+ format: :email
+ },
+ urls: %Schema{
+ type: :object,
+ description: "URLs of interest for clients apps",
+ properties: %{}
+ },
+ stats: %Schema{
+ type: :object,
+ description: "Statistics about how much information the instance contains",
+ properties: %{
+ user_count: %Schema{
+ type: :integer,
+ description: "Users registered on this instance"
+ },
+ status_count: %Schema{
+ type: :integer,
+ description: "Statuses authored by users on instance"
+ },
+ domain_count: %Schema{
+ type: :integer,
+ description: "Domains federated with this instance"
+ }
+ }
+ },
+ thumbnail: %Schema{
+ type: :object,
+ properties: %{
+ url: %Schema{
+ type: :string,
+ description: "Banner image for the website",
+ nullable: true
+ }
+ }
+ },
+ languages: %Schema{
+ type: :array,
+ items: %Schema{type: :string},
+ description: "Primary languages of the website and its staff"
+ },
+ registrations: %Schema{
+ type: :object,
+ description: "Registrations-related configuration",
+ properties: %{
+ enabled: %Schema{
+ type: :boolean,
+ description: "Whether registrations are enabled"
+ },
+ approval_required: %Schema{
+ type: :boolean,
+ description: "Whether users need to be manually approved by admin"
+ }
+ }
+ },
+ configuration: %Schema{
+ type: :object,
+ description: "Instance configuration",
+ properties: %{
+ accounts: %Schema{
+ type: :object,
+ properties: %{
+ max_featured_tags: %Schema{
+ type: :integer,
+ description: "The maximum number of featured tags allowed for each account."
+ },
+ max_pinned_statuses: %Schema{
+ type: :integer,
+ description: "The maximum number of pinned statuses for each account."
+ }
+ }
+ },
+ urls: %Schema{
+ type: :object,
+ properties: %{
+ streaming: %Schema{
+ type: :string,
+ description: "Websockets address for push streaming"
+ }
+ }
+ },
+ statuses: %Schema{
+ type: :object,
+ description: "A map with poll limits for local statuses",
+ properties: %{
+ characters_reserved_per_url: %Schema{
+ type: :integer,
+ description:
+ "Each URL in a status will be assumed to be exactly this many characters."
+ },
+ max_characters: %Schema{
+ type: :integer,
+ description: "Posts character limit (CW/Subject included in the counter)"
+ },
+ max_media_attachments: %Schema{
+ type: :integer,
+ description: "Media attachment limit"
+ }
+ }
+ },
+ media_attachments: %Schema{
+ type: :object,
+ description: "A map with poll limits for media attachments",
+ properties: %{
+ image_size_limit: %Schema{
+ type: :integer,
+ description: "File size limit of uploaded images"
+ },
+ video_size_limit: %Schema{
+ type: :integer,
+ description: "File size limit of uploaded videos"
+ }
+ }
+ },
+ polls: %Schema{
+ type: :object,
+ description: "A map with poll limits for local polls",
+ properties: %{
+ max_options: %Schema{
+ type: :integer,
+ description: "Maximum number of options."
+ },
+ max_characters_per_option: %Schema{
+ type: :integer,
+ description: "Maximum number of characters per option."
+ },
+ min_expiration: %Schema{
+ type: :integer,
+ description: "Minimum expiration time (in seconds)."
+ },
+ max_expiration: %Schema{
+ type: :integer,
+ description: "Maximum expiration time (in seconds)."
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ end
+
defp array_of_domains do
%Schema{
type: :array,
diff --git a/lib/pleroma/web/api_spec/operations/list_operation.ex b/lib/pleroma/web/api_spec/operations/list_operation.ex
index 7d876ae..7d876ae 100755..100644
--- a/lib/pleroma/web/api_spec/operations/list_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/list_operation.ex
diff --git a/lib/pleroma/web/api_spec/operations/marker_operation.ex b/lib/pleroma/web/api_spec/operations/marker_operation.ex
index 4dfdeb4..4dfdeb4 100755..100644
--- a/lib/pleroma/web/api_spec/operations/marker_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/marker_operation.ex
diff --git a/lib/pleroma/web/api_spec/operations/media_operation.ex b/lib/pleroma/web/api_spec/operations/media_operation.ex
index e6df212..e6df212 100755..100644
--- a/lib/pleroma/web/api_spec/operations/media_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/media_operation.ex
diff --git a/lib/pleroma/web/api_spec/operations/notification_operation.ex b/lib/pleroma/web/api_spec/operations/notification_operation.ex
index 56aa129..757429d 100755..100644
--- a/lib/pleroma/web/api_spec/operations/notification_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/notification_operation.ex
@@ -62,7 +62,7 @@ defmodule Pleroma.Web.ApiSpec.NotificationOperation do
Operation.parameter(
:with_muted,
:query,
- BooleanLike,
+ BooleanLike.schema(),
"Include the notifications from muted users"
)
] ++ pagination_params(),
diff --git a/lib/pleroma/web/api_spec/operations/pleroma_account_operation.ex b/lib/pleroma/web/api_spec/operations/pleroma_account_operation.ex
index 5375c5b..7340653 100755..100644
--- a/lib/pleroma/web/api_spec/operations/pleroma_account_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/pleroma_account_operation.ex
@@ -142,7 +142,7 @@ defmodule Pleroma.Web.ApiSpec.PleromaAccountOperation do
end
defp id_param do
- Operation.parameter(:id, :path, FlakeID, "Account ID",
+ Operation.parameter(:id, :path, FlakeID.schema(), "Account ID",
example: "9umDrYheeY451cQnEe",
required: true
)
diff --git a/lib/pleroma/web/api_spec/operations/pleroma_app_operation.ex b/lib/pleroma/web/api_spec/operations/pleroma_app_operation.ex
index 9f8df6c..9f8df6c 100755..100644
--- a/lib/pleroma/web/api_spec/operations/pleroma_app_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/pleroma_app_operation.ex
diff --git a/lib/pleroma/web/api_spec/operations/pleroma_backup_operation.ex b/lib/pleroma/web/api_spec/operations/pleroma_backup_operation.ex
index 45fa2b0..400f382 100755..100644
--- a/lib/pleroma/web/api_spec/operations/pleroma_backup_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/pleroma_backup_operation.ex
@@ -64,7 +64,13 @@ defmodule Pleroma.Web.ApiSpec.PleromaBackupOperation do
content_type: %Schema{type: :string},
file_name: %Schema{type: :string},
file_size: %Schema{type: :integer},
- processed: %Schema{type: :boolean}
+ processed: %Schema{type: :boolean, description: "whether this backup has succeeded"},
+ state: %Schema{
+ type: :string,
+ description: "the state of the backup",
+ enum: ["pending", "running", "complete", "failed"]
+ },
+ processed_number: %Schema{type: :integer, description: "the number of records processed"}
},
example: %{
"content_type" => "application/zip",
@@ -72,7 +78,9 @@ defmodule Pleroma.Web.ApiSpec.PleromaBackupOperation do
"https://cofe.fe:4000/media/backups/archive-foobar-20200908T164207-Yr7vuT5Wycv-sN3kSN2iJ0k-9pMo60j9qmvRCdDqIew.zip",
"file_size" => 4105,
"inserted_at" => "2020-09-08T16:42:07.000Z",
- "processed" => true
+ "processed" => true,
+ "state" => "complete",
+ "processed_number" => 20
}
}
end
diff --git a/lib/pleroma/web/api_spec/operations/pleroma_bookmark_folder_operation.ex b/lib/pleroma/web/api_spec/operations/pleroma_bookmark_folder_operation.ex
new file mode 100644
index 0000000..eaa6831
--- /dev/null
+++ b/lib/pleroma/web/api_spec/operations/pleroma_bookmark_folder_operation.ex
@@ -0,0 +1,125 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2024 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ApiSpec.PleromaBookmarkFolderOperation do
+ alias OpenApiSpex.Operation
+ alias OpenApiSpex.Schema
+ alias Pleroma.Web.ApiSpec.Schemas.ApiError
+ alias Pleroma.Web.ApiSpec.Schemas.BookmarkFolder
+ alias Pleroma.Web.ApiSpec.Schemas.FlakeID
+
+ import Pleroma.Web.ApiSpec.Helpers
+
+ @spec open_api_operation(any()) :: any()
+ def open_api_operation(action) do
+ operation = String.to_existing_atom("#{action}_operation")
+ apply(__MODULE__, operation, [])
+ end
+
+ def index_operation do
+ %Operation{
+ tags: ["Bookmark folders"],
+ summary: "All bookmark folders",
+ security: [%{"oAuth" => ["read:bookmarks"]}],
+ operationId: "PleromaAPI.BookmarkFolderController.index",
+ responses: %{
+ 200 =>
+ Operation.response("Array of Bookmark Folders", "application/json", %Schema{
+ type: :array,
+ items: BookmarkFolder
+ })
+ }
+ }
+ end
+
+ def create_operation do
+ %Operation{
+ tags: ["Bookmark folders"],
+ summary: "Create a bookmark folder",
+ security: [%{"oAuth" => ["write:bookmarks"]}],
+ operationId: "PleromaAPI.BookmarkFolderController.create",
+ requestBody: request_body("Parameters", create_request(), required: true),
+ responses: %{
+ 200 => Operation.response("Bookmark Folder", "application/json", BookmarkFolder),
+ 422 => Operation.response("Error", "application/json", ApiError)
+ }
+ }
+ end
+
+ def update_operation do
+ %Operation{
+ tags: ["Bookmark folders"],
+ summary: "Update a bookmark folder",
+ security: [%{"oAuth" => ["write:bookmarks"]}],
+ operationId: "PleromaAPI.BookmarkFolderController.update",
+ parameters: [id_param()],
+ requestBody: request_body("Parameters", update_request(), required: true),
+ responses: %{
+ 200 => Operation.response("Bookmark Folder", "application/json", BookmarkFolder),
+ 403 => Operation.response("Forbidden", "application/json", ApiError),
+ 404 => Operation.response("Not Found", "application/json", ApiError),
+ 422 => Operation.response("Error", "application/json", ApiError)
+ }
+ }
+ end
+
+ def delete_operation do
+ %Operation{
+ tags: ["Bookmark folders"],
+ summary: "Delete a bookmark folder",
+ security: [%{"oAuth" => ["write:bookmarks"]}],
+ operationId: "PleromaAPI.BookmarkFolderController.delete",
+ parameters: [id_param()],
+ responses: %{
+ 200 => Operation.response("Bookmark Folder", "application/json", BookmarkFolder),
+ 403 => Operation.response("Forbidden", "application/json", ApiError),
+ 404 => Operation.response("Not Found", "application/json", ApiError)
+ }
+ }
+ end
+
+ defp create_request do
+ %Schema{
+ title: "BookmarkFolderCreateRequest",
+ type: :object,
+ properties: %{
+ name: %Schema{
+ type: :string,
+ description: "Folder name"
+ },
+ emoji: %Schema{
+ type: :string,
+ nullable: true,
+ description: "Folder emoji"
+ }
+ }
+ }
+ end
+
+ defp update_request do
+ %Schema{
+ title: "BookmarkFolderUpdateRequest",
+ type: :object,
+ properties: %{
+ name: %Schema{
+ type: :string,
+ nullable: true,
+ description: "Folder name"
+ },
+ emoji: %Schema{
+ type: :string,
+ nullable: true,
+ description: "Folder emoji"
+ }
+ }
+ }
+ end
+
+ def id_param do
+ Operation.parameter(:id, :path, FlakeID.schema(), "Bookmark Folder ID",
+ example: "9umDrYheeY451cQnEe",
+ required: true
+ )
+ end
+end
diff --git a/lib/pleroma/web/api_spec/operations/pleroma_conversation_operation.ex b/lib/pleroma/web/api_spec/operations/pleroma_conversation_operation.ex
index 89f0e13..89f0e13 100755..100644
--- a/lib/pleroma/web/api_spec/operations/pleroma_conversation_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/pleroma_conversation_operation.ex
diff --git a/lib/pleroma/web/api_spec/operations/pleroma_emoji_file_operation.ex b/lib/pleroma/web/api_spec/operations/pleroma_emoji_file_operation.ex
index d09c1c1..b05bad1 100755..100644
--- a/lib/pleroma/web/api_spec/operations/pleroma_emoji_file_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/pleroma_emoji_file_operation.ex
@@ -133,7 +133,11 @@ defmodule Pleroma.Web.ApiSpec.PleromaEmojiFileOperation do
defp files_object do
%Schema{
type: :object,
- additionalProperties: %Schema{type: :string},
+ additionalProperties: %Schema{
+ type: :string,
+ description: "Filename of the emoji",
+ extensions: %{"x-additionalPropertiesName": "Emoji name"}
+ },
description: "Object with emoji names as keys and filenames as values"
}
end
diff --git a/lib/pleroma/web/api_spec/operations/pleroma_emoji_pack_operation.ex b/lib/pleroma/web/api_spec/operations/pleroma_emoji_pack_operation.ex
index 6add3ff..efa36ff 100755..100644
--- a/lib/pleroma/web/api_spec/operations/pleroma_emoji_pack_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/pleroma_emoji_pack_operation.ex
@@ -227,13 +227,29 @@ defmodule Pleroma.Web.ApiSpec.PleromaEmojiPackOperation do
defp emoji_packs_response do
Operation.response(
- "Object with pack names as keys and pack contents as values",
+ "Emoji packs and the count",
"application/json",
%Schema{
type: :object,
- additionalProperties: emoji_pack(),
+ properties: %{
+ packs: %Schema{
+ type: :object,
+ description: "Object with pack names as keys and pack contents as values",
+ additionalProperties: %Schema{
+ emoji_pack()
+ | extensions: %{"x-additionalPropertiesName": "Pack name"}
+ }
+ },
+ count: %Schema{
+ type: :integer,
+ description: "Number of emoji packs"
+ }
+ },
example: %{
- "emojos" => emoji_pack().example
+ "packs" => %{
+ "emojos" => emoji_pack().example
+ },
+ "count" => 1
}
}
)
@@ -274,7 +290,11 @@ defmodule Pleroma.Web.ApiSpec.PleromaEmojiPackOperation do
defp files_object do
%Schema{
type: :object,
- additionalProperties: %Schema{type: :string},
+ additionalProperties: %Schema{
+ type: :string,
+ description: "Filename",
+ extensions: %{"x-additionalPropertiesName": "Emoji name"}
+ },
description: "Object with emoji names as keys and filenames as values"
}
end
diff --git a/lib/pleroma/web/api_spec/operations/pleroma_instances_operation.ex b/lib/pleroma/web/api_spec/operations/pleroma_instances_operation.ex
index 82db4e1..e9319f3 100755..100644
--- a/lib/pleroma/web/api_spec/operations/pleroma_instances_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/pleroma_instances_operation.ex
@@ -13,7 +13,7 @@ defmodule Pleroma.Web.ApiSpec.PleromaInstancesOperation do
def show_operation do
%Operation{
- tags: ["Instance"],
+ tags: ["Instance misc"],
summary: "Retrieve federation status",
description: "Information about instances deemed unreachable by the server",
operationId: "PleromaInstances.show",
diff --git a/lib/pleroma/web/api_spec/operations/pleroma_mascot_operation.ex b/lib/pleroma/web/api_spec/operations/pleroma_mascot_operation.ex
index 775e272..775e272 100755..100644
--- a/lib/pleroma/web/api_spec/operations/pleroma_mascot_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/pleroma_mascot_operation.ex
diff --git a/lib/pleroma/web/api_spec/operations/pleroma_notification_operation.ex b/lib/pleroma/web/api_spec/operations/pleroma_notification_operation.ex
index a994345..a994345 100755..100644
--- a/lib/pleroma/web/api_spec/operations/pleroma_notification_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/pleroma_notification_operation.ex
diff --git a/lib/pleroma/web/api_spec/operations/pleroma_report_operation.ex b/lib/pleroma/web/api_spec/operations/pleroma_report_operation.ex
index 9bc1877..9bc1877 100755..100644
--- a/lib/pleroma/web/api_spec/operations/pleroma_report_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/pleroma_report_operation.ex
diff --git a/lib/pleroma/web/api_spec/operations/pleroma_scrobble_operation.ex b/lib/pleroma/web/api_spec/operations/pleroma_scrobble_operation.ex
index b6273bf..f595583 100755..100644
--- a/lib/pleroma/web/api_spec/operations/pleroma_scrobble_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/pleroma_scrobble_operation.ex
@@ -22,7 +22,8 @@ defmodule Pleroma.Web.ApiSpec.PleromaScrobbleOperation do
summary: "Creates a new Listen activity for an account",
security: [%{"oAuth" => ["write"]}],
operationId: "PleromaAPI.ScrobbleController.create",
- requestBody: request_body("Parameters", create_request(), requried: true),
+ deprecated: true,
+ requestBody: request_body("Parameters", create_request(), required: true),
responses: %{
200 => Operation.response("Scrobble", "application/json", scrobble())
}
@@ -34,6 +35,7 @@ defmodule Pleroma.Web.ApiSpec.PleromaScrobbleOperation do
tags: ["Scrobbles"],
summary: "Requests a list of current and recent Listen activities for an account",
operationId: "PleromaAPI.ScrobbleController.index",
+ deprecated: true,
parameters: [
%Reference{"$ref": "#/components/parameters/accountIdOrNickname"} | pagination_params()
],
@@ -57,6 +59,7 @@ defmodule Pleroma.Web.ApiSpec.PleromaScrobbleOperation do
album: %Schema{type: :string, description: "The album of the media playing"},
artist: %Schema{type: :string, description: "The artist of the media playing"},
length: %Schema{type: :integer, description: "The length of the media playing"},
+ externalLink: %Schema{type: :string, description: "A URL referencing the media playing"},
visibility: %Schema{
allOf: [VisibilityScope],
default: "public",
@@ -67,7 +70,8 @@ defmodule Pleroma.Web.ApiSpec.PleromaScrobbleOperation do
"title" => "Some Title",
"artist" => "Some Artist",
"album" => "Some Album",
- "length" => 180_000
+ "length" => 180_000,
+ "externalLink" => "https://www.last.fm/music/Some+Artist/_/Some+Title"
}
}
end
@@ -81,6 +85,7 @@ defmodule Pleroma.Web.ApiSpec.PleromaScrobbleOperation do
title: %Schema{type: :string, description: "The title of the media playing"},
album: %Schema{type: :string, description: "The album of the media playing"},
artist: %Schema{type: :string, description: "The artist of the media playing"},
+ externalLink: %Schema{type: :string, description: "A URL referencing the media playing"},
length: %Schema{
type: :integer,
description: "The length of the media playing",
@@ -95,6 +100,7 @@ defmodule Pleroma.Web.ApiSpec.PleromaScrobbleOperation do
"artist" => "Some Artist",
"album" => "Some Album",
"length" => 180_000,
+ "externalLink" => "https://www.last.fm/music/Some+Artist/_/Some+Title",
"created_at" => "2019-09-28T12:40:45.000Z"
}
}
diff --git a/lib/pleroma/web/api_spec/operations/pleroma_settings_operation.ex b/lib/pleroma/web/api_spec/operations/pleroma_settings_operation.ex
index e2cef4f..e2cef4f 100755..100644
--- a/lib/pleroma/web/api_spec/operations/pleroma_settings_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/pleroma_settings_operation.ex
diff --git a/lib/pleroma/web/api_spec/operations/pleroma_status_operation.ex b/lib/pleroma/web/api_spec/operations/pleroma_status_operation.ex
new file mode 100644
index 0000000..77c6049
--- /dev/null
+++ b/lib/pleroma/web/api_spec/operations/pleroma_status_operation.ex
@@ -0,0 +1,45 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ApiSpec.PleromaStatusOperation do
+ alias OpenApiSpex.Operation
+ alias Pleroma.Web.ApiSpec.Schemas.ApiError
+ alias Pleroma.Web.ApiSpec.Schemas.FlakeID
+ alias Pleroma.Web.ApiSpec.StatusOperation
+
+ import Pleroma.Web.ApiSpec.Helpers
+
+ def open_api_operation(action) do
+ operation = String.to_existing_atom("#{action}_operation")
+ apply(__MODULE__, operation, [])
+ end
+
+ def quotes_operation do
+ %Operation{
+ tags: ["Retrieve status information"],
+ summary: "Quoted by",
+ description: "View quotes for a given status",
+ operationId: "PleromaAPI.StatusController.quotes",
+ parameters: [id_param() | pagination_params()],
+ security: [%{"oAuth" => ["read:statuses"]}],
+ responses: %{
+ 200 =>
+ Operation.response(
+ "Array of Status",
+ "application/json",
+ StatusOperation.array_of_statuses()
+ ),
+ 403 => Operation.response("Forbidden", "application/json", ApiError),
+ 404 => Operation.response("Not Found", "application/json", ApiError)
+ }
+ }
+ end
+
+ def id_param do
+ Operation.parameter(:id, :path, FlakeID.schema(), "Status ID",
+ example: "9umDrYheeY451cQnEe",
+ required: true
+ )
+ end
+end
diff --git a/lib/pleroma/web/api_spec/operations/poll_operation.ex b/lib/pleroma/web/api_spec/operations/poll_operation.ex
index efd784f..6dd2517 100755..100644
--- a/lib/pleroma/web/api_spec/operations/poll_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/poll_operation.ex
@@ -47,7 +47,7 @@ defmodule Pleroma.Web.ApiSpec.PollOperation do
end
defp id_param do
- Operation.parameter(:id, :path, FlakeID, "Poll ID",
+ Operation.parameter(:id, :path, FlakeID.schema(), "Poll ID",
example: "123",
required: true
)
diff --git a/lib/pleroma/web/api_spec/operations/report_operation.ex b/lib/pleroma/web/api_spec/operations/report_operation.ex
index c74ac7d..c74ac7d 100755..100644
--- a/lib/pleroma/web/api_spec/operations/report_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/report_operation.ex
diff --git a/lib/pleroma/web/api_spec/operations/scheduled_activity_operation.ex b/lib/pleroma/web/api_spec/operations/scheduled_activity_operation.ex
index 802d3b6..c7ed02f 100755..100644
--- a/lib/pleroma/web/api_spec/operations/scheduled_activity_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/scheduled_activity_operation.ex
@@ -88,7 +88,7 @@ defmodule Pleroma.Web.ApiSpec.ScheduledActivityOperation do
end
defp id_param do
- Operation.parameter(:id, :path, FlakeID, "Poll ID",
+ Operation.parameter(:id, :path, FlakeID.schema(), "Poll ID",
example: "123",
required: true
)
diff --git a/lib/pleroma/web/api_spec/operations/search_operation.ex b/lib/pleroma/web/api_spec/operations/search_operation.ex
index 1a7e49b..539743b 100755..100644
--- a/lib/pleroma/web/api_spec/operations/search_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/search_operation.ex
@@ -70,7 +70,7 @@ defmodule Pleroma.Web.ApiSpec.SearchOperation do
Operation.parameter(
:account_id,
:query,
- FlakeID,
+ FlakeID.schema(),
"If provided, statuses returned will be authored only by this account"
),
Operation.parameter(
@@ -116,7 +116,7 @@ defmodule Pleroma.Web.ApiSpec.SearchOperation do
Operation.parameter(
:account_id,
:query,
- FlakeID,
+ FlakeID.schema(),
"If provided, statuses returned will be authored only by this account"
),
Operation.parameter(
diff --git a/lib/pleroma/web/api_spec/operations/status_operation.ex b/lib/pleroma/web/api_spec/operations/status_operation.ex
index e921128..1717c68 100755..100644
--- a/lib/pleroma/web/api_spec/operations/status_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/status_operation.ex
@@ -39,7 +39,7 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
Operation.parameter(
:with_muted,
:query,
- BooleanLike,
+ BooleanLike.schema(),
"Include reactions from muted acccounts."
)
],
@@ -82,7 +82,7 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
Operation.parameter(
:with_muted,
:query,
- BooleanLike,
+ BooleanLike.schema(),
"Include reactions from muted acccounts."
)
],
@@ -256,6 +256,18 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
description: "Privately bookmark a status",
operationId: "StatusController.bookmark",
parameters: [id_param()],
+ requestBody:
+ request_body("Parameters", %Schema{
+ title: "StatusUpdateRequest",
+ type: :object,
+ properties: %{
+ folder_id: %Schema{
+ nullable: true,
+ allOf: [FlakeID],
+ description: "ID of bookmarks folder, if any"
+ }
+ }
+ }),
responses: %{
200 => status_response()
}
@@ -430,7 +442,15 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
summary: "Bookmarked statuses",
description: "Statuses the user has bookmarked",
operationId: "StatusController.bookmarks",
- parameters: pagination_params(),
+ parameters: [
+ Operation.parameter(
+ :folder_id,
+ :query,
+ FlakeID.schema(),
+ "If provided, only display bookmarks from given folder"
+ )
+ | pagination_params()
+ ],
security: [%{"oAuth" => ["read:bookmarks"]}],
responses: %{
200 => Operation.response("Array of Statuses", "application/json", array_of_statuses())
@@ -440,7 +460,7 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
def show_history_operation do
%Operation{
- tags: ["Retrieve status history"],
+ tags: ["Retrieve status information"],
summary: "Status history",
description: "View history of a status",
operationId: "StatusController.show_history",
@@ -457,7 +477,7 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
def show_source_operation do
%Operation{
- tags: ["Retrieve status source"],
+ tags: ["Retrieve status information"],
summary: "Status source",
description: "View source of a status",
operationId: "StatusController.show_source",
@@ -474,7 +494,7 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
def update_operation do
%Operation{
- tags: ["Update status"],
+ tags: ["Status actions"],
summary: "Update status",
description: "Change the content of a status",
operationId: "StatusController.update",
@@ -534,7 +554,7 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
format: :"date-time",
nullable: true,
description:
- "ISO 8601 Datetime at which to schedule a status. Providing this paramter will cause ScheduledStatus to be returned instead of Status. Must be at least 5 minutes in the future."
+ "ISO 8601 Datetime at which to schedule a status. Providing this parameter will cause ScheduledStatus to be returned instead of Status. Must be at least 5 minutes in the future."
},
language: %Schema{
type: :string,
@@ -546,7 +566,7 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
allOf: [BooleanLike],
nullable: true,
description:
- "If set to `true` the post won't be actually posted, but the status entitiy would still be rendered back. This could be useful for previewing rich text/custom emoji, for example"
+ "If set to `true` the post won't be actually posted, but the status entity would still be rendered back. This could be useful for previewing rich text/custom emoji, for example"
},
content_type: %Schema{
type: :string,
@@ -581,6 +601,11 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
type: :string,
description:
"Will reply to a given conversation, addressing only the people who are part of the recipient set of that conversation. Sets the visibility to `direct`."
+ },
+ quote_id: %Schema{
+ nullable: true,
+ allOf: [FlakeID],
+ description: "ID of the status being quoted, if any"
}
},
example: %{
@@ -680,7 +705,7 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
end
def id_param do
- Operation.parameter(:id, :path, FlakeID, "Status ID",
+ Operation.parameter(:id, :path, FlakeID.schema(), "Status ID",
example: "9umDrYheeY451cQnEe",
required: true
)
diff --git a/lib/pleroma/web/api_spec/operations/streaming_operation.ex b/lib/pleroma/web/api_spec/operations/streaming_operation.ex
new file mode 100644
index 0000000..b580bc2
--- /dev/null
+++ b/lib/pleroma/web/api_spec/operations/streaming_operation.ex
@@ -0,0 +1,464 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ApiSpec.StreamingOperation do
+ alias OpenApiSpex.Operation
+ alias OpenApiSpex.Response
+ alias OpenApiSpex.Schema
+ alias Pleroma.Web.ApiSpec.NotificationOperation
+ alias Pleroma.Web.ApiSpec.Schemas.Chat
+ alias Pleroma.Web.ApiSpec.Schemas.Conversation
+ alias Pleroma.Web.ApiSpec.Schemas.FlakeID
+ alias Pleroma.Web.ApiSpec.Schemas.Status
+
+ require Pleroma.Constants
+
+ @spec open_api_operation(atom) :: Operation.t()
+ def open_api_operation(action) do
+ operation = String.to_existing_atom("#{action}_operation")
+ apply(__MODULE__, operation, [])
+ end
+
+ @spec streaming_operation() :: Operation.t()
+ def streaming_operation do
+ %Operation{
+ tags: ["Timelines"],
+ summary: "Establish streaming connection",
+ description: """
+ Receive statuses in real-time via WebSocket.
+
+ You can specify the access token on the query string or through the `sec-websocket-protocol` header. Using
+ the query string to authenticate is considered unsafe and should not be used unless you have to (e.g. to maintain
+ your client's compatibility with Mastodon).
+
+ You may specify a stream on the query string. If you do so and you are connecting to a stream that requires logged-in users,
+ you must specify the access token at the time of the connection (i.e. via query string or header).
+
+ Otherwise, you have the option to authenticate after you have established the connection through client-sent events.
+
+ The "Request body" section below describes what events clients can send through WebSocket, and the "Responses" section
+ describes what events server will send through WebSocket.
+ """,
+ security: [%{"oAuth" => ["read:statuses", "read:notifications"]}],
+ operationId: "WebsocketHandler.streaming",
+ parameters:
+ [
+ Operation.parameter(:connection, :header, %Schema{type: :string}, "connection header",
+ required: true
+ ),
+ Operation.parameter(:upgrade, :header, %Schema{type: :string}, "upgrade header",
+ required: true
+ ),
+ Operation.parameter(
+ :"sec-websocket-key",
+ :header,
+ %Schema{type: :string},
+ "sec-websocket-key header",
+ required: true
+ ),
+ Operation.parameter(
+ :"sec-websocket-version",
+ :header,
+ %Schema{type: :string},
+ "sec-websocket-version header",
+ required: true
+ )
+ ] ++ stream_params() ++ access_token_params(),
+ requestBody: request_body("Client-sent events", client_sent_events()),
+ responses: %{
+ 101 => switching_protocols_response(),
+ 200 =>
+ Operation.response(
+ "Server-sent events",
+ "application/json",
+ server_sent_events()
+ )
+ }
+ }
+ end
+
+ defp stream_params do
+ stream_specifier()
+ |> Enum.map(fn {name, schema} ->
+ Operation.parameter(name, :query, schema, get_schema(schema).description)
+ end)
+ end
+
+ defp access_token_params do
+ [
+ Operation.parameter(:access_token, :query, token(), token().description),
+ Operation.parameter(:"sec-websocket-protocol", :header, token(), token().description)
+ ]
+ end
+
+ defp switching_protocols_response do
+ %Response{
+ description: "Switching protocols",
+ headers: %{
+ "connection" => %OpenApiSpex.Header{required: true},
+ "upgrade" => %OpenApiSpex.Header{required: true},
+ "sec-websocket-accept" => %OpenApiSpex.Header{required: true}
+ }
+ }
+ end
+
+ defp server_sent_events do
+ %Schema{
+ oneOf: [
+ update_event(),
+ status_update_event(),
+ notification_event(),
+ chat_update_event(),
+ follow_relationships_update_event(),
+ conversation_event(),
+ delete_event(),
+ pleroma_respond_event()
+ ]
+ }
+ end
+
+ defp stream do
+ %Schema{
+ type: :array,
+ title: "Stream",
+ description: """
+ The stream identifier.
+ The first item is the name of the stream. If the stream needs a differentiator, the second item will be the corresponding identifier.
+ Currently, for the following stream types, there is a second element in the array:
+
+ - `list`: The second element is the id of the list, as a string.
+ - `hashtag`: The second element is the name of the hashtag.
+ - `public:remote:media` and `public:remote`: The second element is the domain of the corresponding instance.
+ """,
+ maxItems: 2,
+ minItems: 1,
+ items: %Schema{type: :string},
+ example: ["hashtag", "mew"]
+ }
+ end
+
+ defp get_schema(%Schema{} = schema), do: schema
+ defp get_schema(schema), do: schema.schema
+
+ defp server_sent_event_helper(name, description, type, payload, opts \\ []) do
+ payload_type = Keyword.get(opts, :payload_type, :json)
+ has_stream = Keyword.get(opts, :has_stream, true)
+
+ stream_properties =
+ if has_stream do
+ %{stream: stream()}
+ else
+ %{}
+ end
+
+ stream_example = if has_stream, do: %{"stream" => get_schema(stream()).example}, else: %{}
+
+ stream_required = if has_stream, do: [:stream], else: []
+
+ payload_schema =
+ if payload_type == :json do
+ %Schema{
+ title: "Event payload",
+ description: "JSON-encoded string of #{get_schema(payload).title}",
+ allOf: [payload]
+ }
+ else
+ payload
+ end
+
+ payload_example =
+ if payload_type == :json do
+ get_schema(payload).example |> Jason.encode!()
+ else
+ get_schema(payload).example
+ end
+
+ %Schema{
+ type: :object,
+ title: name,
+ description: description,
+ required: [:event, :payload] ++ stream_required,
+ properties:
+ %{
+ event: %Schema{
+ title: "Event type",
+ description: "Type of the event.",
+ type: :string,
+ required: true,
+ enum: [type]
+ },
+ payload: payload_schema
+ }
+ |> Map.merge(stream_properties),
+ example:
+ %{
+ "event" => type,
+ "payload" => payload_example
+ }
+ |> Map.merge(stream_example)
+ }
+ end
+
+ defp update_event do
+ server_sent_event_helper("New status", "A newly-posted status.", "update", Status)
+ end
+
+ defp status_update_event do
+ server_sent_event_helper("Edit", "A status that was just edited", "status.update", Status)
+ end
+
+ defp notification_event do
+ server_sent_event_helper(
+ "Notification",
+ "A new notification.",
+ "notification",
+ NotificationOperation.notification()
+ )
+ end
+
+ defp follow_relationships_update_event do
+ server_sent_event_helper(
+ "Follow relationships update",
+ "An update to follow relationships.",
+ "pleroma:follow_relationships_update",
+ %Schema{
+ type: :object,
+ title: "Follow relationships update",
+ required: [:state, :follower, :following],
+ properties: %{
+ state: %Schema{
+ type: :string,
+ description: "Follow state of the relationship.",
+ enum: ["follow_pending", "follow_accept", "follow_reject", "unfollow"]
+ },
+ follower: %Schema{
+ type: :object,
+ description: "Information about the follower.",
+ required: [:id, :follower_count, :following_count],
+ properties: %{
+ id: FlakeID,
+ follower_count: %Schema{type: :integer},
+ following_count: %Schema{type: :integer}
+ }
+ },
+ following: %Schema{
+ type: :object,
+ description: "Information about the following person.",
+ required: [:id, :follower_count, :following_count],
+ properties: %{
+ id: FlakeID,
+ follower_count: %Schema{type: :integer},
+ following_count: %Schema{type: :integer}
+ }
+ }
+ },
+ example: %{
+ "state" => "follow_pending",
+ "follower" => %{
+ "id" => "someUser1",
+ "follower_count" => 1,
+ "following_count" => 1
+ },
+ "following" => %{
+ "id" => "someUser2",
+ "follower_count" => 1,
+ "following_count" => 1
+ }
+ }
+ }
+ )
+ end
+
+ defp chat_update_event do
+ server_sent_event_helper(
+ "Chat update",
+ "A new chat message.",
+ "pleroma:chat_update",
+ Chat
+ )
+ end
+
+ defp conversation_event do
+ server_sent_event_helper(
+ "Conversation update",
+ "An update about a conversation",
+ "conversation",
+ Conversation
+ )
+ end
+
+ defp delete_event do
+ server_sent_event_helper(
+ "Delete",
+ "A status that was just deleted.",
+ "delete",
+ %Schema{
+ type: :string,
+ title: "Status id",
+ description: "Id of the deleted status",
+ allOf: [FlakeID],
+ example: "some-opaque-id"
+ },
+ payload_type: :string,
+ has_stream: false
+ )
+ end
+
+ defp pleroma_respond_event do
+ server_sent_event_helper(
+ "Server response",
+ "A response to a client-sent event.",
+ "pleroma:respond",
+ %Schema{
+ type: :object,
+ title: "Results",
+ required: [:result, :type],
+ properties: %{
+ result: %Schema{
+ type: :string,
+ title: "Result of the request",
+ enum: ["success", "error", "ignored"]
+ },
+ error: %Schema{
+ type: :string,
+ title: "Error code",
+ description: "An error identifier. Only appears if `result` is `error`."
+ },
+ type: %Schema{
+ type: :string,
+ description: "Type of the request."
+ }
+ },
+ example: %{"result" => "success", "type" => "pleroma:authenticate"}
+ },
+ has_stream: false
+ )
+ end
+
+ defp client_sent_events do
+ %Schema{
+ oneOf: [
+ subscribe_event(),
+ unsubscribe_event(),
+ authenticate_event()
+ ]
+ }
+ end
+
+ defp request_body(description, schema, opts \\ []) do
+ %OpenApiSpex.RequestBody{
+ description: description,
+ content: %{
+ "application/json" => %OpenApiSpex.MediaType{
+ schema: schema,
+ example: opts[:example],
+ examples: opts[:examples]
+ }
+ }
+ }
+ end
+
+ defp client_sent_event_helper(name, description, type, properties, opts) do
+ required = opts[:required] || []
+
+ %Schema{
+ type: :object,
+ title: name,
+ required: [:type] ++ required,
+ description: description,
+ properties:
+ %{
+ type: %Schema{type: :string, enum: [type], description: "Type of the event."}
+ }
+ |> Map.merge(properties),
+ example: opts[:example]
+ }
+ end
+
+ defp subscribe_event do
+ client_sent_event_helper(
+ "Subscribe",
+ "Subscribe to a stream.",
+ "subscribe",
+ stream_specifier(),
+ required: [:stream],
+ example: %{"type" => "subscribe", "stream" => "list", "list" => "1"}
+ )
+ end
+
+ defp unsubscribe_event do
+ client_sent_event_helper(
+ "Unsubscribe",
+ "Unsubscribe from a stream.",
+ "unsubscribe",
+ stream_specifier(),
+ required: [:stream],
+ example: %{
+ "type" => "unsubscribe",
+ "stream" => "public:remote:media",
+ "instance" => "example.org"
+ }
+ )
+ end
+
+ defp authenticate_event do
+ client_sent_event_helper(
+ "Authenticate",
+ "Authenticate via an access token.",
+ "pleroma:authenticate",
+ %{
+ token: token()
+ },
+ required: [:token]
+ )
+ end
+
+ defp token do
+ %Schema{
+ type: :string,
+ description: "An OAuth access token with corresponding permissions.",
+ example: "some token"
+ }
+ end
+
+ defp stream_specifier do
+ %{
+ stream: %Schema{
+ type: :string,
+ description: "The name of the stream.",
+ enum:
+ Pleroma.Constants.public_streams() ++
+ [
+ "public:remote",
+ "public:remote:media",
+ "user",
+ "user:pleroma_chat",
+ "user:notification",
+ "direct",
+ "list",
+ "hashtag"
+ ]
+ },
+ list: %Schema{
+ type: :string,
+ title: "List id",
+ description: "The id of the list. Required when `stream` is `list`.",
+ example: "some-id"
+ },
+ tag: %Schema{
+ type: :string,
+ title: "Hashtag name",
+ description: "The name of the hashtag. Required when `stream` is `hashtag`.",
+ example: "mew"
+ },
+ instance: %Schema{
+ type: :string,
+ title: "Domain name",
+ description:
+ "Domain name of the instance. Required when `stream` is `public:remote` or `public:remote:media`.",
+ example: "example.org"
+ }
+ }
+ end
+end
diff --git a/lib/pleroma/web/api_spec/operations/subscription_operation.ex b/lib/pleroma/web/api_spec/operations/subscription_operation.ex
index c53ec29..c53ec29 100755..100644
--- a/lib/pleroma/web/api_spec/operations/subscription_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/subscription_operation.ex
diff --git a/lib/pleroma/web/api_spec/operations/timeline_operation.ex b/lib/pleroma/web/api_spec/operations/timeline_operation.ex
index fbe3f76..f55e598 100755..100644
--- a/lib/pleroma/web/api_spec/operations/timeline_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/timeline_operation.ex
@@ -176,7 +176,12 @@ defmodule Pleroma.Web.ApiSpec.TimelineOperation do
end
defp with_muted_param do
- Operation.parameter(:with_muted, :query, BooleanLike, "Include activities by muted users")
+ Operation.parameter(
+ :with_muted,
+ :query,
+ BooleanLike.schema(),
+ "Include activities by muted users"
+ )
end
defp exclude_visibilities_param do
diff --git a/lib/pleroma/web/api_spec/operations/twitter_util_operation.ex b/lib/pleroma/web/api_spec/operations/twitter_util_operation.ex
index 29df03e..724d873 100755..100644
--- a/lib/pleroma/web/api_spec/operations/twitter_util_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/twitter_util_operation.ex
@@ -17,7 +17,7 @@ defmodule Pleroma.Web.ApiSpec.TwitterUtilOperation do
def emoji_operation do
%Operation{
- tags: ["Emojis"],
+ tags: ["Custom emojis"],
summary: "List all custom emojis",
operationId: "UtilController.emoji",
parameters: [],
@@ -30,7 +30,8 @@ defmodule Pleroma.Web.ApiSpec.TwitterUtilOperation do
properties: %{
image_url: %Schema{type: :string},
tags: %Schema{type: :array, items: %Schema{type: :string}}
- }
+ },
+ extensions: %{"x-additionalPropertiesName": "Emoji name"}
},
example: %{
"firefox" => %{
@@ -45,7 +46,7 @@ defmodule Pleroma.Web.ApiSpec.TwitterUtilOperation do
def frontend_configurations_operation do
%Operation{
- tags: ["Configuration"],
+ tags: ["Others"],
summary: "Dump frontend configurations",
operationId: "UtilController.frontend_configurations",
parameters: [],
@@ -53,7 +54,12 @@ defmodule Pleroma.Web.ApiSpec.TwitterUtilOperation do
200 =>
Operation.response("List", "application/json", %Schema{
type: :object,
- additionalProperties: %Schema{type: :object}
+ additionalProperties: %Schema{
+ type: :object,
+ description:
+ "Opaque object representing the instance-wide configuration for the frontend",
+ extensions: %{"x-additionalPropertiesName": "Frontend name"}
+ }
})
}
}
@@ -81,7 +87,7 @@ defmodule Pleroma.Web.ApiSpec.TwitterUtilOperation do
defp change_password_request do
%Schema{
title: "ChangePasswordRequest",
- description: "POST body for changing the account's passowrd",
+ description: "POST body for changing the account's password",
type: :object,
required: [:password, :new_password, :new_password_confirmation],
properties: %{
@@ -130,23 +136,23 @@ defmodule Pleroma.Web.ApiSpec.TwitterUtilOperation do
}
end
- def update_notificaton_settings_operation do
+ def update_notification_settings_operation do
%Operation{
- tags: ["Accounts"],
+ tags: ["Settings"],
summary: "Update Notification Settings",
security: [%{"oAuth" => ["write:accounts"]}],
- operationId: "UtilController.update_notificaton_settings",
+ operationId: "UtilController.update_notification_settings",
parameters: [
Operation.parameter(
:block_from_strangers,
:query,
- BooleanLike,
+ BooleanLike.schema(),
"blocks notifications from accounts you do not follow"
),
Operation.parameter(
:hide_notification_contents,
:query,
- BooleanLike,
+ BooleanLike.schema(),
"removes the contents of a message from the push notification"
)
],
@@ -207,6 +213,7 @@ defmodule Pleroma.Web.ApiSpec.TwitterUtilOperation do
%Operation{
summary: "Get a captcha",
operationId: "UtilController.captcha",
+ tags: ["Others"],
parameters: [],
responses: %{
200 => Operation.response("Success", "application/json", %Schema{type: :object})
@@ -356,7 +363,7 @@ defmodule Pleroma.Web.ApiSpec.TwitterUtilOperation do
def healthcheck_operation do
%Operation{
- tags: ["Accounts"],
+ tags: ["Others"],
summary: "Quick status check on the instance",
security: [%{"oAuth" => ["write:accounts"]}],
operationId: "UtilController.healthcheck",
@@ -371,7 +378,7 @@ defmodule Pleroma.Web.ApiSpec.TwitterUtilOperation do
def remote_subscribe_operation do
%Operation{
- tags: ["Accounts"],
+ tags: ["Remote interaction"],
summary: "Remote Subscribe",
operationId: "UtilController.remote_subscribe",
parameters: [],
@@ -381,7 +388,7 @@ defmodule Pleroma.Web.ApiSpec.TwitterUtilOperation do
def remote_interaction_operation do
%Operation{
- tags: ["Accounts"],
+ tags: ["Remote interaction"],
summary: "Remote interaction",
operationId: "UtilController.remote_interaction",
requestBody: request_body("Parameters", remote_interaction_request(), required: true),
@@ -407,7 +414,7 @@ defmodule Pleroma.Web.ApiSpec.TwitterUtilOperation do
def show_subscribe_form_operation do
%Operation{
- tags: ["Accounts"],
+ tags: ["Remote interaction"],
summary: "Show remote subscribe form",
operationId: "UtilController.show_subscribe_form",
parameters: [],
diff --git a/lib/pleroma/web/api_spec/operations/user_import_operation.ex b/lib/pleroma/web/api_spec/operations/user_import_operation.ex
index e99e6e6..e99e6e6 100755..100644
--- a/lib/pleroma/web/api_spec/operations/user_import_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/user_import_operation.ex
diff --git a/lib/pleroma/web/api_spec/render_error.ex b/lib/pleroma/web/api_spec/render_error.ex
index 3539af6..3539af6 100755..100644
--- a/lib/pleroma/web/api_spec/render_error.ex
+++ b/lib/pleroma/web/api_spec/render_error.ex
diff --git a/lib/pleroma/web/api_spec/schemas/account.ex b/lib/pleroma/web/api_spec/schemas/account.ex
index 8aeb821..8aeb821 100755..100644
--- a/lib/pleroma/web/api_spec/schemas/account.ex
+++ b/lib/pleroma/web/api_spec/schemas/account.ex
diff --git a/lib/pleroma/web/api_spec/schemas/account_field.ex b/lib/pleroma/web/api_spec/schemas/account_field.ex
index 93ba1b5..93ba1b5 100755..100644
--- a/lib/pleroma/web/api_spec/schemas/account_field.ex
+++ b/lib/pleroma/web/api_spec/schemas/account_field.ex
diff --git a/lib/pleroma/web/api_spec/schemas/account_relationship.ex b/lib/pleroma/web/api_spec/schemas/account_relationship.ex
index 68219a0..68219a0 100755..100644
--- a/lib/pleroma/web/api_spec/schemas/account_relationship.ex
+++ b/lib/pleroma/web/api_spec/schemas/account_relationship.ex
diff --git a/lib/pleroma/web/api_spec/schemas/actor_type.ex b/lib/pleroma/web/api_spec/schemas/actor_type.ex
index 13b6b47..13b6b47 100755..100644
--- a/lib/pleroma/web/api_spec/schemas/actor_type.ex
+++ b/lib/pleroma/web/api_spec/schemas/actor_type.ex
diff --git a/lib/pleroma/web/api_spec/schemas/announcement.ex b/lib/pleroma/web/api_spec/schemas/announcement.ex
index 67d129e..67d129e 100755..100644
--- a/lib/pleroma/web/api_spec/schemas/announcement.ex
+++ b/lib/pleroma/web/api_spec/schemas/announcement.ex
diff --git a/lib/pleroma/web/api_spec/schemas/api_error.ex b/lib/pleroma/web/api_spec/schemas/api_error.ex
index 58a7107..58a7107 100755..100644
--- a/lib/pleroma/web/api_spec/schemas/api_error.ex
+++ b/lib/pleroma/web/api_spec/schemas/api_error.ex
diff --git a/lib/pleroma/web/api_spec/schemas/app.ex b/lib/pleroma/web/api_spec/schemas/app.ex
index 742413b..742413b 100755..100644
--- a/lib/pleroma/web/api_spec/schemas/app.ex
+++ b/lib/pleroma/web/api_spec/schemas/app.ex
diff --git a/lib/pleroma/web/api_spec/schemas/attachment.ex b/lib/pleroma/web/api_spec/schemas/attachment.ex
index 48634a1..2871b5f 100755..100644
--- a/lib/pleroma/web/api_spec/schemas/attachment.ex
+++ b/lib/pleroma/web/api_spec/schemas/attachment.ex
@@ -11,7 +11,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Attachment do
title: "Attachment",
description: "Represents a file or media attachment that can be added to a status.",
type: :object,
- requried: [:id, :url, :preview_url],
+ required: [:id, :url, :preview_url],
properties: %{
id: %Schema{type: :string, description: "The ID of the attachment in the database."},
url: %Schema{
diff --git a/lib/pleroma/web/api_spec/schemas/bookmark_folder.ex b/lib/pleroma/web/api_spec/schemas/bookmark_folder.ex
new file mode 100644
index 0000000..e8b4f43
--- /dev/null
+++ b/lib/pleroma/web/api_spec/schemas/bookmark_folder.ex
@@ -0,0 +1,26 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2024 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ApiSpec.Schemas.BookmarkFolder do
+ alias OpenApiSpex.Schema
+ alias Pleroma.Web.ApiSpec.Schemas.FlakeID
+
+ require OpenApiSpex
+
+ OpenApiSpex.schema(%{
+ title: "BookmarkFolder",
+ description: "Response schema for a bookmark folder",
+ type: :object,
+ properties: %{
+ id: FlakeID,
+ name: %Schema{type: :string, description: "Folder name"},
+ emoji: %Schema{type: :string, description: "Folder emoji", nullable: true}
+ },
+ example: %{
+ "id" => "9toJCu5YZW7O7gfvH6",
+ "name" => "Read later",
+ "emoji" => nil
+ }
+ })
+end
diff --git a/lib/pleroma/web/api_spec/schemas/boolean_like.ex b/lib/pleroma/web/api_spec/schemas/boolean_like.ex
index 14f728e..14f728e 100755..100644
--- a/lib/pleroma/web/api_spec/schemas/boolean_like.ex
+++ b/lib/pleroma/web/api_spec/schemas/boolean_like.ex
diff --git a/lib/pleroma/web/api_spec/schemas/chat.ex b/lib/pleroma/web/api_spec/schemas/chat.ex
index a07d128..a07d128 100755..100644
--- a/lib/pleroma/web/api_spec/schemas/chat.ex
+++ b/lib/pleroma/web/api_spec/schemas/chat.ex
diff --git a/lib/pleroma/web/api_spec/schemas/chat_message.ex b/lib/pleroma/web/api_spec/schemas/chat_message.ex
index 57f7890..57f7890 100755..100644
--- a/lib/pleroma/web/api_spec/schemas/chat_message.ex
+++ b/lib/pleroma/web/api_spec/schemas/chat_message.ex
diff --git a/lib/pleroma/web/api_spec/schemas/conversation.ex b/lib/pleroma/web/api_spec/schemas/conversation.ex
index f00a973..f00a973 100755..100644
--- a/lib/pleroma/web/api_spec/schemas/conversation.ex
+++ b/lib/pleroma/web/api_spec/schemas/conversation.ex
diff --git a/lib/pleroma/web/api_spec/schemas/emoji.ex b/lib/pleroma/web/api_spec/schemas/emoji.ex
index 936bbe1..936bbe1 100755..100644
--- a/lib/pleroma/web/api_spec/schemas/emoji.ex
+++ b/lib/pleroma/web/api_spec/schemas/emoji.ex
diff --git a/lib/pleroma/web/api_spec/schemas/flake_id.ex b/lib/pleroma/web/api_spec/schemas/flake_id.ex
index 4c3ec01..4c3ec01 100755..100644
--- a/lib/pleroma/web/api_spec/schemas/flake_id.ex
+++ b/lib/pleroma/web/api_spec/schemas/flake_id.ex
diff --git a/lib/pleroma/web/api_spec/schemas/list.ex b/lib/pleroma/web/api_spec/schemas/list.ex
index e57de79..e57de79 100755..100644
--- a/lib/pleroma/web/api_spec/schemas/list.ex
+++ b/lib/pleroma/web/api_spec/schemas/list.ex
diff --git a/lib/pleroma/web/api_spec/schemas/poll.ex b/lib/pleroma/web/api_spec/schemas/poll.ex
index 9157058..20cf5b0 100755..100644
--- a/lib/pleroma/web/api_spec/schemas/poll.ex
+++ b/lib/pleroma/web/api_spec/schemas/poll.ex
@@ -56,6 +56,15 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Poll do
}
},
description: "Possible answers for the poll."
+ },
+ pleroma: %Schema{
+ type: :object,
+ properties: %{
+ non_anonymous: %Schema{
+ type: :boolean,
+ description: "Can voters be publicly identified?"
+ }
+ }
}
},
example: %{
@@ -79,7 +88,10 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Poll do
votes_count: 4
}
],
- emojis: []
+ emojis: [],
+ pleroma: %{
+ non_anonymous: false
+ }
}
})
end
diff --git a/lib/pleroma/web/api_spec/schemas/push_subscription.ex b/lib/pleroma/web/api_spec/schemas/push_subscription.ex
index a546663..a546663 100755..100644
--- a/lib/pleroma/web/api_spec/schemas/push_subscription.ex
+++ b/lib/pleroma/web/api_spec/schemas/push_subscription.ex
diff --git a/lib/pleroma/web/api_spec/schemas/scheduled_status.ex b/lib/pleroma/web/api_spec/schemas/scheduled_status.ex
index a1acda1..a1acda1 100755..100644
--- a/lib/pleroma/web/api_spec/schemas/scheduled_status.ex
+++ b/lib/pleroma/web/api_spec/schemas/scheduled_status.ex
diff --git a/lib/pleroma/web/api_spec/schemas/status.ex b/lib/pleroma/web/api_spec/schemas/status.ex
index 698f117..6e537b5 100755..100644
--- a/lib/pleroma/web/api_spec/schemas/status.ex
+++ b/lib/pleroma/web/api_spec/schemas/status.ex
@@ -58,6 +58,10 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Status do
format: :uri,
description: "Preview thumbnail"
},
+ image_description: %Schema{
+ type: :string,
+ description: "Alternate text that describes what is in the thumbnail"
+ },
title: %Schema{type: :string, description: "Title of linked resource"},
description: %Schema{type: :string, description: "Description of preview"}
}
@@ -144,7 +148,11 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Status do
properties: %{
content: %Schema{
type: :object,
- additionalProperties: %Schema{type: :string},
+ additionalProperties: %Schema{
+ type: :string,
+ description: "Alternate representation in the MIME type specified",
+ extensions: %{"x-additionalPropertiesName": "MIME type"}
+ },
description:
"A map consisting of alternate representations of the `content` property with the key being it's mimetype. Currently the only alternate representation supported is `text/plain`"
},
@@ -189,13 +197,41 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Status do
nullable: true,
description: "The `acct` property of User entity for replied user (if any)"
},
+ quote: %Schema{
+ allOf: [%OpenApiSpex.Reference{"$ref": "#/components/schemas/Status"}],
+ nullable: true,
+ description: "Quoted status (if any)"
+ },
+ quote_id: %Schema{
+ nullable: true,
+ allOf: [FlakeID],
+ description: "ID of the status being quoted, if any"
+ },
+ quote_url: %Schema{
+ type: :string,
+ format: :uri,
+ nullable: true,
+ description: "URL of the quoted status"
+ },
+ quote_visible: %Schema{
+ type: :boolean,
+ description: "`true` if the quoted post is visible to the user"
+ },
+ quotes_count: %Schema{
+ type: :integer,
+ description: "How many statuses quoted this status"
+ },
local: %Schema{
type: :boolean,
description: "`true` if the post was made on the local instance"
},
spoiler_text: %Schema{
type: :object,
- additionalProperties: %Schema{type: :string},
+ additionalProperties: %Schema{
+ type: :string,
+ description: "Alternate representation in the MIME type specified",
+ extensions: %{"x-additionalPropertiesName": "MIME type"}
+ },
description:
"A map consisting of alternate representations of the `spoiler_text` property with the key being it's mimetype. Currently the only alternate representation supported is `text/plain`."
},
@@ -339,7 +375,8 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Status do
"in_reply_to_account_acct" => nil,
"local" => true,
"spoiler_text" => %{"text/plain" => ""},
- "thread_muted" => false
+ "thread_muted" => false,
+ "quotes_count" => 0
},
"poll" => nil,
"reblog" => nil,
diff --git a/lib/pleroma/web/api_spec/schemas/tag.ex b/lib/pleroma/web/api_spec/schemas/tag.ex
index 66bf0ca..66bf0ca 100755..100644
--- a/lib/pleroma/web/api_spec/schemas/tag.ex
+++ b/lib/pleroma/web/api_spec/schemas/tag.ex
diff --git a/lib/pleroma/web/api_spec/schemas/visibility_scope.ex b/lib/pleroma/web/api_spec/schemas/visibility_scope.ex
index ecd247b..ecd247b 100755..100644
--- a/lib/pleroma/web/api_spec/schemas/visibility_scope.ex
+++ b/lib/pleroma/web/api_spec/schemas/visibility_scope.ex
diff --git a/lib/pleroma/web/api_spec/scopes/compiler.ex b/lib/pleroma/web/api_spec/scopes/compiler.ex
new file mode 100644
index 0000000..162edc9
--- /dev/null
+++ b/lib/pleroma/web/api_spec/scopes/compiler.ex
@@ -0,0 +1,82 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ApiSpec.Scopes.Compiler do
+ defmacro __before_compile__(_env) do
+ strings = __MODULE__.extract_all_scopes()
+
+ quote do
+ def placeholder do
+ unquote do
+ Enum.map(
+ strings,
+ fn string ->
+ quote do
+ Pleroma.Web.Gettext.dgettext_noop(
+ "oauth_scopes",
+ unquote(string)
+ )
+ end
+ end
+ )
+ end
+ end
+ end
+ end
+
+ def extract_all_scopes do
+ extract_all_scopes_from(Pleroma.Web.ApiSpec.spec())
+ end
+
+ def extract_all_scopes_from(specs) do
+ specs.paths
+ |> Enum.reduce([], fn
+ {_path, %{} = path_item}, acc ->
+ extract_routes(path_item)
+ |> Enum.flat_map(fn operation -> process_operation(operation) end)
+ |> Kernel.++(acc)
+
+ {_, _}, acc ->
+ acc
+ end)
+ |> Enum.uniq()
+ end
+
+ defp extract_routes(path_item) do
+ path_item
+ |> Map.from_struct()
+ |> Enum.map(fn {_method, path_item} -> path_item end)
+ |> Enum.filter(fn
+ %OpenApiSpex.Operation{} = _operation -> true
+ _ -> false
+ end)
+ end
+
+ defp process_operation(operation) do
+ operation.security
+ |> Kernel.||([])
+ |> Enum.flat_map(fn
+ %{"oAuth" => scopes} -> process_scopes(scopes)
+ _ -> []
+ end)
+ end
+
+ defp process_scopes(scopes) do
+ scopes
+ |> Enum.flat_map(fn scope ->
+ process_scope(scope)
+ end)
+ end
+
+ def process_scope(scope) do
+ hierarchy = String.split(scope, ":")
+
+ {_, list} =
+ Enum.reduce(hierarchy, {"", []}, fn comp, {cur, list} ->
+ {cur <> comp <> ":", [cur <> comp | list]}
+ end)
+
+ list
+ end
+end
diff --git a/lib/pleroma/web/api_spec/scopes/translator.ex b/lib/pleroma/web/api_spec/scopes/translator.ex
new file mode 100644
index 0000000..54eea35
--- /dev/null
+++ b/lib/pleroma/web/api_spec/scopes/translator.ex
@@ -0,0 +1,10 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ApiSpec.Scopes.Translator do
+ require Pleroma.Web.ApiSpec.Scopes.Compiler
+ require Pleroma.Web.Gettext
+
+ @before_compile Pleroma.Web.ApiSpec.Scopes.Compiler
+end
diff --git a/lib/pleroma/web/auth/authenticator.ex b/lib/pleroma/web/auth/authenticator.ex
index a0bd154..01bf157 100755..100644
--- a/lib/pleroma/web/auth/authenticator.ex
+++ b/lib/pleroma/web/auth/authenticator.ex
@@ -5,7 +5,7 @@
defmodule Pleroma.Web.Auth.Authenticator do
@callback get_user(Plug.Conn.t()) :: {:ok, user :: struct()} | {:error, any()}
@callback create_from_registration(Plug.Conn.t(), registration :: struct()) ::
- {:ok, User.t()} | {:error, any()}
+ {:ok, Pleroma.User.t()} | {:error, any()}
@callback get_registration(Plug.Conn.t()) :: {:ok, registration :: struct()} | {:error, any()}
@callback handle_error(Plug.Conn.t(), any()) :: any()
@callback auth_template() :: String.t() | nil
diff --git a/lib/pleroma/web/auth/helpers.ex b/lib/pleroma/web/auth/helpers.ex
index 02e1f39..02e1f39 100755..100644
--- a/lib/pleroma/web/auth/helpers.ex
+++ b/lib/pleroma/web/auth/helpers.ex
diff --git a/lib/pleroma/web/auth/ldap_authenticator.ex b/lib/pleroma/web/auth/ldap_authenticator.ex
index e8cd449..e8cd449 100755..100644
--- a/lib/pleroma/web/auth/ldap_authenticator.ex
+++ b/lib/pleroma/web/auth/ldap_authenticator.ex
diff --git a/lib/pleroma/web/auth/pleroma_authenticator.ex b/lib/pleroma/web/auth/pleroma_authenticator.ex
index 09a58eb..09a58eb 100755..100644
--- a/lib/pleroma/web/auth/pleroma_authenticator.ex
+++ b/lib/pleroma/web/auth/pleroma_authenticator.ex
diff --git a/lib/pleroma/web/auth/totp_authenticator.ex b/lib/pleroma/web/auth/totp_authenticator.ex
index 4be3641..4be3641 100755..100644
--- a/lib/pleroma/web/auth/totp_authenticator.ex
+++ b/lib/pleroma/web/auth/totp_authenticator.ex
diff --git a/lib/pleroma/web/auth/wrapper_authenticator.ex b/lib/pleroma/web/auth/wrapper_authenticator.ex
index a077cfa..a077cfa 100755..100644
--- a/lib/pleroma/web/auth/wrapper_authenticator.ex
+++ b/lib/pleroma/web/auth/wrapper_authenticator.ex
diff --git a/lib/pleroma/web/channels/user_socket.ex b/lib/pleroma/web/channels/user_socket.ex
index 0f61b80..0f61b80 100755..100644
--- a/lib/pleroma/web/channels/user_socket.ex
+++ b/lib/pleroma/web/channels/user_socket.ex
diff --git a/lib/pleroma/web/common_api.ex b/lib/pleroma/web/common_api.ex
index 44eb000..27e82ec 100755..100644
--- a/lib/pleroma/web/common_api.ex
+++ b/lib/pleroma/web/common_api.ex
@@ -154,7 +154,7 @@ defmodule Pleroma.Web.CommonAPI do
def delete(activity_id, user) do
with {_, %Activity{data: %{"object" => _, "type" => "Create"}} = activity} <-
- {:find_activity, Activity.get_by_id(activity_id)},
+ {:find_activity, Activity.get_by_id(activity_id, filter: [])},
{_, %Object{} = object, _} <-
{:find_object, Object.normalize(activity, fetch: false), activity},
true <- User.privileged?(user, :messages_delete) || user.ap_id == object.data["actor"],
@@ -372,7 +372,7 @@ defmodule Pleroma.Web.CommonAPI do
do: visibility in ~w(public unlisted)
def public_announce?(object, _) do
- Visibility.is_public?(object)
+ Visibility.public?(object)
end
def get_visibility(_, _, %Participation{}), do: {"direct", "direct"}
@@ -500,12 +500,12 @@ defmodule Pleroma.Web.CommonAPI do
end
defp activity_is_public(activity) do
- with false <- Visibility.is_public?(activity) do
+ with false <- Visibility.public?(activity) do
{:error, :visibility_error}
end
end
- @spec unpin(String.t(), User.t()) :: {:ok, User.t()} | {:error, term()}
+ @spec unpin(String.t(), User.t()) :: {:ok, Activity.t()} | {:error, term()}
def unpin(id, user) do
with %Activity{} = activity <- create_activity_by_id(id),
{:ok, unpin_data, _} <- Builder.unpin(user, activity.object),
@@ -550,7 +550,7 @@ defmodule Pleroma.Web.CommonAPI do
remove_mute(user, activity)
else
{what, result} = error ->
- Logger.warn(
+ Logger.warning(
"CommonAPI.remove_mute/2 failed. #{what}: #{result}, user_id: #{user_id}, activity_id: #{activity_id}"
)
@@ -595,7 +595,7 @@ defmodule Pleroma.Web.CommonAPI do
end
def update_report_state(activity_id, state) do
- with %Activity{} = activity <- Activity.get_by_id(activity_id) do
+ with %Activity{} = activity <- Activity.get_by_id(activity_id, filter: []) do
Utils.update_report_state(activity, state)
else
nil -> {:error, :not_found}
diff --git a/lib/pleroma/web/common_api/activity_draft.ex b/lib/pleroma/web/common_api/activity_draft.ex
index 63ed48a..bc46a8a 100755..100644
--- a/lib/pleroma/web/common_api/activity_draft.ex
+++ b/lib/pleroma/web/common_api/activity_draft.ex
@@ -7,10 +7,14 @@ defmodule Pleroma.Web.CommonAPI.ActivityDraft do
alias Pleroma.Conversation.Participation
alias Pleroma.Object
alias Pleroma.Web.ActivityPub.Builder
+ alias Pleroma.Web.ActivityPub.Visibility
alias Pleroma.Web.CommonAPI
alias Pleroma.Web.CommonAPI.Utils
import Pleroma.Web.Gettext
+ import Pleroma.Web.Utils.Guards, only: [not_empty_string: 1]
+
+ @type t :: %__MODULE__{}
defstruct valid?: true,
errors: [],
@@ -22,6 +26,7 @@ defmodule Pleroma.Web.CommonAPI.ActivityDraft do
attachments: [],
in_reply_to: nil,
in_reply_to_conversation: nil,
+ quote_post: nil,
visibility: nil,
expires_at: nil,
extra: nil,
@@ -53,7 +58,9 @@ defmodule Pleroma.Web.CommonAPI.ActivityDraft do
|> poll()
|> with_valid(&in_reply_to/1)
|> with_valid(&in_reply_to_conversation/1)
+ |> with_valid(&quote_post/1)
|> with_valid(&visibility/1)
+ |> with_valid(&quoting_visibility/1)
|> content()
|> with_valid(&to_and_cc/1)
|> with_valid(&context/1)
@@ -78,7 +85,7 @@ defmodule Pleroma.Web.CommonAPI.ActivityDraft do
defp listen_object(draft) do
object =
draft.params
- |> Map.take([:album, :artist, :title, :length])
+ |> Map.take([:album, :artist, :title, :length, :externalLink])
|> Map.new(fn {key, value} -> {to_string(key), value} end)
|> Map.put("type", "Audio")
|> Map.put("to", draft.to)
@@ -132,6 +139,18 @@ defmodule Pleroma.Web.CommonAPI.ActivityDraft do
defp in_reply_to(draft), do: draft
+ defp quote_post(%{params: %{quote_id: id}} = draft) when not_empty_string(id) do
+ case Activity.get_by_id_with_object(id) do
+ %Activity{} = activity ->
+ %__MODULE__{draft | quote_post: activity}
+
+ _ ->
+ draft
+ end
+ end
+
+ defp quote_post(draft), do: draft
+
defp in_reply_to_conversation(draft) do
in_reply_to_conversation = Participation.get(draft.params[:in_reply_to_conversation_id])
%__MODULE__{draft | in_reply_to_conversation: in_reply_to_conversation}
@@ -147,6 +166,29 @@ defmodule Pleroma.Web.CommonAPI.ActivityDraft do
end
end
+ defp can_quote?(_draft, _object, visibility) when visibility in ~w(public unlisted local) do
+ true
+ end
+
+ defp can_quote?(draft, object, "private") do
+ draft.user.ap_id == object.data["actor"]
+ end
+
+ defp can_quote?(_, _, _) do
+ false
+ end
+
+ defp quoting_visibility(%{quote_post: %Activity{}} = draft) do
+ with %Object{} = object <- Object.normalize(draft.quote_post, fetch: false),
+ true <- can_quote?(draft, object, Visibility.get_visibility(object)) do
+ draft
+ else
+ _ -> add_error(draft, dgettext("errors", "Cannot quote private message"))
+ end
+ end
+
+ defp quoting_visibility(draft), do: draft
+
defp expires_at(draft) do
case CommonAPI.check_expiry_date(draft.params[:expires_in]) do
{:ok, expires_at} -> %__MODULE__{draft | expires_at: expires_at}
@@ -164,12 +206,15 @@ defmodule Pleroma.Web.CommonAPI.ActivityDraft do
end
end
- defp content(draft) do
+ defp content(%{mentions: mentions} = draft) do
{content_html, mentioned_users, tags} = Utils.make_content_html(draft)
+ mentioned_ap_ids =
+ Enum.map(mentioned_users, fn {_, mentioned_user} -> mentioned_user.ap_id end)
+
mentions =
- mentioned_users
- |> Enum.map(fn {_, mentioned_user} -> mentioned_user.ap_id end)
+ mentions
+ |> Kernel.++(mentioned_ap_ids)
|> Utils.get_addressed_users(draft.params[:to])
%__MODULE__{draft | content_html: content_html, mentions: mentions, tags: tags}
diff --git a/lib/pleroma/web/common_api/utils.ex b/lib/pleroma/web/common_api/utils.ex
index 6410815..52c08f0 100755..100644
--- a/lib/pleroma/web/common_api/utils.ex
+++ b/lib/pleroma/web/common_api/utils.ex
@@ -59,7 +59,8 @@ defmodule Pleroma.Web.CommonAPI.Utils do
end
defp get_attachment(media_id, user) do
- with %Object{data: _data} = object <- Repo.get(Object, media_id),
+ with %Object{data: data} = object <- Repo.get(Object, media_id),
+ %{"type" => type} when type in Pleroma.Constants.upload_object_types() <- data,
:ok <- Object.authorize_access(object, user) do
object
else
@@ -108,7 +109,7 @@ defmodule Pleroma.Web.CommonAPI.Utils do
def get_to_and_cc(%{visibility: "direct"} = draft) do
# If the OP is a DM already, add the implicit actor.
- if draft.in_reply_to && Visibility.is_direct?(draft.in_reply_to) do
+ if draft.in_reply_to && Visibility.direct?(draft.in_reply_to) do
{Enum.uniq([draft.in_reply_to.data["actor"] | draft.mentions]), []}
else
{draft.mentions, []}
@@ -150,6 +151,8 @@ defmodule Pleroma.Web.CommonAPI.Utils do
when is_list(options) do
limits = Config.get([:instance, :poll_limits])
+ options = options |> Enum.uniq()
+
with :ok <- validate_poll_expiration(expires_in, limits),
:ok <- validate_poll_options_amount(options, limits),
:ok <- validate_poll_options_length(options, limits) do
@@ -185,10 +188,15 @@ defmodule Pleroma.Web.CommonAPI.Utils do
end
defp validate_poll_options_amount(options, %{max_options: max_options}) do
- if Enum.count(options) > max_options do
- {:error, "Poll can't contain more than #{max_options} options"}
- else
- :ok
+ cond do
+ Enum.count(options) < 2 ->
+ {:error, "Poll must contain at least 2 options"}
+
+ Enum.count(options) > max_options ->
+ {:error, "Poll can't contain more than #{max_options} options"}
+
+ true ->
+ :ok
end
end
@@ -313,13 +321,13 @@ defmodule Pleroma.Web.CommonAPI.Utils do
format_asctime(date)
else
_e ->
- Logger.warn("Date #{date} in wrong format, must be ISO 8601")
+ Logger.warning("Date #{date} in wrong format, must be ISO 8601")
""
end
end
def date_to_asctime(date) do
- Logger.warn("Date #{date} in wrong format, must be ISO 8601")
+ Logger.warning("Date #{date} in wrong format, must be ISO 8601")
""
end
diff --git a/lib/pleroma/web/controller_helper.ex b/lib/pleroma/web/controller_helper.ex
index 0c7fc17..1caf0f7 100755..100644
--- a/lib/pleroma/web/controller_helper.ex
+++ b/lib/pleroma/web/controller_helper.ex
@@ -20,7 +20,7 @@ defmodule Pleroma.Web.ControllerHelper do
|> json(json)
end
- @spec fetch_integer_param(map(), String.t(), integer() | nil) :: integer() | nil
+ @spec fetch_integer_param(map(), String.t() | atom(), integer() | nil) :: integer() | nil
def fetch_integer_param(params, name, default \\ nil) do
params
|> Map.get(name, default)
@@ -53,10 +53,15 @@ defmodule Pleroma.Web.ControllerHelper do
end
end
+ # TODO: Only fetch the params from open_api_spex when everything is converted
@id_keys Pagination.page_keys() -- ["limit", "order"]
defp build_pagination_fields(conn, min_id, max_id, extra_params) do
params =
- conn.params
+ if Map.has_key?(conn.private, :open_api_spex) do
+ get_in(conn, [Access.key(:private), Access.key(:open_api_spex), Access.key(:params)])
+ else
+ conn.params
+ end
|> Map.drop(Map.keys(conn.path_params) |> Enum.map(&String.to_existing_atom/1))
|> Map.merge(extra_params)
|> Map.drop(@id_keys)
@@ -85,18 +90,15 @@ defmodule Pleroma.Web.ControllerHelper do
end
end
- def assign_account_by_id(conn, _) do
- case Pleroma.User.get_cached_by_id(conn.params.id) do
+ def assign_account_by_id(%{private: %{open_api_spex: %{params: %{id: id}}}} = conn, _) do
+ case Pleroma.User.get_cached_by_id(id) do
%Pleroma.User{} = account -> assign(conn, :account, account)
nil -> Pleroma.Web.MastodonAPI.FallbackController.call(conn, {:error, :not_found}) |> halt()
end
end
def try_render(conn, target, params) when is_binary(target) do
- case render(conn, target, params) do
- nil -> render_error(conn, :not_implemented, "Can't display this activity")
- res -> res
- end
+ render(conn, target, params)
end
def try_render(conn, _, _) do
diff --git a/lib/pleroma/web/embed_controller.ex b/lib/pleroma/web/embed_controller.ex
index 8b9f0a0..2ca4501 100755..100644
--- a/lib/pleroma/web/embed_controller.ex
+++ b/lib/pleroma/web/embed_controller.ex
@@ -11,12 +11,10 @@ defmodule Pleroma.Web.EmbedController do
alias Pleroma.Web.ActivityPub.Visibility
- plug(:put_layout, :embed)
-
def show(conn, %{"id" => id}) do
with %Activity{local: true} = activity <-
Activity.get_by_id_with_object(id),
- true <- Visibility.is_public?(activity.object) do
+ true <- Visibility.public?(activity.object) do
{:ok, author} = User.get_or_fetch(activity.object.data["actor"])
conn
diff --git a/lib/pleroma/web/endpoint.ex b/lib/pleroma/web/endpoint.ex
index d8d40cc..2e21049 100755..100644
--- a/lib/pleroma/web/endpoint.ex
+++ b/lib/pleroma/web/endpoint.ex
@@ -9,7 +9,31 @@ defmodule Pleroma.Web.Endpoint do
alias Pleroma.Config
- socket("/socket", Pleroma.Web.UserSocket)
+ socket("/api/v1/streaming", Pleroma.Web.MastodonAPI.WebsocketHandler,
+ longpoll: false,
+ websocket: [
+ path: "/",
+ compress: false,
+ error_handler: {Pleroma.Web.MastodonAPI.WebsocketHandler, :handle_error, []},
+ fullsweep_after: 20
+ ]
+ )
+
+ socket("/socket", Pleroma.Web.UserSocket,
+ websocket: [
+ path: "/websocket",
+ serializer: [
+ {Phoenix.Socket.V1.JSONSerializer, "~> 1.0.0"},
+ {Phoenix.Socket.V2.JSONSerializer, "~> 2.0.0"}
+ ],
+ timeout: 60_000,
+ transport_log: false,
+ compress: false,
+ fullsweep_after: 20
+ ],
+ longpoll: false
+ )
+
socket("/live", Phoenix.LiveView.Socket)
plug(Plug.Telemetry, event_prefix: [:phoenix, :endpoint])
@@ -19,7 +43,8 @@ defmodule Pleroma.Web.Endpoint do
plug(Pleroma.Web.Plugs.HTTPSecurityPlug)
plug(Pleroma.Web.Plugs.UploadedMedia)
- @static_cache_control "public, no-cache"
+ @static_cache_control "public, max-age=1209600"
+ @static_cache_disabled "public, no-cache"
# InstanceStatic needs to be before Plug.Static to be able to override shipped-static files
# If you're adding new paths to `only:` you'll need to configure them in InstanceStatic as well
@@ -30,22 +55,32 @@ defmodule Pleroma.Web.Endpoint do
from: :pleroma,
only: ["emoji", "images"],
gzip: true,
- cache_control_for_etags: "public, max-age=1209600",
+ cache_control_for_etags: @static_cache_control,
headers: %{
- "cache-control" => "public, max-age=1209600"
+ "cache-control" => @static_cache_control
}
)
plug(Pleroma.Web.Plugs.InstanceStatic,
at: "/",
gzip: true,
- cache_control_for_etags: @static_cache_control,
+ cache_control_for_etags: @static_cache_disabled,
headers: %{
- "cache-control" => @static_cache_control
+ "cache-control" => @static_cache_disabled
+ }
+ )
+
+ plug(Pleroma.Web.Plugs.FrontendStatic,
+ at: "/",
+ frontend_type: :primary,
+ only: ["index.html"],
+ gzip: true,
+ cache_control_for_etags: @static_cache_disabled,
+ headers: %{
+ "cache-control" => @static_cache_disabled
}
)
- # Careful! No `only` restriction here, as we don't know what frontends contain.
plug(Pleroma.Web.Plugs.FrontendStatic,
at: "/",
frontend_type: :primary,
@@ -62,9 +97,9 @@ defmodule Pleroma.Web.Endpoint do
at: "/pleroma/admin",
frontend_type: :admin,
gzip: true,
- cache_control_for_etags: @static_cache_control,
+ cache_control_for_etags: @static_cache_disabled,
headers: %{
- "cache-control" => @static_cache_control
+ "cache-control" => @static_cache_disabled
}
)
@@ -79,9 +114,9 @@ defmodule Pleroma.Web.Endpoint do
only: Pleroma.Constants.static_only_files(),
# credo:disable-for-previous-line Credo.Check.Readability.MaxLineLength
gzip: true,
- cache_control_for_etags: @static_cache_control,
+ cache_control_for_etags: @static_cache_disabled,
headers: %{
- "cache-control" => @static_cache_control
+ "cache-control" => @static_cache_disabled
}
)
@@ -101,13 +136,10 @@ defmodule Pleroma.Web.Endpoint do
plug(Plug.Logger, log: :debug)
plug(Plug.Parsers,
- parsers: [
- :urlencoded,
- {:multipart, length: {Config, :get, [[:instance, :upload_limit]]}},
- :json
- ],
+ parsers: [:urlencoded, Pleroma.Web.Multipart, :json],
pass: ["*/*"],
json_decoder: Jason,
+ # Note: this is compile-time only, won't work for database-config
length: Config.get([:instance, :upload_limit]),
body_reader: {Pleroma.Web.Plugs.DigestPlug, :read_body, []}
)
@@ -141,47 +173,6 @@ defmodule Pleroma.Web.Endpoint do
plug(Pleroma.Web.Plugs.RemoteIp)
- defmodule Instrumenter do
- use Prometheus.PhoenixInstrumenter
- end
-
- defmodule PipelineInstrumenter do
- use Prometheus.PlugPipelineInstrumenter
- end
-
- defmodule MetricsExporter do
- use Prometheus.PlugExporter
- end
-
- defmodule MetricsExporterCaller do
- @behaviour Plug
-
- def init(opts), do: opts
-
- def call(conn, opts) do
- prometheus_config = Application.get_env(:prometheus, MetricsExporter, [])
- ip_whitelist = List.wrap(prometheus_config[:ip_whitelist])
-
- cond do
- !prometheus_config[:enabled] ->
- conn
-
- ip_whitelist != [] and
- !Enum.find(ip_whitelist, fn ip ->
- Pleroma.Helpers.InetHelper.parse_address(ip) == {:ok, conn.remote_ip}
- end) ->
- conn
-
- true ->
- MetricsExporter.call(conn, opts)
- end
- end
- end
-
- plug(PipelineInstrumenter)
-
- plug(MetricsExporterCaller)
-
plug(Pleroma.Web.Router)
@doc """
diff --git a/lib/pleroma/web/fallback/legacy_pleroma_api_rerouter_plug.ex b/lib/pleroma/web/fallback/legacy_pleroma_api_rerouter_plug.ex
index 6176f3d..6176f3d 100755..100644
--- a/lib/pleroma/web/fallback/legacy_pleroma_api_rerouter_plug.ex
+++ b/lib/pleroma/web/fallback/legacy_pleroma_api_rerouter_plug.ex
diff --git a/lib/pleroma/web/fallback/redirect_controller.ex b/lib/pleroma/web/fallback/redirect_controller.ex
index 1a86f7a..4a0885f 100755..100644
--- a/lib/pleroma/web/fallback/redirect_controller.ex
+++ b/lib/pleroma/web/fallback/redirect_controller.ex
@@ -17,10 +17,28 @@ defmodule Pleroma.Web.Fallback.RedirectController do
|> json(%{error: "Not implemented"})
end
+ def add_generated_metadata(page_content, extra \\ "") do
+ title = "<title>#{Pleroma.Config.get([:instance, :name])}</title>"
+ favicon = "<link rel='icon' href='#{Pleroma.Config.get([:instance, :favicon])}'>"
+ manifest = "<link rel='manifest' href='/manifest.json'>"
+
+ page_content
+ |> String.replace(
+ "<!--server-generated-meta-->",
+ title <> favicon <> manifest <> extra
+ )
+ end
+
def redirector(conn, _params, code \\ 200) do
+ {:ok, index_content} = File.read(index_file_path())
+
+ response =
+ index_content
+ |> add_generated_metadata()
+
conn
|> put_resp_content_type("text/html")
- |> send_file(code, index_file_path())
+ |> send_resp(code, response)
end
def redirector_with_meta(conn, %{"maybe_nickname_or_id" => maybe_nickname_or_id} = params) do
@@ -34,14 +52,12 @@ defmodule Pleroma.Web.Fallback.RedirectController do
def redirector_with_meta(conn, params) do
{:ok, index_content} = File.read(index_file_path())
-
tags = build_tags(conn, params)
preloads = preload_data(conn, params)
- title = "<title>#{Pleroma.Config.get([:instance, :name])}</title>"
response =
index_content
- |> String.replace("<!--server-generated-meta-->", tags <> preloads <> title)
+ |> add_generated_metadata(tags <> preloads)
conn
|> put_resp_content_type("text/html")
@@ -55,11 +71,10 @@ defmodule Pleroma.Web.Fallback.RedirectController do
def redirector_with_preload(conn, params) do
{:ok, index_content} = File.read(index_file_path())
preloads = preload_data(conn, params)
- title = "<title>#{Pleroma.Config.get([:instance, :name])}</title>"
response =
index_content
- |> String.replace("<!--server-generated-meta-->", preloads <> title)
+ |> add_generated_metadata(preloads)
conn
|> put_resp_content_type("text/html")
diff --git a/lib/pleroma/web/federator.ex b/lib/pleroma/web/federator.ex
index 318b6cb..1f2c383 100755..100644
--- a/lib/pleroma/web/federator.ex
+++ b/lib/pleroma/web/federator.ex
@@ -6,10 +6,9 @@ defmodule Pleroma.Web.Federator do
alias Pleroma.Activity
alias Pleroma.Object.Containment
alias Pleroma.User
- alias Pleroma.Web.ActivityPub.ActivityPub
+ alias Pleroma.Web.ActivityPub.Publisher
alias Pleroma.Web.ActivityPub.Transmogrifier
alias Pleroma.Web.ActivityPub.Utils
- alias Pleroma.Web.Federator.Publisher
alias Pleroma.Workers.PublisherWorker
alias Pleroma.Workers.ReceiverWorker
@@ -36,6 +35,17 @@ defmodule Pleroma.Web.Federator do
end
# Client API
+ def incoming_ap_doc(%{params: params, req_headers: req_headers}) do
+ ReceiverWorker.enqueue(
+ "incoming_ap_doc",
+ %{"req_headers" => req_headers, "params" => params, "timeout" => :timer.seconds(20)},
+ priority: 2
+ )
+ end
+
+ def incoming_ap_doc(%{"type" => "Delete"} = params) do
+ ReceiverWorker.enqueue("incoming_ap_doc", %{"params" => params}, priority: 3)
+ end
def incoming_ap_doc(params) do
ReceiverWorker.enqueue("incoming_ap_doc", %{"params" => params})
@@ -58,10 +68,8 @@ defmodule Pleroma.Web.Federator do
# Job Worker Callbacks
- @spec perform(atom(), module(), any()) :: {:ok, any()} | {:error, any()}
- def perform(:publish_one, module, params) do
- apply(module, :publish_one, [params])
- end
+ @spec perform(atom(), any()) :: {:ok, any()} | {:error, any()}
+ def perform(:publish_one, params), do: Publisher.publish_one(params)
def perform(:publish, activity) do
Logger.debug(fn -> "Running publish for #{activity.data["id"]}" end)
@@ -80,7 +88,7 @@ defmodule Pleroma.Web.Federator do
# NOTE: we use the actor ID to do the containment, this is fine because an
# actor shouldn't be acting on objects outside their own AP server.
- with {_, {:ok, _user}} <- {:actor, ap_enabled_actor(actor)},
+ with {_, {:ok, _user}} <- {:actor, User.get_or_fetch_by_ap_id(actor)},
nil <- Activity.normalize(params["id"]),
{_, :ok} <-
{:correct_origin?, Containment.contain_origin_from_id(actor, params)},
@@ -110,14 +118,4 @@ defmodule Pleroma.Web.Federator do
{:error, e}
end
end
-
- def ap_enabled_actor(id) do
- user = User.get_cached_by_ap_id(id)
-
- if User.ap_enabled?(user) do
- {:ok, user}
- else
- ActivityPub.make_user_from_ap_id(id)
- end
- end
end
diff --git a/lib/pleroma/web/federator/publisher.ex b/lib/pleroma/web/federator/publisher.ex
deleted file mode 100755
index a45796e..0000000
--- a/lib/pleroma/web/federator/publisher.ex
+++ /dev/null
@@ -1,109 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.Federator.Publisher do
- alias Pleroma.Activity
- alias Pleroma.Config
- alias Pleroma.User
- alias Pleroma.Workers.PublisherWorker
-
- require Logger
-
- @moduledoc """
- Defines the contract used by federation implementations to publish messages to
- their peers.
- """
-
- @doc """
- Determine whether an activity can be relayed using the federation module.
- """
- @callback is_representable?(Pleroma.Activity.t()) :: boolean()
-
- @doc """
- Relays an activity to a specified peer, determined by the parameters. The
- parameters used are controlled by the federation module.
- """
- @callback publish_one(Map.t()) :: {:ok, Map.t()} | {:error, any()}
-
- @doc """
- Enqueue publishing a single activity.
- """
- @spec enqueue_one(module(), Map.t()) :: :ok
- def enqueue_one(module, %{} = params) do
- PublisherWorker.enqueue(
- "publish_one",
- %{"module" => to_string(module), "params" => params}
- )
- end
-
- @doc """
- Relays an activity to all specified peers.
- """
- @callback publish(User.t(), Activity.t()) :: :ok | {:error, any()}
-
- @spec publish(User.t(), Activity.t()) :: :ok
- def publish(%User{} = user, %Activity{} = activity) do
- Config.get([:instance, :federation_publisher_modules])
- |> Enum.each(fn module ->
- if module.is_representable?(activity) do
- Logger.debug("Publishing #{activity.data["id"]} using #{inspect(module)}")
- module.publish(user, activity)
- end
- end)
-
- :ok
- end
-
- @doc """
- Gathers links used by an outgoing federation module for WebFinger output.
- """
- @callback gather_webfinger_links(User.t()) :: list()
-
- @spec gather_webfinger_links(User.t()) :: list()
- def gather_webfinger_links(%User{} = user) do
- Config.get([:instance, :federation_publisher_modules])
- |> Enum.reduce([], fn module, links ->
- links ++ module.gather_webfinger_links(user)
- end)
- end
-
- @doc """
- Gathers nodeinfo protocol names supported by the federation module.
- """
- @callback gather_nodeinfo_protocol_names() :: list()
-
- @spec gather_nodeinfo_protocol_names() :: list()
- def gather_nodeinfo_protocol_names do
- Config.get([:instance, :federation_publisher_modules])
- |> Enum.reduce([], fn module, links ->
- links ++ module.gather_nodeinfo_protocol_names()
- end)
- end
-
- @doc """
- Gathers a set of remote users given an IR envelope.
- """
- def remote_users(%User{id: user_id}, %{data: %{"to" => to} = data}) do
- cc = Map.get(data, "cc", [])
-
- bcc =
- data
- |> Map.get("bcc", [])
- |> Enum.reduce([], fn ap_id, bcc ->
- case Pleroma.List.get_by_ap_id(ap_id) do
- %Pleroma.List{user_id: ^user_id} = list ->
- {:ok, following} = Pleroma.List.get_following(list)
- bcc ++ Enum.map(following, & &1.ap_id)
-
- _ ->
- bcc
- end
- end)
-
- [to, cc, bcc]
- |> Enum.concat()
- |> Enum.map(&User.get_cached_by_ap_id/1)
- |> Enum.filter(fn user -> user && !user.local end)
- end
-end
diff --git a/lib/pleroma/web/federator/publishing.ex b/lib/pleroma/web/federator/publishing.ex
index 3a242b8..3a242b8 100755..100644
--- a/lib/pleroma/web/federator/publishing.ex
+++ b/lib/pleroma/web/federator/publishing.ex
diff --git a/lib/pleroma/web/feed/feed_view.ex b/lib/pleroma/web/feed/feed_view.ex
index 034722e..e1ee33d 100755..100644
--- a/lib/pleroma/web/feed/feed_view.ex
+++ b/lib/pleroma/web/feed/feed_view.ex
@@ -132,7 +132,7 @@ defmodule Pleroma.Web.Feed.FeedView do
|> safe_to_string()
end
- @spec to_rfc3339(String.t() | NativeDateTime.t()) :: String.t()
+ @spec to_rfc3339(String.t() | NaiveDateTime.t()) :: String.t()
def to_rfc3339(date) when is_binary(date) do
date
|> Timex.parse!("{ISO:Extended}")
@@ -145,7 +145,7 @@ defmodule Pleroma.Web.Feed.FeedView do
|> Timex.format!("{RFC3339}")
end
- @spec to_rfc2822(String.t() | DateTime.t() | NativeDateTime.t()) :: String.t()
+ @spec to_rfc2822(String.t() | DateTime.t() | NaiveDateTime.t()) :: String.t()
def to_rfc2822(datestr) when is_binary(datestr) do
datestr
|> Timex.parse!("{ISO:Extended}")
diff --git a/lib/pleroma/web/feed/tag_controller.ex b/lib/pleroma/web/feed/tag_controller.ex
index e607673..e607673 100755..100644
--- a/lib/pleroma/web/feed/tag_controller.ex
+++ b/lib/pleroma/web/feed/tag_controller.ex
diff --git a/lib/pleroma/web/feed/user_controller.ex b/lib/pleroma/web/feed/user_controller.ex
index 6657c2b..6657c2b 100755..100644
--- a/lib/pleroma/web/feed/user_controller.ex
+++ b/lib/pleroma/web/feed/user_controller.ex
diff --git a/lib/pleroma/web/gettext.ex b/lib/pleroma/web/gettext.ex
index 5ef49d8..1fa3f97 100755..100644
--- a/lib/pleroma/web/gettext.ex
+++ b/lib/pleroma/web/gettext.ex
@@ -85,12 +85,12 @@ defmodule Pleroma.Web.Gettext do
Process.get({Pleroma.Web.Gettext, :locales}, [])
end
- def is_locale_list(locales) do
+ def locale_list?(locales) do
Enum.all?(locales, &is_binary/1)
end
def put_locales(locales) do
- if is_locale_list(locales) do
+ if locale_list?(locales) do
Process.put({Pleroma.Web.Gettext, :locales}, Enum.uniq(locales))
Gettext.put_locale(Enum.at(locales, 0, Gettext.get_locale()))
:ok
diff --git a/lib/pleroma/web/instance_document.ex b/lib/pleroma/web/instance_document.ex
index 9da3c50..9da3c50 100755..100644
--- a/lib/pleroma/web/instance_document.ex
+++ b/lib/pleroma/web/instance_document.ex
diff --git a/lib/pleroma/web/mailer/subscription_controller.ex b/lib/pleroma/web/mailer/subscription_controller.ex
index f2fc8fb..f2fc8fb 100755..100644
--- a/lib/pleroma/web/mailer/subscription_controller.ex
+++ b/lib/pleroma/web/mailer/subscription_controller.ex
diff --git a/lib/pleroma/web/manifest_controller.ex b/lib/pleroma/web/manifest_controller.ex
index 3b02e4b..3b02e4b 100755..100644
--- a/lib/pleroma/web/manifest_controller.ex
+++ b/lib/pleroma/web/manifest_controller.ex
diff --git a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex
index ea6e593..9226a2d 100755..100644
--- a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex
@@ -30,7 +30,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
alias Pleroma.Web.TwitterAPI.TwitterAPI
alias Pleroma.Web.Utils.Params
- plug(Pleroma.Web.ApiSpec.CastAndValidate)
+ plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
plug(:skip_auth when action in [:create, :lookup])
@@ -92,7 +92,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
plug(
RateLimiter,
- [name: :relation_id_action, params: [:id, :uri]] when action in @relationship_actions
+ [name: :relation_id_action, params: ["id", "uri"]] when action in @relationship_actions
)
plug(RateLimiter, [name: :relations_actions] when action in @relationship_actions)
@@ -104,7 +104,10 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.AccountOperation
@doc "POST /api/v1/accounts"
- def create(%{assigns: %{app: app}, body_params: params} = conn, _params) do
+ def create(
+ %{assigns: %{app: app}, private: %{open_api_spex: %{body_params: params}}} = conn,
+ _params
+ ) do
with :ok <- validate_email_param(params),
:ok <- TwitterAPI.validate_captcha(app, params),
{:ok, user} <- TwitterAPI.register_user(params),
@@ -168,7 +171,10 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
end
@doc "PATCH /api/v1/accounts/update_credentials"
- def update_credentials(%{assigns: %{user: user}, body_params: params} = conn, _params) do
+ def update_credentials(
+ %{assigns: %{user: user}, private: %{open_api_spex: %{body_params: params}}} = conn,
+ _params
+ ) do
params =
params
|> Enum.filter(fn {_, value} -> not is_nil(value) end)
@@ -235,7 +241,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
# So we first build the normal local changeset, then apply it to the
# user data, but don't persist it. With this, we generate the object
# data for our update activity. We feed this and the changeset as meta
- # inforation into the pipeline, where they will be properly updated and
+ # information into the pipeline, where they will be properly updated and
# federated.
with changeset <- User.update_changeset(user, user_params),
{:ok, unpersisted_user} <- Ecto.Changeset.apply_action(changeset, :update),
@@ -263,24 +269,36 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
{:error, %Ecto.Changeset{errors: [background: {"file is too large", _}]}} ->
render_error(conn, :request_entity_too_large, "File is too large")
+ {:error, %Ecto.Changeset{errors: [{:bio, {_, _}} | _]}} ->
+ render_error(conn, :request_entity_too_large, "Bio is too long")
+
+ {:error, %Ecto.Changeset{errors: [{:name, {_, _}} | _]}} ->
+ render_error(conn, :request_entity_too_large, "Name is too long")
+
+ {:error, %Ecto.Changeset{errors: [{:fields, {"invalid", _}} | _]}} ->
+ render_error(conn, :request_entity_too_large, "One or more field entries are too long")
+
+ {:error, %Ecto.Changeset{errors: [{:fields, {_, _}} | _]}} ->
+ render_error(conn, :request_entity_too_large, "Too many field entries")
+
_e ->
render_error(conn, :forbidden, "Invalid request")
end
end
defp normalize_fields_attributes(fields) do
- if Enum.all?(fields, &is_tuple/1) do
- Enum.map(fields, fn {_, v} -> v end)
- else
- Enum.map(fields, fn
- %{} = field -> %{"name" => field.name, "value" => field.value}
- field -> field
- end)
- end
+ if(Enum.all?(fields, &is_tuple/1), do: Enum.map(fields, fn {_, v} -> v end), else: fields)
+ |> Enum.map(fn
+ %{} = field -> %{"name" => field.name, "value" => field.value}
+ field -> field
+ end)
end
@doc "GET /api/v1/accounts/relationships"
- def relationships(%{assigns: %{user: user}} = conn, %{id: id}) do
+ def relationships(
+ %{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: id}}}} = conn,
+ _
+ ) do
targets = User.get_all_by_ids(List.wrap(id))
render(conn, "relationships.json", user: user, targets: targets)
@@ -290,7 +308,13 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
def relationships(%{assigns: %{user: _user}} = conn, _), do: json(conn, [])
@doc "GET /api/v1/accounts/:id"
- def show(%{assigns: %{user: for_user}} = conn, %{id: nickname_or_id} = params) do
+ def show(
+ %{
+ assigns: %{user: for_user},
+ private: %{open_api_spex: %{params: %{id: nickname_or_id} = params}}
+ } = conn,
+ _params
+ ) do
with %User{} = user <- User.get_cached_by_nickname_or_id(nickname_or_id, for: for_user),
:visible <- User.visible_for(user, for_user) do
render(conn, "show.json",
@@ -304,7 +328,10 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
end
@doc "GET /api/v1/accounts/:id/statuses"
- def statuses(%{assigns: %{user: reading_user}} = conn, params) do
+ def statuses(
+ %{assigns: %{user: reading_user}, private: %{open_api_spex: %{params: params}}} = conn,
+ _params
+ ) do
with %User{} = user <- User.get_cached_by_nickname_or_id(params.id, for: reading_user),
:visible <- User.visible_for(user, reading_user) do
params =
@@ -339,7 +366,11 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
end
@doc "GET /api/v1/accounts/:id/followers"
- def followers(%{assigns: %{user: for_user, account: user}} = conn, params) do
+ def followers(
+ %{assigns: %{user: for_user, account: user}, private: %{open_api_spex: %{params: params}}} =
+ conn,
+ _params
+ ) do
params =
params
|> Enum.map(fn {key, value} -> {to_string(key), value} end)
@@ -364,7 +395,11 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
end
@doc "GET /api/v1/accounts/:id/following"
- def following(%{assigns: %{user: for_user, account: user}} = conn, params) do
+ def following(
+ %{assigns: %{user: for_user, account: user}, private: %{open_api_spex: %{params: params}}} =
+ conn,
+ _params
+ ) do
params =
params
|> Enum.map(fn {key, value} -> {to_string(key), value} end)
@@ -402,7 +437,13 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
{:error, "Can not follow yourself"}
end
- def follow(%{body_params: params, assigns: %{user: follower, account: followed}} = conn, _) do
+ def follow(
+ %{
+ assigns: %{user: follower, account: followed},
+ private: %{open_api_spex: %{body_params: params}}
+ } = conn,
+ _
+ ) do
with {:ok, follower} <- MastodonAPI.follow(follower, followed, params) do
render(conn, "relationship.json", user: follower, target: followed)
else
@@ -422,7 +463,13 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
end
@doc "POST /api/v1/accounts/:id/mute"
- def mute(%{assigns: %{user: muter, account: muted}, body_params: params} = conn, _params) do
+ def mute(
+ %{
+ assigns: %{user: muter, account: muted},
+ private: %{open_api_spex: %{body_params: params}}
+ } = conn,
+ _params
+ ) do
params =
params
|> Map.put_new(:duration, Map.get(params, :expires_in, 0))
@@ -463,7 +510,10 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
@doc "POST /api/v1/accounts/:id/note"
def note(
- %{assigns: %{user: noter, account: target}, body_params: %{comment: comment}} = conn,
+ %{
+ assigns: %{user: noter, account: target},
+ private: %{open_api_spex: %{body_params: %{comment: comment}}}
+ } = conn,
_params
) do
with {:ok, _user_note} <- UserNote.create(noter, target, comment) do
@@ -504,7 +554,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
end
@doc "POST /api/v1/follows"
- def follow_by_uri(%{body_params: %{uri: uri}} = conn, _) do
+ def follow_by_uri(%{private: %{open_api_spex: %{body_params: %{uri: uri}}}} = conn, _) do
case User.get_cached_by_nickname(uri) do
%User{} = user ->
conn
@@ -543,11 +593,16 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
conn
|> add_link_headers(users)
- |> render("index.json", users: users, for: user, as: :user)
+ |> render("index.json",
+ users: users,
+ for: user,
+ as: :user,
+ embed_relationships: embed_relationships?(params)
+ )
end
@doc "GET /api/v1/accounts/lookup"
- def lookup(conn, %{acct: nickname} = _params) do
+ def lookup(%{private: %{open_api_spex: %{params: %{acct: nickname}}}} = conn, _params) do
with %User{} = user <- User.get_by_nickname(nickname) do
render(conn, "show.json",
user: user,
diff --git a/lib/pleroma/web/mastodon_api/controllers/announcement_controller.ex b/lib/pleroma/web/mastodon_api/controllers/announcement_controller.ex
index 080af96..080af96 100755..100644
--- a/lib/pleroma/web/mastodon_api/controllers/announcement_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/announcement_controller.ex
diff --git a/lib/pleroma/web/mastodon_api/controllers/app_controller.ex b/lib/pleroma/web/mastodon_api/controllers/app_controller.ex
index 844673a..844673a 100755..100644
--- a/lib/pleroma/web/mastodon_api/controllers/app_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/app_controller.ex
diff --git a/lib/pleroma/web/mastodon_api/controllers/auth_controller.ex b/lib/pleroma/web/mastodon_api/controllers/auth_controller.ex
index fbb54a1..fbb54a1 100755..100644
--- a/lib/pleroma/web/mastodon_api/controllers/auth_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/auth_controller.ex
diff --git a/lib/pleroma/web/mastodon_api/controllers/conversation_controller.ex b/lib/pleroma/web/mastodon_api/controllers/conversation_controller.ex
index 9cc6225..9cc6225 100755..100644
--- a/lib/pleroma/web/mastodon_api/controllers/conversation_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/conversation_controller.ex
diff --git a/lib/pleroma/web/mastodon_api/controllers/custom_emoji_controller.ex b/lib/pleroma/web/mastodon_api/controllers/custom_emoji_controller.ex
index 8b27b0b..8b27b0b 100755..100644
--- a/lib/pleroma/web/mastodon_api/controllers/custom_emoji_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/custom_emoji_controller.ex
diff --git a/lib/pleroma/web/mastodon_api/controllers/directory_controller.ex b/lib/pleroma/web/mastodon_api/controllers/directory_controller.ex
index 253f06c..f894259 100755..100644
--- a/lib/pleroma/web/mastodon_api/controllers/directory_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/directory_controller.ex
@@ -15,7 +15,7 @@ defmodule Pleroma.Web.MastodonAPI.DirectoryController do
plug(Pleroma.Web.ApiSpec.CastAndValidate)
- plug(:skip_auth when action == "index")
+ plug(:skip_auth when action == :index)
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.DirectoryOperation
diff --git a/lib/pleroma/web/mastodon_api/controllers/domain_block_controller.ex b/lib/pleroma/web/mastodon_api/controllers/domain_block_controller.ex
index b2e347e..4615794 100755..100644
--- a/lib/pleroma/web/mastodon_api/controllers/domain_block_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/domain_block_controller.ex
@@ -8,7 +8,7 @@ defmodule Pleroma.Web.MastodonAPI.DomainBlockController do
alias Pleroma.User
alias Pleroma.Web.Plugs.OAuthScopesPlug
- plug(Pleroma.Web.ApiSpec.CastAndValidate)
+ plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.DomainBlockOperation
plug(
@@ -27,23 +27,31 @@ defmodule Pleroma.Web.MastodonAPI.DomainBlockController do
end
@doc "POST /api/v1/domain_blocks"
- def create(%{assigns: %{user: blocker}, body_params: %{domain: domain}} = conn, _params) do
+ def create(
+ %{assigns: %{user: blocker}, private: %{open_api_spex: %{body_params: %{domain: domain}}}} =
+ conn,
+ _params
+ ) do
User.block_domain(blocker, domain)
json(conn, %{})
end
- def create(%{assigns: %{user: blocker}} = conn, %{domain: domain}) do
+ def create(%{assigns: %{user: blocker}} = conn, %{"domain" => domain}) do
User.block_domain(blocker, domain)
json(conn, %{})
end
@doc "DELETE /api/v1/domain_blocks"
- def delete(%{assigns: %{user: blocker}, body_params: %{domain: domain}} = conn, _params) do
+ def delete(
+ %{assigns: %{user: blocker}, private: %{open_api_spex: %{body_params: %{domain: domain}}}} =
+ conn,
+ _params
+ ) do
User.unblock_domain(blocker, domain)
json(conn, %{})
end
- def delete(%{assigns: %{user: blocker}} = conn, %{domain: domain}) do
+ def delete(%{assigns: %{user: blocker}} = conn, %{"domain" => domain}) do
User.unblock_domain(blocker, domain)
json(conn, %{})
end
diff --git a/lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex b/lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex
index 1c650eb..1c650eb 100755..100644
--- a/lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex
diff --git a/lib/pleroma/web/mastodon_api/controllers/filter_controller.ex b/lib/pleroma/web/mastodon_api/controllers/filter_controller.ex
index 0959b4b..0959b4b 100755..100644
--- a/lib/pleroma/web/mastodon_api/controllers/filter_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/filter_controller.ex
diff --git a/lib/pleroma/web/mastodon_api/controllers/follow_request_controller.ex b/lib/pleroma/web/mastodon_api/controllers/follow_request_controller.ex
index ba6d074..6eee55d 100755..100644
--- a/lib/pleroma/web/mastodon_api/controllers/follow_request_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/follow_request_controller.ex
@@ -9,7 +9,7 @@ defmodule Pleroma.Web.MastodonAPI.FollowRequestController do
alias Pleroma.Web.CommonAPI
alias Pleroma.Web.Plugs.OAuthScopesPlug
- plug(Pleroma.Web.ApiSpec.CastAndValidate)
+ plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
plug(:assign_follower when action != :index)
action_fallback(:errors)
@@ -44,7 +44,7 @@ defmodule Pleroma.Web.MastodonAPI.FollowRequestController do
end
end
- defp assign_follower(%{params: %{id: id}} = conn, _) do
+ defp assign_follower(%{private: %{open_api_spex: %{params: %{id: id}}}} = conn, _) do
case User.get_cached_by_id(id) do
%User{} = follower -> assign(conn, :follower, follower)
nil -> Pleroma.Web.MastodonAPI.FallbackController.call(conn, {:error, :not_found}) |> halt()
diff --git a/lib/pleroma/web/mastodon_api/controllers/instance_controller.ex b/lib/pleroma/web/mastodon_api/controllers/instance_controller.ex
index 6410e87..3e66490 100755..100644
--- a/lib/pleroma/web/mastodon_api/controllers/instance_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/instance_controller.ex
@@ -7,7 +7,7 @@ defmodule Pleroma.Web.MastodonAPI.InstanceController do
plug(Pleroma.Web.ApiSpec.CastAndValidate)
- plug(:skip_auth when action in [:show, :peers])
+ plug(:skip_auth when action in [:show, :show2, :peers])
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.InstanceOperation
@@ -16,6 +16,11 @@ defmodule Pleroma.Web.MastodonAPI.InstanceController do
render(conn, "show.json")
end
+ @doc "GET /api/v2/instance"
+ def show2(conn, _params) do
+ render(conn, "show2.json")
+ end
+
@doc "GET /api/v1/instance/peers"
def peers(conn, _params) do
json(conn, Pleroma.Stats.get_peers())
diff --git a/lib/pleroma/web/mastodon_api/controllers/list_controller.ex b/lib/pleroma/web/mastodon_api/controllers/list_controller.ex
index 2117aae..3bfc365 100755..100644
--- a/lib/pleroma/web/mastodon_api/controllers/list_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/list_controller.ex
@@ -11,7 +11,7 @@ defmodule Pleroma.Web.MastodonAPI.ListController do
@oauth_read_actions [:index, :show, :list_accounts]
- plug(Pleroma.Web.ApiSpec.CastAndValidate)
+ plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
plug(:list_by_id_and_user when action not in [:index, :create])
plug(OAuthScopesPlug, %{scopes: ["read:lists"]} when action in @oauth_read_actions)
plug(OAuthScopesPlug, %{scopes: ["write:lists"]} when action not in @oauth_read_actions)
@@ -21,25 +21,33 @@ defmodule Pleroma.Web.MastodonAPI.ListController do
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.ListOperation
# GET /api/v1/lists
- def index(%{assigns: %{user: user}} = conn, opts) do
- lists = Pleroma.List.for_user(user, opts)
+ def index(%{assigns: %{user: user}, private: %{open_api_spex: %{params: params}}} = conn, _) do
+ lists = Pleroma.List.for_user(user, params)
render(conn, "index.json", lists: lists)
end
# POST /api/v1/lists
- def create(%{assigns: %{user: user}, body_params: %{title: title}} = conn, _) do
+ def create(
+ %{assigns: %{user: user}, private: %{open_api_spex: %{body_params: %{title: title}}}} =
+ conn,
+ _
+ ) do
with {:ok, %Pleroma.List{} = list} <- Pleroma.List.create(title, user) do
render(conn, "show.json", list: list)
end
end
- # GET /api/v1/lists/:id
+ # GET /api/v1/lists/:idOB
def show(%{assigns: %{list: list}} = conn, _) do
render(conn, "show.json", list: list)
end
# PUT /api/v1/lists/:id
- def update(%{assigns: %{list: list}, body_params: %{title: title}} = conn, _) do
+ def update(
+ %{assigns: %{list: list}, private: %{open_api_spex: %{body_params: %{title: title}}}} =
+ conn,
+ _
+ ) do
with {:ok, list} <- Pleroma.List.rename(list, title) do
render(conn, "show.json", list: list)
end
@@ -62,7 +70,13 @@ defmodule Pleroma.Web.MastodonAPI.ListController do
end
# POST /api/v1/lists/:id/accounts
- def add_to_list(%{assigns: %{list: list}, body_params: %{account_ids: account_ids}} = conn, _) do
+ def add_to_list(
+ %{
+ assigns: %{list: list},
+ private: %{open_api_spex: %{body_params: %{account_ids: account_ids}}}
+ } = conn,
+ _
+ ) do
Enum.each(account_ids, fn account_id ->
with %User{} = followed <- User.get_cached_by_id(account_id) do
Pleroma.List.follow(list, followed)
@@ -74,9 +88,22 @@ defmodule Pleroma.Web.MastodonAPI.ListController do
# DELETE /api/v1/lists/:id/accounts
def remove_from_list(
- %{assigns: %{list: list}, params: %{account_ids: account_ids}} = conn,
+ %{
+ private: %{open_api_spex: %{params: %{account_ids: account_ids}}}
+ } = conn,
_
) do
+ do_remove_from_list(conn, account_ids)
+ end
+
+ def remove_from_list(
+ %{private: %{open_api_spex: %{body_params: %{account_ids: account_ids}}}} = conn,
+ _
+ ) do
+ do_remove_from_list(conn, account_ids)
+ end
+
+ defp do_remove_from_list(%{assigns: %{list: list}} = conn, account_ids) do
Enum.each(account_ids, fn account_id ->
with %User{} = followed <- User.get_cached_by_id(account_id) do
Pleroma.List.unfollow(list, followed)
@@ -86,11 +113,10 @@ defmodule Pleroma.Web.MastodonAPI.ListController do
json(conn, %{})
end
- def remove_from_list(%{body_params: params} = conn, _) do
- remove_from_list(%{conn | params: params}, %{})
- end
-
- defp list_by_id_and_user(%{assigns: %{user: user}, params: %{id: id}} = conn, _) do
+ defp list_by_id_and_user(
+ %{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: id}}}} = conn,
+ _
+ ) do
case Pleroma.List.get(id, user) do
%Pleroma.List{} = list -> assign(conn, :list, list)
nil -> conn |> render_error(:not_found, "List not found") |> halt()
diff --git a/lib/pleroma/web/mastodon_api/controllers/marker_controller.ex b/lib/pleroma/web/mastodon_api/controllers/marker_controller.ex
index 4ad30f3..4ad30f3 100755..100644
--- a/lib/pleroma/web/mastodon_api/controllers/marker_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/marker_controller.ex
diff --git a/lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex
index 0aa7b37..0aa7b37 100755..100644
--- a/lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex
diff --git a/lib/pleroma/web/mastodon_api/controllers/media_controller.ex b/lib/pleroma/web/mastodon_api/controllers/media_controller.ex
index 7d9a63c..056bad8 100755..100644
--- a/lib/pleroma/web/mastodon_api/controllers/media_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/media_controller.ex
@@ -12,7 +12,7 @@ defmodule Pleroma.Web.MastodonAPI.MediaController do
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
plug(Majic.Plug, [pool: Pleroma.MajicPool] when action in [:create, :create2])
- plug(Pleroma.Web.ApiSpec.CastAndValidate)
+ plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
plug(OAuthScopesPlug, %{scopes: ["read:media"]} when action == :show)
plug(OAuthScopesPlug, %{scopes: ["write:media"]} when action != :show)
@@ -20,7 +20,11 @@ defmodule Pleroma.Web.MastodonAPI.MediaController do
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.MediaOperation
@doc "POST /api/v1/media"
- def create(%{assigns: %{user: user}, body_params: %{file: file} = data} = conn, _) do
+ def create(
+ %{assigns: %{user: user}, private: %{open_api_spex: %{body_params: %{file: file} = data}}} =
+ conn,
+ _
+ ) do
with {:ok, object} <-
ActivityPub.upload(
file,
@@ -36,7 +40,11 @@ defmodule Pleroma.Web.MastodonAPI.MediaController do
def create(_conn, _data), do: {:error, :bad_request}
@doc "POST /api/v2/media"
- def create2(%{assigns: %{user: user}, body_params: %{file: file} = data} = conn, _) do
+ def create2(
+ %{assigns: %{user: user}, private: %{open_api_spex: %{body_params: %{file: file} = data}}} =
+ conn,
+ _
+ ) do
with {:ok, object} <-
ActivityPub.upload(
file,
@@ -54,7 +62,15 @@ defmodule Pleroma.Web.MastodonAPI.MediaController do
def create2(_conn, _data), do: {:error, :bad_request}
@doc "PUT /api/v1/media/:id"
- def update(%{assigns: %{user: user}, body_params: %{description: description}} = conn, %{id: id}) do
+ def update(
+ %{
+ assigns: %{user: user},
+ private: %{
+ open_api_spex: %{body_params: %{description: description}, params: %{id: id}}
+ }
+ } = conn,
+ _
+ ) do
with %Object{} = object <- Object.get_by_id(id),
:ok <- Object.authorize_access(object, user),
{:ok, %Object{data: data}} <- Object.update_data(object, %{"name" => description}) do
@@ -67,7 +83,7 @@ defmodule Pleroma.Web.MastodonAPI.MediaController do
def update(conn, data), do: show(conn, data)
@doc "GET /api/v1/media/:id"
- def show(%{assigns: %{user: user}} = conn, %{id: id}) do
+ def show(%{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: id}}}} = conn, _) do
with %Object{data: data, id: object_id} = object <- Object.get_by_id(id),
:ok <- Object.authorize_access(object, user) do
attachment_data = Map.put(data, "id", object_id)
diff --git a/lib/pleroma/web/mastodon_api/controllers/notification_controller.ex b/lib/pleroma/web/mastodon_api/controllers/notification_controller.ex
index a490e83..e305aea 100755..100644
--- a/lib/pleroma/web/mastodon_api/controllers/notification_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/notification_controller.ex
@@ -13,7 +13,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationController do
@oauth_read_actions [:show, :index]
- plug(Pleroma.Web.ApiSpec.CastAndValidate)
+ plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
plug(
OAuthScopesPlug,
@@ -24,8 +24,20 @@ defmodule Pleroma.Web.MastodonAPI.NotificationController do
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.NotificationOperation
+ @default_notification_types ~w{
+ mention
+ follow
+ follow_request
+ reblog
+ favourite
+ move
+ pleroma:emoji_reaction
+ poll
+ update
+ }
+
# GET /api/v1/notifications
- def index(conn, %{account_id: account_id} = params) do
+ def index(%{private: %{open_api_spex: %{params: %{account_id: account_id} = params}}} = conn, _) do
case Pleroma.User.get_cached_by_id(account_id) do
%{ap_id: account_ap_id} ->
params =
@@ -33,7 +45,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationController do
|> Map.delete(:account_id)
|> Map.put(:account_ap_id, account_ap_id)
- index(conn, params)
+ do_get_notifications(conn, params)
_ ->
conn
@@ -42,18 +54,11 @@ defmodule Pleroma.Web.MastodonAPI.NotificationController do
end
end
- @default_notification_types ~w{
- mention
- follow
- follow_request
- reblog
- favourite
- move
- pleroma:emoji_reaction
- poll
- update
- }
- def index(%{assigns: %{user: user}} = conn, params) do
+ def index(%{private: %{open_api_spex: %{params: params}}} = conn, _) do
+ do_get_notifications(conn, params)
+ end
+
+ defp do_get_notifications(%{assigns: %{user: user}} = conn, params) do
params =
Map.new(params, fn {k, v} -> {to_string(k), v} end)
|> Map.put_new("types", Map.get(params, :include_types, @default_notification_types))
@@ -69,7 +74,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationController do
end
# GET /api/v1/notifications/:id
- def show(%{assigns: %{user: user}} = conn, %{id: id}) do
+ def show(%{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: id}}}} = conn, _) do
with {:ok, notification} <- Notification.get(user, id) do
render(conn, "show.json", notification: notification, for: user)
else
@@ -88,8 +93,20 @@ defmodule Pleroma.Web.MastodonAPI.NotificationController do
# POST /api/v1/notifications/:id/dismiss
- def dismiss(%{assigns: %{user: user}} = conn, %{id: id} = _params) do
- with {:ok, _notif} <- Notification.dismiss(user, id) do
+ def dismiss(%{private: %{open_api_spex: %{params: %{id: id}}}} = conn, _) do
+ do_dismiss(conn, id)
+ end
+
+ # POST /api/v1/notifications/dismiss (deprecated)
+ def dismiss_via_body(
+ %{private: %{open_api_spex: %{body_params: %{id: id}}}} = conn,
+ _
+ ) do
+ do_dismiss(conn, id)
+ end
+
+ defp do_dismiss(%{assigns: %{user: user}} = conn, notification_id) do
+ with {:ok, _notif} <- Notification.dismiss(user, notification_id) do
json(conn, %{})
else
{:error, reason} ->
@@ -99,13 +116,11 @@ defmodule Pleroma.Web.MastodonAPI.NotificationController do
end
end
- # POST /api/v1/notifications/dismiss (deprecated)
- def dismiss_via_body(%{body_params: params} = conn, _) do
- dismiss(conn, params)
- end
-
# DELETE /api/v1/notifications/destroy_multiple
- def destroy_multiple(%{assigns: %{user: user}} = conn, %{ids: ids} = _params) do
+ def destroy_multiple(
+ %{assigns: %{user: user}, private: %{open_api_spex: %{params: %{ids: ids}}}} = conn,
+ _
+ ) do
Notification.destroy_multiple(user, ids)
json(conn, %{})
end
diff --git a/lib/pleroma/web/mastodon_api/controllers/poll_controller.ex b/lib/pleroma/web/mastodon_api/controllers/poll_controller.ex
index 002c210..b074ee4 100755..100644
--- a/lib/pleroma/web/mastodon_api/controllers/poll_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/poll_controller.ex
@@ -15,7 +15,7 @@ defmodule Pleroma.Web.MastodonAPI.PollController do
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
- plug(Pleroma.Web.ApiSpec.CastAndValidate)
+ plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
plug(
OAuthScopesPlug,
@@ -29,7 +29,7 @@ defmodule Pleroma.Web.MastodonAPI.PollController do
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
@doc "GET /api/v1/polls/:id"
- def show(%{assigns: %{user: user}} = conn, %{id: id}) do
+ def show(%{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: id}}}} = conn, _) do
with %Object{} = object <- Object.get_by_id_and_maybe_refetch(id, interval: 60),
%Activity{} = activity <- Activity.get_create_by_object_ap_id(object.data["id"]),
true <- Visibility.visible_for_user?(activity, user) do
@@ -41,7 +41,13 @@ defmodule Pleroma.Web.MastodonAPI.PollController do
end
@doc "POST /api/v1/polls/:id/votes"
- def vote(%{assigns: %{user: user}, body_params: %{choices: choices}} = conn, %{id: id}) do
+ def vote(
+ %{
+ assigns: %{user: user},
+ private: %{open_api_spex: %{body_params: %{choices: choices}, params: %{id: id}}}
+ } = conn,
+ _
+ ) do
with %Object{data: %{"type" => "Question"}} = object <- Object.get_by_id(id),
%Activity{} = activity <- Activity.get_create_by_object_ap_id(object.data["id"]),
true <- Visibility.visible_for_user?(activity, user),
diff --git a/lib/pleroma/web/mastodon_api/controllers/report_controller.ex b/lib/pleroma/web/mastodon_api/controllers/report_controller.ex
index 3db80d7..3db80d7 100755..100644
--- a/lib/pleroma/web/mastodon_api/controllers/report_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/report_controller.ex
diff --git a/lib/pleroma/web/mastodon_api/controllers/scheduled_activity_controller.ex b/lib/pleroma/web/mastodon_api/controllers/scheduled_activity_controller.ex
index 0392fce..1b7095e 100755..100644
--- a/lib/pleroma/web/mastodon_api/controllers/scheduled_activity_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/scheduled_activity_controller.ex
@@ -13,7 +13,7 @@ defmodule Pleroma.Web.MastodonAPI.ScheduledActivityController do
@oauth_read_actions [:show, :index]
- plug(Pleroma.Web.ApiSpec.CastAndValidate)
+ plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
plug(OAuthScopesPlug, %{scopes: ["read:statuses"]} when action in @oauth_read_actions)
plug(OAuthScopesPlug, %{scopes: ["write:statuses"]} when action not in @oauth_read_actions)
plug(:assign_scheduled_activity when action != :index)
@@ -23,7 +23,7 @@ defmodule Pleroma.Web.MastodonAPI.ScheduledActivityController do
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.ScheduledActivityOperation
@doc "GET /api/v1/scheduled_statuses"
- def index(%{assigns: %{user: user}} = conn, params) do
+ def index(%{assigns: %{user: user}, private: %{open_api_spex: %{params: params}}} = conn, _) do
params = Map.new(params, fn {key, value} -> {to_string(key), value} end)
with scheduled_activities <- MastodonAPI.get_scheduled_activities(user, params) do
@@ -39,7 +39,13 @@ defmodule Pleroma.Web.MastodonAPI.ScheduledActivityController do
end
@doc "PUT /api/v1/scheduled_statuses/:id"
- def update(%{assigns: %{scheduled_activity: scheduled_activity}, body_params: params} = conn, _) do
+ def update(
+ %{
+ assigns: %{scheduled_activity: scheduled_activity},
+ private: %{open_api_spex: %{body_params: params}}
+ } = conn,
+ _
+ ) do
with {:ok, scheduled_activity} <- ScheduledActivity.update(scheduled_activity, params) do
render(conn, "show.json", scheduled_activity: scheduled_activity)
end
@@ -52,7 +58,10 @@ defmodule Pleroma.Web.MastodonAPI.ScheduledActivityController do
end
end
- defp assign_scheduled_activity(%{assigns: %{user: user}, params: %{id: id}} = conn, _) do
+ defp assign_scheduled_activity(
+ %{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: id}}}} = conn,
+ _
+ ) do
case ScheduledActivity.get(user, id) do
%ScheduledActivity{} = activity -> assign(conn, :scheduled_activity, activity)
nil -> Pleroma.Web.MastodonAPI.FallbackController.call(conn, {:error, :not_found}) |> halt()
diff --git a/lib/pleroma/web/mastodon_api/controllers/search_controller.ex b/lib/pleroma/web/mastodon_api/controllers/search_controller.ex
index 5e6e047..628aa31 100755..100644
--- a/lib/pleroma/web/mastodon_api/controllers/search_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/search_controller.ex
@@ -5,7 +5,6 @@
defmodule Pleroma.Web.MastodonAPI.SearchController do
use Pleroma.Web, :controller
- alias Pleroma.Activity
alias Pleroma.Repo
alias Pleroma.User
alias Pleroma.Web.ControllerHelper
@@ -19,7 +18,7 @@ defmodule Pleroma.Web.MastodonAPI.SearchController do
@search_limit 40
- plug(Pleroma.Web.ApiSpec.CastAndValidate)
+ plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
# Note: Mastodon doesn't allow unauthenticated access (requires read:accounts / read:search)
plug(OAuthScopesPlug, %{scopes: ["read:search"], fallback: :proceed_unauthenticated})
@@ -30,7 +29,11 @@ defmodule Pleroma.Web.MastodonAPI.SearchController do
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.SearchOperation
- def account_search(%{assigns: %{user: user}} = conn, %{q: query} = params) do
+ def account_search(
+ %{assigns: %{user: user}, private: %{open_api_spex: %{params: %{q: query} = params}}} =
+ conn,
+ _
+ ) do
accounts = User.search(query, search_options(params, user))
conn
@@ -45,7 +48,12 @@ defmodule Pleroma.Web.MastodonAPI.SearchController do
def search2(conn, params), do: do_search(:v2, conn, params)
def search(conn, params), do: do_search(:v1, conn, params)
- defp do_search(version, %{assigns: %{user: user}} = conn, %{q: query} = params) do
+ defp do_search(
+ version,
+ %{assigns: %{user: user}, private: %{open_api_spex: %{params: %{q: query} = params}}} =
+ conn,
+ _
+ ) do
query = String.trim(query)
options = search_options(params, user)
timeout = Keyword.get(Repo.config(), :timeout, 15_000)
@@ -100,7 +108,7 @@ defmodule Pleroma.Web.MastodonAPI.SearchController do
end
defp resource_search(_, "statuses", query, options) do
- statuses = with_fallback(fn -> Activity.search(options[:for_user], query, options) end)
+ statuses = with_fallback(fn -> Pleroma.Search.search(query, options) end)
StatusView.render("index.json",
activities: statuses,
@@ -148,7 +156,7 @@ defmodule Pleroma.Web.MastodonAPI.SearchController do
tags
end
- Pleroma.Pagination.paginate(tags, options)
+ Pleroma.Pagination.paginate_list(tags, options)
end
defp add_joined_tag(tags) do
diff --git a/lib/pleroma/web/mastodon_api/controllers/status_controller.ex b/lib/pleroma/web/mastodon_api/controllers/status_controller.ex
index e594ea4..83e1bee 100755..100644
--- a/lib/pleroma/web/mastodon_api/controllers/status_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/status_controller.ex
@@ -12,6 +12,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
alias Pleroma.Activity
alias Pleroma.Bookmark
+ alias Pleroma.BookmarkFolder
alias Pleroma.Object
alias Pleroma.Repo
alias Pleroma.ScheduledActivity
@@ -25,7 +26,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
alias Pleroma.Web.Plugs.OAuthScopesPlug
alias Pleroma.Web.Plugs.RateLimiter
- plug(Pleroma.Web.ApiSpec.CastAndValidate)
+ plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
plug(:skip_public_check when action in [:index, :show])
@@ -37,7 +38,6 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
when action in [
:index,
:show,
- :card,
:context,
:show_history,
:show_source
@@ -110,7 +110,11 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
`ids` query param is required
"""
- def index(%{assigns: %{user: user}} = conn, %{ids: ids} = params) do
+ def index(
+ %{assigns: %{user: user}, private: %{open_api_spex: %{params: %{ids: ids} = params}}} =
+ conn,
+ _
+ ) do
limit = 100
activities =
@@ -134,7 +138,9 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
def create(
%{
assigns: %{user: user},
- body_params: %{status: _, scheduled_at: scheduled_at} = params
+ private: %{
+ open_api_spex: %{body_params: %{status: _, scheduled_at: scheduled_at} = params}
+ }
} = conn,
_
)
@@ -156,7 +162,13 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
else
{:far_enough, _} ->
params = Map.drop(params, [:scheduled_at])
- create(%Plug.Conn{conn | body_params: params}, %{})
+
+ put_in(
+ conn,
+ [Access.key(:private), Access.key(:open_api_spex), Access.key(:body_params)],
+ params
+ )
+ |> do_create
error ->
error
@@ -164,7 +176,35 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
end
# Creates a regular status
- def create(%{assigns: %{user: user}, body_params: %{status: _} = params} = conn, _) do
+ def create(
+ %{
+ private: %{open_api_spex: %{body_params: %{status: _}}}
+ } = conn,
+ _
+ ) do
+ do_create(conn)
+ end
+
+ def create(
+ %{
+ assigns: %{user: _user},
+ private: %{open_api_spex: %{body_params: %{media_ids: _} = params}}
+ } = conn,
+ _
+ ) do
+ params = Map.put(params, :status, "")
+
+ put_in(
+ conn,
+ [Access.key(:private), Access.key(:open_api_spex), Access.key(:body_params)],
+ params
+ )
+ |> do_create
+ end
+
+ defp do_create(
+ %{assigns: %{user: user}, private: %{open_api_spex: %{body_params: params}}} = conn
+ ) do
params =
Map.put(params, :in_reply_to_status_id, params[:in_reply_to_id])
|> put_application(conn)
@@ -189,13 +229,11 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
end
end
- def create(%{assigns: %{user: _user}, body_params: %{media_ids: _} = params} = conn, _) do
- params = Map.put(params, :status, "")
- create(%Plug.Conn{conn | body_params: params}, %{})
- end
-
@doc "GET /api/v1/statuses/:id/history"
- def show_history(%{assigns: assigns} = conn, %{id: id} = params) do
+ def show_history(
+ %{assigns: assigns, private: %{open_api_spex: %{params: %{id: id} = params}}} = conn,
+ _
+ ) do
with user = assigns[:user],
%Activity{} = activity <- Activity.get_by_id_with_object(id),
true <- Visibility.visible_for_user?(activity, user) do
@@ -211,7 +249,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
end
@doc "GET /api/v1/statuses/:id/source"
- def show_source(%{assigns: assigns} = conn, %{id: id} = _params) do
+ def show_source(%{assigns: assigns, private: %{open_api_spex: %{params: %{id: id}}}} = conn, _) do
with user = assigns[:user],
%Activity{} = activity <- Activity.get_by_id_with_object(id),
true <- Visibility.visible_for_user?(activity, user) do
@@ -225,7 +263,13 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
end
@doc "PUT /api/v1/statuses/:id"
- def update(%{assigns: %{user: user}, body_params: body_params} = conn, %{id: id} = params) do
+ def update(
+ %{
+ assigns: %{user: user},
+ private: %{open_api_spex: %{body_params: body_params, params: %{id: id} = params}}
+ } = conn,
+ _
+ ) do
with {_, %Activity{}} = {_, activity} <- {:activity, Activity.get_by_id_with_object(id)},
{_, true} <- {:visible, Visibility.visible_for_user?(activity, user)},
{_, true} <- {:is_create, activity.data["type"] == "Create"},
@@ -248,7 +292,11 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
end
@doc "GET /api/v1/statuses/:id"
- def show(%{assigns: %{user: user}} = conn, %{id: id} = params) do
+ def show(
+ %{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: id} = params}}} =
+ conn,
+ _
+ ) do
with %Activity{} = activity <- Activity.get_by_id_with_object(id),
true <- Visibility.visible_for_user?(activity, user) do
try_render(conn, "show.json",
@@ -263,7 +311,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
end
@doc "DELETE /api/v1/statuses/:id"
- def delete(%{assigns: %{user: user}} = conn, %{id: id}) do
+ def delete(%{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: id}}}} = conn, _) do
with %Activity{} = activity <- Activity.get_by_id_with_object(id),
{:ok, %Activity{}} <- CommonAPI.delete(id, user) do
try_render(conn, "show.json",
@@ -278,7 +326,13 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
end
@doc "POST /api/v1/statuses/:id/reblog"
- def reblog(%{assigns: %{user: user}, body_params: params} = conn, %{id: ap_id_or_id}) do
+ def reblog(
+ %{
+ assigns: %{user: user},
+ private: %{open_api_spex: %{body_params: params, params: %{id: ap_id_or_id}}}
+ } = conn,
+ _
+ ) do
with {:ok, announce} <- CommonAPI.repeat(ap_id_or_id, user, params),
%Activity{} = announce <- Activity.normalize(announce.data) do
try_render(conn, "show.json", %{activity: announce, for: user, as: :activity})
@@ -286,7 +340,11 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
end
@doc "POST /api/v1/statuses/:id/unreblog"
- def unreblog(%{assigns: %{user: user}} = conn, %{id: activity_id}) do
+ def unreblog(
+ %{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: activity_id}}}} =
+ conn,
+ _
+ ) do
with {:ok, _unannounce} <- CommonAPI.unrepeat(activity_id, user),
%Activity{} = activity <- Activity.get_by_id(activity_id) do
try_render(conn, "show.json", %{activity: activity, for: user, as: :activity})
@@ -294,7 +352,11 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
end
@doc "POST /api/v1/statuses/:id/favourite"
- def favourite(%{assigns: %{user: user}} = conn, %{id: activity_id}) do
+ def favourite(
+ %{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: activity_id}}}} =
+ conn,
+ _
+ ) do
with {:ok, _fav} <- CommonAPI.favorite(user, activity_id),
%Activity{} = activity <- Activity.get_by_id(activity_id) do
try_render(conn, "show.json", activity: activity, for: user, as: :activity)
@@ -302,7 +364,11 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
end
@doc "POST /api/v1/statuses/:id/unfavourite"
- def unfavourite(%{assigns: %{user: user}} = conn, %{id: activity_id}) do
+ def unfavourite(
+ %{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: activity_id}}}} =
+ conn,
+ _
+ ) do
with {:ok, _unfav} <- CommonAPI.unfavorite(activity_id, user),
%Activity{} = activity <- Activity.get_by_id(activity_id) do
try_render(conn, "show.json", activity: activity, for: user, as: :activity)
@@ -310,7 +376,11 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
end
@doc "POST /api/v1/statuses/:id/pin"
- def pin(%{assigns: %{user: user}} = conn, %{id: ap_id_or_id}) do
+ def pin(
+ %{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: ap_id_or_id}}}} =
+ conn,
+ _
+ ) do
with {:ok, activity} <- CommonAPI.pin(ap_id_or_id, user) do
try_render(conn, "show.json", activity: activity, for: user, as: :activity)
else
@@ -329,24 +399,43 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
end
@doc "POST /api/v1/statuses/:id/unpin"
- def unpin(%{assigns: %{user: user}} = conn, %{id: ap_id_or_id}) do
+ def unpin(
+ %{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: ap_id_or_id}}}} =
+ conn,
+ _
+ ) do
with {:ok, activity} <- CommonAPI.unpin(ap_id_or_id, user) do
try_render(conn, "show.json", activity: activity, for: user, as: :activity)
end
end
@doc "POST /api/v1/statuses/:id/bookmark"
- def bookmark(%{assigns: %{user: user}} = conn, %{id: id}) do
+ def bookmark(
+ %{
+ assigns: %{user: user},
+ private: %{open_api_spex: %{body_params: body_params, params: %{id: id}}}
+ } = conn,
+ _
+ ) do
with %Activity{} = activity <- Activity.get_by_id_with_object(id),
%User{} = user <- User.get_cached_by_nickname(user.nickname),
true <- Visibility.visible_for_user?(activity, user),
- {:ok, _bookmark} <- Bookmark.create(user.id, activity.id) do
+ folder_id <- Map.get(body_params, :folder_id, nil),
+ folder_id <-
+ if(folder_id && BookmarkFolder.belongs_to_user?(folder_id, user.id),
+ do: folder_id,
+ else: nil
+ ),
+ {:ok, _bookmark} <- Bookmark.create(user.id, activity.id, folder_id) do
try_render(conn, "show.json", activity: activity, for: user, as: :activity)
end
end
@doc "POST /api/v1/statuses/:id/unbookmark"
- def unbookmark(%{assigns: %{user: user}} = conn, %{id: id}) do
+ def unbookmark(
+ %{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: id}}}} = conn,
+ _
+ ) do
with %Activity{} = activity <- Activity.get_by_id_with_object(id),
%User{} = user <- User.get_cached_by_nickname(user.nickname),
true <- Visibility.visible_for_user?(activity, user),
@@ -356,7 +445,13 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
end
@doc "POST /api/v1/statuses/:id/mute"
- def mute_conversation(%{assigns: %{user: user}, body_params: params} = conn, %{id: id}) do
+ def mute_conversation(
+ %{
+ assigns: %{user: user},
+ private: %{open_api_spex: %{body_params: params, params: %{id: id}}}
+ } = conn,
+ _
+ ) do
with %Activity{} = activity <- Activity.get_by_id(id),
{:ok, activity} <- CommonAPI.add_mute(user, activity, params) do
try_render(conn, "show.json", activity: activity, for: user, as: :activity)
@@ -364,27 +459,24 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
end
@doc "POST /api/v1/statuses/:id/unmute"
- def unmute_conversation(%{assigns: %{user: user}} = conn, %{id: id}) do
+ def unmute_conversation(
+ %{
+ assigns: %{user: user},
+ private: %{open_api_spex: %{params: %{id: id}}}
+ } = conn,
+ _
+ ) do
with %Activity{} = activity <- Activity.get_by_id(id),
{:ok, activity} <- CommonAPI.remove_mute(user, activity) do
try_render(conn, "show.json", activity: activity, for: user, as: :activity)
end
end
- @doc "GET /api/v1/statuses/:id/card"
- @deprecated "https://github.com/tootsuite/mastodon/pull/11213"
- def card(%{assigns: %{user: user}} = conn, %{id: status_id}) do
- with %Activity{} = activity <- Activity.get_by_id(status_id),
- true <- Visibility.visible_for_user?(activity, user) do
- data = Pleroma.Web.RichMedia.Helpers.fetch_data_for_activity(activity)
- render(conn, "card.json", data)
- else
- _ -> render_error(conn, :not_found, "Record not found")
- end
- end
-
@doc "GET /api/v1/statuses/:id/favourited_by"
- def favourited_by(%{assigns: %{user: user}} = conn, %{id: id}) do
+ def favourited_by(
+ %{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: id}}}} = conn,
+ _
+ ) do
with true <- Pleroma.Config.get([:instance, :show_reactions]),
%Activity{} = activity <- Activity.get_by_id_with_object(id),
{:visible, true} <- {:visible, Visibility.visible_for_user?(activity, user)},
@@ -405,7 +497,10 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
end
@doc "GET /api/v1/statuses/:id/reblogged_by"
- def reblogged_by(%{assigns: %{user: user}} = conn, %{id: id}) do
+ def reblogged_by(
+ %{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: id}}}} = conn,
+ _
+ ) do
with %Activity{} = activity <- Activity.get_by_id_with_object(id),
{:visible, true} <- {:visible, Visibility.visible_for_user?(activity, user)},
%Object{data: %{"announcements" => announces, "id" => ap_id}} <-
@@ -437,7 +532,10 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
end
@doc "GET /api/v1/statuses/:id/context"
- def context(%{assigns: %{user: user}} = conn, %{id: id}) do
+ def context(
+ %{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: id}}}} = conn,
+ _
+ ) do
with %Activity{} = activity <- Activity.get_by_id(id) do
activities =
ActivityPub.fetch_activities_for_context(activity.data["context"], %{
@@ -451,7 +549,10 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
end
@doc "GET /api/v1/favourites"
- def favourites(%{assigns: %{user: %User{} = user}} = conn, params) do
+ def favourites(
+ %{assigns: %{user: %User{} = user}, private: %{open_api_spex: %{params: params}}} = conn,
+ _
+ ) do
activities = ActivityPub.fetch_favourites(user, params)
conn
@@ -464,12 +565,13 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
end
@doc "GET /api/v1/bookmarks"
- def bookmarks(%{assigns: %{user: user}} = conn, params) do
+ def bookmarks(%{assigns: %{user: user}, private: %{open_api_spex: %{params: params}}} = conn, _) do
user = User.get_cached_by_id(user.id)
+ folder_id = Map.get(params, :folder_id)
bookmarks =
user.id
- |> Bookmark.for_user_query()
+ |> Bookmark.for_user_query(folder_id)
|> Pleroma.Pagination.fetch_paginated(params)
activities =
diff --git a/lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex b/lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex
index 9cc0071..9cc0071 100755..100644
--- a/lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex
diff --git a/lib/pleroma/web/mastodon_api/controllers/suggestion_controller.ex b/lib/pleroma/web/mastodon_api/controllers/suggestion_controller.ex
index 69ae70a..69ae70a 100755..100644
--- a/lib/pleroma/web/mastodon_api/controllers/suggestion_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/suggestion_controller.ex
diff --git a/lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex b/lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex
index 293c61b..293c61b 100755..100644
--- a/lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex
diff --git a/lib/pleroma/web/mastodon_api/mastodon_api.ex b/lib/pleroma/web/mastodon_api/mastodon_api.ex
index 467dc2f..467dc2f 100755..100644
--- a/lib/pleroma/web/mastodon_api/mastodon_api.ex
+++ b/lib/pleroma/web/mastodon_api/mastodon_api.ex
diff --git a/lib/pleroma/web/mastodon_api/views/account_view.ex b/lib/pleroma/web/mastodon_api/views/account_view.ex
index cc3e358..267c3e3 100755..100644
--- a/lib/pleroma/web/mastodon_api/views/account_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/account_view.ex
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.MastodonAPI.AccountView do
@@ -194,6 +194,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
end
defp do_render("show.json", %{user: user} = opts) do
+ self = opts[:for] == user
+
user = User.sanitize_html(user, User.html_filter_policy(opts[:for]))
display_name = user.name || user.nickname
@@ -203,16 +205,16 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
header_static = User.banner_url(user) |> MediaProxy.preview_url(static: true)
following_count =
- if !user.hide_follows_count or !user.hide_follows or opts[:for] == user,
+ if !user.hide_follows_count or !user.hide_follows or self,
do: user.following_count,
else: 0
followers_count =
- if !user.hide_followers_count or !user.hide_followers or opts[:for] == user,
+ if !user.hide_followers_count or !user.hide_followers or self,
do: user.follower_count,
else: 0
- bot = user.actor_type == "Service"
+ bot = bot?(user)
emojis =
Enum.map(user.emoji, fn {shortcode, raw_url} ->
@@ -249,6 +251,10 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
nil
end
+ last_status_at =
+ user.last_status_at &&
+ user.last_status_at |> NaiveDateTime.to_date() |> Date.to_iso8601()
+
%{
id: to_string(user.id),
username: username_from_nickname(user.nickname),
@@ -277,7 +283,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
actor_type: user.actor_type
}
},
- last_status_at: user.last_status_at,
+ last_status_at: last_status_at,
# Pleroma extensions
# Note: it's insecure to output :email but fully-qualified nickname may serve as safe stub
@@ -464,4 +470,12 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
defp image_url(%{"url" => [%{"href" => href} | _]}), do: href
defp image_url(_), do: nil
+
+ defp bot?(user) do
+ # Because older and/or Mastodon clients may not recognize a Group actor properly,
+ # and currently the group actor can only boost things, we should let these clients
+ # think groups are bots.
+ # See https://git.pleroma.social/pleroma/pleroma-meta/-/issues/14
+ user.actor_type == "Service" || user.actor_type == "Group"
+ end
end
diff --git a/lib/pleroma/web/mastodon_api/views/announcement_view.ex b/lib/pleroma/web/mastodon_api/views/announcement_view.ex
index 93fdfb1..93fdfb1 100755..100644
--- a/lib/pleroma/web/mastodon_api/views/announcement_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/announcement_view.ex
diff --git a/lib/pleroma/web/mastodon_api/views/app_view.ex b/lib/pleroma/web/mastodon_api/views/app_view.ex
index 92cccd4..92cccd4 100755..100644
--- a/lib/pleroma/web/mastodon_api/views/app_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/app_view.ex
diff --git a/lib/pleroma/web/mastodon_api/views/conversation_view.ex b/lib/pleroma/web/mastodon_api/views/conversation_view.ex
index f6577cd..f6577cd 100755..100644
--- a/lib/pleroma/web/mastodon_api/views/conversation_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/conversation_view.ex
diff --git a/lib/pleroma/web/mastodon_api/views/custom_emoji_view.ex b/lib/pleroma/web/mastodon_api/views/custom_emoji_view.ex
index cd59ab9..cd59ab9 100755..100644
--- a/lib/pleroma/web/mastodon_api/views/custom_emoji_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/custom_emoji_view.ex
diff --git a/lib/pleroma/web/mastodon_api/views/filter_view.ex b/lib/pleroma/web/mastodon_api/views/filter_view.ex
index 0c97061..0c97061 100755..100644
--- a/lib/pleroma/web/mastodon_api/views/filter_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/filter_view.ex
diff --git a/lib/pleroma/web/mastodon_api/views/follow_request_view.ex b/lib/pleroma/web/mastodon_api/views/follow_request_view.ex
index 5e50bc2..5e50bc2 100755..100644
--- a/lib/pleroma/web/mastodon_api/views/follow_request_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/follow_request_view.ex
diff --git a/lib/pleroma/web/mastodon_api/views/instance_view.ex b/lib/pleroma/web/mastodon_api/views/instance_view.ex
index abf7f29..890dd39 100755..100644
--- a/lib/pleroma/web/mastodon_api/views/instance_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/instance_view.ex
@@ -13,12 +13,11 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do
def render("show.json", _) do
instance = Config.get(:instance)
- %{
- uri: Pleroma.Web.Endpoint.url(),
- title: Keyword.get(instance, :name),
+ common_information(instance)
+ |> Map.merge(%{
+ uri: Pleroma.Web.WebFinger.host(),
description: Keyword.get(instance, :description),
short_description: Keyword.get(instance, :short_description),
- version: "#{@mastodon_api_level} (compatible; #{Pleroma.Application.named_version()})",
email: Keyword.get(instance, :email),
urls: %{
streaming_api: Pleroma.Web.Endpoint.websocket_url()
@@ -27,9 +26,10 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do
thumbnail:
URI.merge(Pleroma.Web.Endpoint.url(), Keyword.get(instance, :instance_thumbnail))
|> to_string,
- languages: Keyword.get(instance, :languages, ["en"]),
registrations: Keyword.get(instance, :registrations_open),
approval_required: Keyword.get(instance, :account_approval_required),
+ contact_account: contact_account(Keyword.get(instance, :contact_username)),
+ configuration: configuration(),
# Extra (not present in Mastodon):
max_toot_chars: Keyword.get(instance, :limit),
max_media_attachments: Keyword.get(instance, :max_media_attachments),
@@ -41,19 +41,47 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do
background_image: Pleroma.Web.Endpoint.url() <> Keyword.get(instance, :background_image),
shout_limit: Config.get([:shout, :limit]),
description_limit: Keyword.get(instance, :description_limit),
- pleroma: %{
- metadata: %{
- account_activation_required: Keyword.get(instance, :account_activation_required),
- features: features(),
- federation: federation(),
- fields_limits: fields_limits(),
- post_formats: Config.get([:instance, :allowed_post_formats]),
- birthday_required: Config.get([:instance, :birthday_required]),
- birthday_min_age: Config.get([:instance, :birthday_min_age])
- },
- stats: %{mau: Pleroma.User.active_user_count()},
- vapid_public_key: Keyword.get(Pleroma.Web.Push.vapid_config(), :public_key)
- }
+ chat_limit: Keyword.get(instance, :chat_limit),
+ pleroma: pleroma_configuration(instance)
+ })
+ end
+
+ def render("show2.json", _) do
+ instance = Config.get(:instance)
+
+ common_information(instance)
+ |> Map.merge(%{
+ domain: Pleroma.Web.WebFinger.host(),
+ source_url: Pleroma.Application.repository(),
+ description: Keyword.get(instance, :short_description),
+ usage: %{users: %{active_month: Pleroma.User.active_user_count()}},
+ thumbnail: %{
+ url:
+ URI.merge(Pleroma.Web.Endpoint.url(), Keyword.get(instance, :instance_thumbnail))
+ |> to_string
+ },
+ configuration: configuration2(),
+ registrations: %{
+ enabled: Keyword.get(instance, :registrations_open),
+ approval_required: Keyword.get(instance, :account_approval_required),
+ message: nil,
+ url: nil
+ },
+ contact: %{
+ email: Keyword.get(instance, :email),
+ account: contact_account(Keyword.get(instance, :contact_username))
+ },
+ # Extra (not present in Mastodon):
+ pleroma: pleroma_configuration2(instance)
+ })
+ end
+
+ defp common_information(instance) do
+ %{
+ title: Keyword.get(instance, :name),
+ version: "#{@mastodon_api_level} (compatible; #{Pleroma.Application.named_version()})",
+ languages: Keyword.get(instance, :languages, ["en"]),
+ rules: []
}
end
@@ -69,6 +97,7 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do
"multifetch",
"pleroma:api/v1/notifications:include_types_filter",
"editing",
+ "quote_posting",
if Config.get([:activitypub, :blockers_visible]) do
"blockers_visible"
end,
@@ -92,6 +121,7 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do
"safe_dm_mentions"
end,
"pleroma_emoji_reactions",
+ "pleroma_custom_emoji_reactions",
"pleroma_chat_messages",
if Config.get([:instance, :show_reactions]) do
"exposable_reactions"
@@ -99,7 +129,9 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do
if Config.get([:instance, :profile_directory]) do
"profile_directory"
end,
- "pleroma:get:main/ostatus"
+ "pleroma:get:main/ostatus",
+ "pleroma:group_actors",
+ "pleroma:bookmark_folders"
]
|> Enum.filter(& &1)
end
@@ -131,7 +163,7 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do
|> Map.put(:enabled, Config.get([:instance, :federating]))
end
- def fields_limits do
+ defp fields_limits do
%{
max_fields: Config.get([:instance, :max_account_fields]),
max_remote_fields: Config.get([:instance, :max_remote_account_fields]),
@@ -139,4 +171,94 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do
value_length: Config.get([:instance, :account_field_value_length])
}
end
+
+ defp contact_account(nil), do: nil
+
+ defp contact_account("@" <> username) do
+ contact_account(username)
+ end
+
+ defp contact_account(username) do
+ user = Pleroma.User.get_cached_by_nickname(username)
+
+ if user do
+ Pleroma.Web.MastodonAPI.AccountView.render("show.json", %{user: user, for: nil})
+ else
+ nil
+ end
+ end
+
+ defp configuration do
+ %{
+ accounts: %{
+ max_featured_tags: 0
+ },
+ statuses: %{
+ max_characters: Config.get([:instance, :limit]),
+ max_media_attachments: Config.get([:instance, :max_media_attachments])
+ },
+ media_attachments: %{
+ image_size_limit: Config.get([:instance, :upload_limit]),
+ video_size_limit: Config.get([:instance, :upload_limit]),
+ supported_mime_types: ["application/octet-stream"]
+ },
+ polls: %{
+ max_options: Config.get([:instance, :poll_limits, :max_options]),
+ max_characters_per_option: Config.get([:instance, :poll_limits, :max_option_chars]),
+ min_expiration: Config.get([:instance, :poll_limits, :min_expiration]),
+ max_expiration: Config.get([:instance, :poll_limits, :max_expiration])
+ }
+ }
+ end
+
+ defp configuration2 do
+ configuration()
+ |> put_in([:accounts, :max_pinned_statuses], Config.get([:instance, :max_pinned_statuses], 0))
+ |> put_in([:statuses, :characters_reserved_per_url], 0)
+ |> Map.merge(%{
+ urls: %{
+ streaming: Pleroma.Web.Endpoint.websocket_url(),
+ status: Config.get([:instance, :status_page])
+ },
+ vapid: %{
+ public_key: Keyword.get(Pleroma.Web.Push.vapid_config(), :public_key)
+ }
+ })
+ end
+
+ defp pleroma_configuration(instance) do
+ %{
+ metadata: %{
+ account_activation_required: Keyword.get(instance, :account_activation_required),
+ features: features(),
+ federation: federation(),
+ fields_limits: fields_limits(),
+ post_formats: Config.get([:instance, :allowed_post_formats]),
+ birthday_required: Config.get([:instance, :birthday_required]),
+ birthday_min_age: Config.get([:instance, :birthday_min_age])
+ },
+ stats: %{mau: Pleroma.User.active_user_count()},
+ vapid_public_key: Keyword.get(Pleroma.Web.Push.vapid_config(), :public_key)
+ }
+ end
+
+ defp pleroma_configuration2(instance) do
+ configuration = pleroma_configuration(instance)
+
+ configuration
+ |> Map.merge(%{
+ metadata:
+ configuration.metadata
+ |> Map.merge(%{
+ avatar_upload_limit: Keyword.get(instance, :avatar_upload_limit),
+ background_upload_limit: Keyword.get(instance, :background_upload_limit),
+ banner_upload_limit: Keyword.get(instance, :banner_upload_limit),
+ background_image:
+ Pleroma.Web.Endpoint.url() <> Keyword.get(instance, :background_image),
+ chat_limit: Keyword.get(instance, :chat_limit),
+ description_limit: Keyword.get(instance, :description_limit),
+ shout_limit: Config.get([:shout, :limit])
+ })
+ })
+ end
end
diff --git a/lib/pleroma/web/mastodon_api/views/list_view.ex b/lib/pleroma/web/mastodon_api/views/list_view.ex
index a7ae7c5..a7ae7c5 100755..100644
--- a/lib/pleroma/web/mastodon_api/views/list_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/list_view.ex
diff --git a/lib/pleroma/web/mastodon_api/views/marker_view.ex b/lib/pleroma/web/mastodon_api/views/marker_view.ex
index 944769b..944769b 100755..100644
--- a/lib/pleroma/web/mastodon_api/views/marker_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/marker_view.ex
diff --git a/lib/pleroma/web/mastodon_api/views/media_view.ex b/lib/pleroma/web/mastodon_api/views/media_view.ex
index 4db72de..4db72de 100755..100644
--- a/lib/pleroma/web/mastodon_api/views/media_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/media_view.ex
diff --git a/lib/pleroma/web/mastodon_api/views/notification_view.ex b/lib/pleroma/web/mastodon_api/views/notification_view.ex
index b5b5b23..2a51f37 100755..100644
--- a/lib/pleroma/web/mastodon_api/views/notification_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/notification_view.ex
@@ -17,6 +17,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationView do
alias Pleroma.Web.MastodonAPI.AccountView
alias Pleroma.Web.MastodonAPI.NotificationView
alias Pleroma.Web.MastodonAPI.StatusView
+ alias Pleroma.Web.MediaProxy
alias Pleroma.Web.PleromaAPI.Chat.MessageReferenceView
defp object_id_for(%{data: %{"object" => %{"id" => id}}}) when is_binary(id), do: id
@@ -145,7 +146,9 @@ defmodule Pleroma.Web.MastodonAPI.NotificationView do
end
defp put_emoji(response, activity) do
- Map.put(response, :emoji, activity.data["content"])
+ response
+ |> Map.put(:emoji, activity.data["content"])
+ |> Map.put(:emoji_url, MediaProxy.url(Pleroma.Emoji.emoji_url(activity.data)))
end
defp put_chat_message(response, activity, reading_user, opts) do
diff --git a/lib/pleroma/web/mastodon_api/views/poll_view.ex b/lib/pleroma/web/mastodon_api/views/poll_view.ex
index 34e2387..1e3c9f3 100755..100644
--- a/lib/pleroma/web/mastodon_api/views/poll_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/poll_view.ex
@@ -21,7 +21,10 @@ defmodule Pleroma.Web.MastodonAPI.PollView do
votes_count: votes_count,
voters_count: voters_count(object),
options: options,
- emojis: Pleroma.Web.MastodonAPI.StatusView.build_emojis(object.data["emoji"])
+ emojis: Pleroma.Web.MastodonAPI.StatusView.build_emojis(object.data["emoji"]),
+ pleroma: %{
+ non_anonymous: object.data["nonAnonymous"] || false
+ }
}
if params[:for] do
diff --git a/lib/pleroma/web/mastodon_api/views/report_view.ex b/lib/pleroma/web/mastodon_api/views/report_view.ex
index 983f7bd..983f7bd 100755..100644
--- a/lib/pleroma/web/mastodon_api/views/report_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/report_view.ex
diff --git a/lib/pleroma/web/mastodon_api/views/scheduled_activity_view.ex b/lib/pleroma/web/mastodon_api/views/scheduled_activity_view.ex
index 772d22f..772d22f 100755..100644
--- a/lib/pleroma/web/mastodon_api/views/scheduled_activity_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/scheduled_activity_view.ex
diff --git a/lib/pleroma/web/mastodon_api/views/status_view.ex b/lib/pleroma/web/mastodon_api/views/status_view.ex
index 0a8c98b..c945290 100755..100644
--- a/lib/pleroma/web/mastodon_api/views/status_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/status_view.ex
@@ -21,6 +21,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
alias Pleroma.Web.MastodonAPI.StatusView
alias Pleroma.Web.MediaProxy
alias Pleroma.Web.PleromaAPI.EmojiReactionController
+ alias Pleroma.Web.RichMedia.Card
import Pleroma.Web.ActivityPub.Visibility, only: [get_visibility: 1, visible_for_user?: 2]
@@ -29,9 +30,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
# pagination is restricted to 40 activities at a time
defp fetch_rich_media_for_activities(activities) do
Enum.each(activities, fn activity ->
- spawn(fn ->
- Pleroma.Web.RichMedia.Helpers.fetch_data_for_activity(activity)
- end)
+ spawn(fn -> Card.get_by_activity(activity) end)
end)
end
@@ -57,6 +56,27 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
end)
end
+ defp get_quoted_activities([]), do: %{}
+
+ defp get_quoted_activities(activities) do
+ activities
+ |> Enum.map(fn
+ %{data: %{"type" => "Create"}} = activity ->
+ object = Object.normalize(activity, fetch: false)
+ object && object.data["quoteUrl"] != "" && object.data["quoteUrl"]
+
+ _ ->
+ nil
+ end)
+ |> Enum.filter(& &1)
+ |> Activity.create_by_object_ap_id_with_object()
+ |> Repo.all()
+ |> Enum.reduce(%{}, fn activity, acc ->
+ object = Object.normalize(activity, fetch: false)
+ if object, do: Map.put(acc, object.data["id"], activity), else: acc
+ end)
+ end
+
# DEPRECATED This field seems to be a left-over from the StatusNet era.
# If your application uses `pleroma.conversation_id`: this field is deprecated.
# It is currently stubbed instead by doing a CRC32 of the context, and
@@ -92,11 +112,10 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
# To do: check AdminAPIControllerTest on the reasons behind nil activities in the list
activities = Enum.filter(opts.activities, & &1)
- # Start fetching rich media before doing anything else, so that later calls to get the cards
- # only block for timeout in the worst case, as opposed to
- # length(activities_with_links) * timeout
+ # Start prefetching rich media before doing anything else
fetch_rich_media_for_activities(activities)
replied_to_activities = get_replied_to_activities(activities)
+ quoted_activities = get_quoted_activities(activities)
parent_activities =
activities
@@ -129,6 +148,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
opts =
opts
|> Map.put(:replied_to_activities, replied_to_activities)
+ |> Map.put(:quoted_activities, quoted_activities)
|> Map.put(:parent_activities, parent_activities)
|> Map.put(:relationships, relationships_opt)
@@ -161,7 +181,14 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
favorited = opts[:for] && opts[:for].ap_id in (object.data["likes"] || [])
- bookmarked = Activity.get_bookmark(reblogged_parent_activity, opts[:for]) != nil
+ bookmark = Activity.get_bookmark(reblogged_parent_activity, opts[:for])
+
+ bookmark_folder =
+ if bookmark != nil do
+ bookmark.folder_id
+ else
+ nil
+ end
mentions =
activity.recipients
@@ -190,7 +217,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
favourites_count: 0,
reblogged: reblogged?(reblogged_parent_activity, opts[:for]),
favourited: present?(favorited),
- bookmarked: present?(bookmarked),
+ bookmarked: present?(bookmark),
muted: false,
pinned: pinned?,
sensitive: false,
@@ -204,7 +231,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
emojis: [],
pleroma: %{
local: activity.local,
- pinned_at: pinned_at
+ pinned_at: pinned_at,
+ bookmark_folder: bookmark_folder
}
}
end
@@ -241,7 +269,14 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
favorited = opts[:for] && opts[:for].ap_id in (object.data["likes"] || [])
- bookmarked = Activity.get_bookmark(activity, opts[:for]) != nil
+ bookmark = Activity.get_bookmark(activity, opts[:for])
+
+ bookmark_folder =
+ if bookmark != nil do
+ bookmark.folder_id
+ else
+ nil
+ end
client_posted_this_activity = opts[:for] && user.id == opts[:for].id
@@ -277,7 +312,6 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
end
reply_to = get_reply_to(activity, opts)
-
reply_to_user = reply_to && CommonAPI.get_user(reply_to.data["actor"])
history_len =
@@ -290,6 +324,22 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
# Here the implicit index of the current content is 0
chrono_order = history_len - 1
+ quote_activity = get_quote(activity, opts)
+
+ quote_id =
+ case quote_activity do
+ %Activity{id: id} -> id
+ _ -> nil
+ end
+
+ quote_post =
+ if visible_for_user?(quote_activity, opts[:for]) and opts[:show_quote] != false do
+ quote_rendering_opts = Map.merge(opts, %{activity: quote_activity, show_quote: false})
+ render("show.json", quote_rendering_opts)
+ else
+ nil
+ end
+
content =
object
|> render_content()
@@ -311,7 +361,11 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
summary = object.data["summary"] || ""
- card = render("card.json", Pleroma.Web.RichMedia.Helpers.fetch_data_for_activity(activity))
+ card =
+ case Card.get_by_activity(activity) do
+ %Card{} = result -> render("card.json", result)
+ _ -> nil
+ end
url =
if user.local do
@@ -334,14 +388,14 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
end
emoji_reactions =
- object.data
- |> Map.get("reactions", [])
+ object
+ |> Object.get_emoji_reactions()
|> EmojiReactionController.filter_allowed_users(
opts[:for],
Map.get(opts, :with_muted, false)
)
- |> Stream.map(fn {emoji, users} ->
- build_emoji_map(emoji, users, opts[:for])
+ |> Stream.map(fn {emoji, users, url} ->
+ build_emoji_map(emoji, users, url, opts[:for])
end)
|> Enum.to_list()
@@ -380,7 +434,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
favourites_count: like_count,
reblogged: reblogged?(activity, opts[:for]),
favourited: present?(favorited),
- bookmarked: present?(bookmarked),
+ bookmarked: present?(bookmark),
muted: muted,
pinned: pinned?,
sensitive: sensitive,
@@ -398,6 +452,10 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
conversation_id: get_context_id(activity),
context: object.data["context"],
in_reply_to_account_acct: reply_to_user && reply_to_user.nickname,
+ quote: quote_post,
+ quote_id: quote_id,
+ quote_url: object.data["quoteUrl"],
+ quote_visible: visible_for_user?(quote_activity, opts[:for]),
content: %{"text/plain" => content_plaintext},
spoiler_text: %{"text/plain" => summary},
expires_at: expires_at,
@@ -405,7 +463,9 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
thread_muted: thread_muted?,
emoji_reactions: emoji_reactions,
parent_visible: visible_for_user?(reply_to, opts[:for]),
- pinned_at: pinned_at
+ pinned_at: pinned_at,
+ quotes_count: object.data["quotesCount"] || 0,
+ bookmark_folder: bookmark_folder
}
}
end
@@ -508,37 +568,30 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
}
end
- def render("card.json", %{rich_media: rich_media, page_url: page_url}) do
- page_url_data = URI.parse(page_url)
-
- page_url_data =
- if is_binary(rich_media["url"]) do
- URI.merge(page_url_data, URI.parse(rich_media["url"]))
- else
- page_url_data
- end
+ def render("card.json", %Card{fields: rich_media}) do
+ page_url_data = URI.parse(rich_media["url"])
page_url = page_url_data |> to_string
- image_url_data =
- if is_binary(rich_media["image"]) do
- URI.parse(rich_media["image"])
- else
- nil
- end
-
- image_url = build_image_url(image_url_data, page_url_data)
+ image_url = proxied_url(rich_media["image"], page_url_data)
+ audio_url = proxied_url(rich_media["audio"], page_url_data)
+ video_url = proxied_url(rich_media["video"], page_url_data)
%{
type: "link",
provider_name: page_url_data.host,
provider_url: page_url_data.scheme <> "://" <> page_url_data.host,
url: page_url,
- image: image_url |> MediaProxy.url(),
+ image: image_url,
+ image_description: rich_media["image:alt"] || "",
title: rich_media["title"] || "",
description: rich_media["description"] || "",
pleroma: %{
- opengraph: rich_media
+ opengraph:
+ rich_media
+ |> Maps.put_if_present("image", image_url)
+ |> Maps.put_if_present("audio", audio_url)
+ |> Maps.put_if_present("video", video_url)
}
}
end
@@ -633,6 +686,25 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
end
end
+ def get_quote(activity, %{quoted_activities: quoted_activities}) do
+ object = Object.normalize(activity, fetch: false)
+
+ with nil <- quoted_activities[object.data["quoteUrl"]] do
+ # For when a quote post is inside an Announce
+ Activity.get_create_by_object_ap_id_with_object(object.data["quoteUrl"])
+ end
+ end
+
+ def get_quote(%{data: %{"object" => _object}} = activity, _) do
+ object = Object.normalize(activity, fetch: false)
+
+ if object.data["quoteUrl"] && object.data["quoteUrl"] != "" do
+ Activity.get_create_by_object_ap_id(object.data["quoteUrl"])
+ else
+ nil
+ end
+ end
+
def render_content(%{data: %{"name" => name}} = object) when not is_nil(name) and name != "" do
url = object.data["url"] || object.data["id"]
@@ -702,11 +774,13 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
end
end
- defp build_emoji_map(emoji, users, current_user) do
+ defp build_emoji_map(emoji, users, url, current_user) do
%{
- name: emoji,
+ name: Pleroma.Web.PleromaAPI.EmojiReactionView.emoji_name(emoji, url),
count: length(users),
- me: !!(current_user && current_user.ap_id in users)
+ url: MediaProxy.url(url),
+ me: !!(current_user && current_user.ap_id in users),
+ account_ids: Enum.map(users, fn user -> User.get_cached_by_ap_id(user).id end)
}
end
@@ -733,8 +807,6 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
URI.merge(page_url_data, image_url_data) |> to_string
end
- defp build_image_url(_, _), do: nil
-
defp get_source_text(%{"content" => content} = _source) do
content
end
@@ -754,4 +826,12 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
defp get_source_content_type(_source) do
Utils.get_content_type(nil)
end
+
+ defp proxied_url(url, page_url_data) do
+ if is_binary(url) do
+ build_image_url(URI.parse(url), page_url_data) |> MediaProxy.url()
+ else
+ nil
+ end
+ end
end
diff --git a/lib/pleroma/web/mastodon_api/views/subscription_view.ex b/lib/pleroma/web/mastodon_api/views/subscription_view.ex
index baa1e03..baa1e03 100755..100644
--- a/lib/pleroma/web/mastodon_api/views/subscription_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/subscription_view.ex
diff --git a/lib/pleroma/web/mastodon_api/views/suggestion_view.ex b/lib/pleroma/web/mastodon_api/views/suggestion_view.ex
index d3df4ef..d3df4ef 100755..100644
--- a/lib/pleroma/web/mastodon_api/views/suggestion_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/suggestion_view.ex
diff --git a/lib/pleroma/web/mastodon_api/views/timeline_view.ex b/lib/pleroma/web/mastodon_api/views/timeline_view.ex
index 702eb7e..702eb7e 100755..100644
--- a/lib/pleroma/web/mastodon_api/views/timeline_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/timeline_view.ex
diff --git a/lib/pleroma/web/mastodon_api/websocket_handler.ex b/lib/pleroma/web/mastodon_api/websocket_handler.ex
index 8844410..bb27d80 100755..100644
--- a/lib/pleroma/web/mastodon_api/websocket_handler.ex
+++ b/lib/pleroma/web/mastodon_api/websocket_handler.ex
@@ -9,124 +9,128 @@ defmodule Pleroma.Web.MastodonAPI.WebsocketHandler do
alias Pleroma.User
alias Pleroma.Web.OAuth.Token
alias Pleroma.Web.Streamer
+ alias Pleroma.Web.StreamerView
- @behaviour :cowboy_websocket
+ @behaviour Phoenix.Socket.Transport
# Client ping period.
@tick :timer.seconds(30)
- # Cowboy timeout period.
- @timeout :timer.seconds(60)
- # Hibernate every X messages
- @hibernate_every 100
-
- def init(%{qs: qs} = req, state) do
- with params <- Enum.into(:cow_qs.parse_qs(qs), %{}),
- sec_websocket <- :cowboy_req.header("sec-websocket-protocol", req, nil),
- access_token <- Map.get(params, "access_token"),
- {:ok, user, oauth_token} <- authenticate_request(access_token, sec_websocket),
- {:ok, topic} <- Streamer.get_topic(params["stream"], user, oauth_token, params) do
- req =
- if sec_websocket do
- :cowboy_req.set_resp_header("sec-websocket-protocol", sec_websocket, req)
+
+ @impl Phoenix.Socket.Transport
+ def child_spec(_opts), do: :ignore
+
+ # This only prepares the connection and is not in the process yet
+ @impl Phoenix.Socket.Transport
+ def connect(%{params: params} = transport_info) do
+ with access_token <- Map.get(params, "access_token"),
+ {:ok, user, oauth_token} <- authenticate_request(access_token),
+ {:ok, topic} <-
+ Streamer.get_topic(params["stream"], user, oauth_token, params) do
+ topics =
+ if topic do
+ [topic]
else
- req
+ []
end
- {:cowboy_websocket, req,
- %{user: user, topic: topic, oauth_token: oauth_token, count: 0, timer: nil},
- %{idle_timeout: @timeout}}
+ state = %{
+ user: user,
+ topics: topics,
+ oauth_token: oauth_token,
+ count: 0,
+ timer: nil
+ }
+
+ {:ok, state}
else
{:error, :bad_topic} ->
- Logger.debug("#{__MODULE__} bad topic #{inspect(req)}")
- req = :cowboy_req.reply(404, req)
- {:ok, req, state}
+ Logger.debug("#{__MODULE__} bad topic #{inspect(transport_info)}")
+
+ {:error, :bad_topic}
{:error, :unauthorized} ->
- Logger.debug("#{__MODULE__} authentication error: #{inspect(req)}")
- req = :cowboy_req.reply(401, req)
- {:ok, req, state}
+ Logger.debug("#{__MODULE__} authentication error: #{inspect(transport_info)}")
+ {:error, :unauthorized}
end
end
- def websocket_init(state) do
- Logger.debug(
- "#{__MODULE__} accepted websocket connection for user #{(state.user || %{id: "anonymous"}).id}, topic #{state.topic}"
- )
+ # All subscriptions/links and messages cannot be created
+ # until the processed is launched with init/1
+ @impl Phoenix.Socket.Transport
+ def init(state) do
+ Enum.each(state.topics, fn topic -> Streamer.add_socket(topic, state.oauth_token) end)
- Streamer.add_socket(state.topic, state.oauth_token)
- {:ok, %{state | timer: timer()}}
- end
+ Process.send_after(self(), :ping, @tick)
- # Client's Pong frame.
- def websocket_handle(:pong, state) do
- if state.timer, do: Process.cancel_timer(state.timer)
- {:ok, %{state | timer: timer()}}
+ {:ok, state}
end
- # We only receive pings for now
- def websocket_handle(:ping, state), do: {:ok, state}
+ @impl Phoenix.Socket.Transport
+ def handle_in({text, [opcode: :text]}, state) do
+ with {:ok, %{} = event} <- Jason.decode(text) do
+ handle_client_event(event, state)
+ else
+ _ ->
+ Logger.error("#{__MODULE__} received non-JSON event: #{inspect(text)}")
+ {:ok, state}
+ end
+ end
- def websocket_handle(frame, state) do
+ def handle_in(frame, state) do
Logger.error("#{__MODULE__} received frame: #{inspect(frame)}")
{:ok, state}
end
- def websocket_info({:render_with_user, view, template, item}, state) do
+ @impl Phoenix.Socket.Transport
+ def handle_info({:render_with_user, view, template, item, topic}, state) do
user = %User{} = User.get_cached_by_ap_id(state.user.ap_id)
unless Streamer.filtered_by_user?(user, item) do
- websocket_info({:text, view.render(template, item, user)}, %{state | user: user})
+ message = view.render(template, item, user, topic)
+ {:push, {:text, message}, %{state | user: user}}
else
{:ok, state}
end
end
- def websocket_info({:text, message}, state) do
- # If the websocket processed X messages, force an hibernate/GC.
- # We don't hibernate at every message to balance CPU usage/latency with RAM usage.
- if state.count > @hibernate_every do
- {:reply, {:text, message}, %{state | count: 0}, :hibernate}
- else
- {:reply, {:text, message}, %{state | count: state.count + 1}}
- end
+ def handle_info({:text, text}, state) do
+ {:push, {:text, text}, state}
end
- # Ping tick. We don't re-queue a timer there, it is instead queued when :pong is received.
- # As we hibernate there, reset the count to 0.
- # If the client misses :pong, Cowboy will automatically timeout the connection after
- # `@idle_timeout`.
- def websocket_info(:tick, state) do
- {:reply, :ping, %{state | timer: nil, count: 0}, :hibernate}
+ def handle_info(:ping, state) do
+ Process.send_after(self(), :ping, @tick)
+
+ {:push, {:ping, ""}, state}
end
- def websocket_info(:close, state) do
- {:stop, state}
+ def handle_info(:close, state) do
+ {:stop, {:closed, 'connection closed by server'}, state}
end
- # State can be `[]` only in case we terminate before switching to websocket,
- # we already log errors for these cases in `init/1`, so just do nothing here
- def terminate(_reason, _req, []), do: :ok
+ def handle_info(msg, state) do
+ Logger.debug("#{__MODULE__} received info: #{inspect(msg)}")
+
+ {:ok, state}
+ end
- def terminate(reason, _req, state) do
+ @impl Phoenix.Socket.Transport
+ def terminate(reason, state) do
Logger.debug(
- "#{__MODULE__} terminating websocket connection for user #{(state.user || %{id: "anonymous"}).id}, topic #{state.topic || "?"}: #{inspect(reason)}"
+ "#{__MODULE__} terminating websocket connection for user #{(state.user || %{id: "anonymous"}).id}, topics #{state.topics || "?"}: #{inspect(reason)})"
)
- Streamer.remove_socket(state.topic)
+ Enum.each(state.topics, fn topic -> Streamer.remove_socket(topic) end)
:ok
end
# Public streams without authentication.
- defp authenticate_request(nil, nil) do
+ defp authenticate_request(nil) do
{:ok, nil, nil}
end
# Authenticated streams.
- defp authenticate_request(access_token, sec_websocket) do
- token = access_token || sec_websocket
-
- with true <- is_bitstring(token),
- oauth_token = %Token{user_id: user_id} <- Repo.get_by(Token, token: token),
+ defp authenticate_request(access_token) do
+ with oauth_token = %Token{user_id: user_id} <- Repo.get_by(Token, token: access_token),
user = %User{} <- User.get_cached_by_id(user_id) do
{:ok, user, oauth_token}
else
@@ -134,7 +138,110 @@ defmodule Pleroma.Web.MastodonAPI.WebsocketHandler do
end
end
- defp timer do
- Process.send_after(self(), :tick, @tick)
+ defp handle_client_event(%{"type" => "subscribe", "stream" => _topic} = params, state) do
+ with {_, {:ok, topic}} <-
+ {:topic, Streamer.get_topic(params["stream"], state.user, state.oauth_token, params)},
+ {_, false} <- {:subscribed, topic in state.topics} do
+ Streamer.add_socket(topic, state.oauth_token)
+
+ message =
+ StreamerView.render("pleroma_respond.json", %{type: "subscribe", result: "success"})
+
+ {:reply, :ok, {:text, message}, %{state | topics: [topic | state.topics]}}
+ else
+ {:subscribed, true} ->
+ message =
+ StreamerView.render("pleroma_respond.json", %{type: "subscribe", result: "ignored"})
+
+ {:reply, :error, {:text, message}, state}
+
+ {:topic, {:error, error}} ->
+ message =
+ StreamerView.render("pleroma_respond.json", %{
+ type: "subscribe",
+ result: "error",
+ error: error
+ })
+
+ {:reply, :error, {:text, message}, state}
+ end
+ end
+
+ defp handle_client_event(%{"type" => "unsubscribe", "stream" => _topic} = params, state) do
+ with {_, {:ok, topic}} <-
+ {:topic, Streamer.get_topic(params["stream"], state.user, state.oauth_token, params)},
+ {_, true} <- {:subscribed, topic in state.topics} do
+ Streamer.remove_socket(topic)
+
+ message =
+ StreamerView.render("pleroma_respond.json", %{type: "unsubscribe", result: "success"})
+
+ {:reply, :ok, {:text, message}, %{state | topics: List.delete(state.topics, topic)}}
+ else
+ {:subscribed, false} ->
+ message =
+ StreamerView.render("pleroma_respond.json", %{type: "unsubscribe", result: "ignored"})
+
+ {:reply, :error, {:text, message}, state}
+
+ {:topic, {:error, error}} ->
+ message =
+ StreamerView.render("pleroma_respond.json", %{
+ type: "unsubscribe",
+ result: "error",
+ error: error
+ })
+
+ {:reply, :error, {:text, message}, state}
+ end
+ end
+
+ defp handle_client_event(
+ %{"type" => "pleroma:authenticate", "token" => access_token} = _params,
+ state
+ ) do
+ with {:auth, nil, nil} <- {:auth, state.user, state.oauth_token},
+ {:ok, user, oauth_token} <- authenticate_request(access_token) do
+ message =
+ StreamerView.render("pleroma_respond.json", %{
+ type: "pleroma:authenticate",
+ result: "success"
+ })
+
+ {:reply, :ok, {:text, message}, %{state | user: user, oauth_token: oauth_token}}
+ else
+ {:auth, _, _} ->
+ message =
+ StreamerView.render("pleroma_respond.json", %{
+ type: "pleroma:authenticate",
+ result: "error",
+ error: :already_authenticated
+ })
+
+ {:reply, :error, {:text, message}, state}
+
+ _ ->
+ message =
+ StreamerView.render("pleroma_respond.json", %{
+ type: "pleroma:authenticate",
+ result: "error",
+ error: :unauthorized
+ })
+
+ {:reply, :error, {:text, message}, state}
+ end
+ end
+
+ defp handle_client_event(params, state) do
+ Logger.error("#{__MODULE__} received unknown event: #{inspect(params)}")
+ {:ok, state}
+ end
+
+ def handle_error(conn, :unauthorized) do
+ Plug.Conn.send_resp(conn, 401, "Unauthorized")
+ end
+
+ def handle_error(conn, _reason) do
+ Plug.Conn.send_resp(conn, 404, "Not Found")
end
end
diff --git a/lib/pleroma/web/media_proxy.ex b/lib/pleroma/web/media_proxy.ex
index d64760f..d64760f 100755..100644
--- a/lib/pleroma/web/media_proxy.ex
+++ b/lib/pleroma/web/media_proxy.ex
diff --git a/lib/pleroma/web/media_proxy/invalidation.ex b/lib/pleroma/web/media_proxy/invalidation.ex
index ea927fe..ea927fe 100755..100644
--- a/lib/pleroma/web/media_proxy/invalidation.ex
+++ b/lib/pleroma/web/media_proxy/invalidation.ex
diff --git a/lib/pleroma/web/media_proxy/invalidation/http.ex b/lib/pleroma/web/media_proxy/invalidation/http.ex
index 28ea749..28ea749 100755..100644
--- a/lib/pleroma/web/media_proxy/invalidation/http.ex
+++ b/lib/pleroma/web/media_proxy/invalidation/http.ex
diff --git a/lib/pleroma/web/media_proxy/invalidation/script.ex b/lib/pleroma/web/media_proxy/invalidation/script.ex
index 784178f..784178f 100755..100644
--- a/lib/pleroma/web/media_proxy/invalidation/script.ex
+++ b/lib/pleroma/web/media_proxy/invalidation/script.ex
diff --git a/lib/pleroma/web/media_proxy/media_proxy_controller.ex b/lib/pleroma/web/media_proxy/media_proxy_controller.ex
index bda5b36..c11484e 100755..100644
--- a/lib/pleroma/web/media_proxy/media_proxy_controller.ex
+++ b/lib/pleroma/web/media_proxy/media_proxy_controller.ex
@@ -56,7 +56,7 @@ defmodule Pleroma.Web.MediaProxy.MediaProxyController do
media_proxy_url = MediaProxy.url(url)
with {:ok, %{status: status} = head_response} when status in 200..299 <-
- Pleroma.HTTP.request("HEAD", media_proxy_url, [], [], pool: :media) do
+ Pleroma.HTTP.request(:head, media_proxy_url, "", [], pool: :media) do
content_type = Tesla.get_header(head_response, "content-type")
content_length = Tesla.get_header(head_response, "content-length")
content_length = content_length && String.to_integer(content_length)
diff --git a/lib/pleroma/web/metadata.ex b/lib/pleroma/web/metadata.ex
index 59d0187..59d0187 100755..100644
--- a/lib/pleroma/web/metadata.ex
+++ b/lib/pleroma/web/metadata.ex
diff --git a/lib/pleroma/web/metadata/player_view.ex b/lib/pleroma/web/metadata/player_view.ex
index 59c56a2..59c56a2 100755..100644
--- a/lib/pleroma/web/metadata/player_view.ex
+++ b/lib/pleroma/web/metadata/player_view.ex
diff --git a/lib/pleroma/web/metadata/providers/feed.ex b/lib/pleroma/web/metadata/providers/feed.ex
index e97d6a5..e97d6a5 100755..100644
--- a/lib/pleroma/web/metadata/providers/feed.ex
+++ b/lib/pleroma/web/metadata/providers/feed.ex
diff --git a/lib/pleroma/web/metadata/providers/open_graph.ex b/lib/pleroma/web/metadata/providers/open_graph.ex
index 97d3865..97d3865 100755..100644
--- a/lib/pleroma/web/metadata/providers/open_graph.ex
+++ b/lib/pleroma/web/metadata/providers/open_graph.ex
diff --git a/lib/pleroma/web/metadata/providers/provider.ex b/lib/pleroma/web/metadata/providers/provider.ex
index bb31c4d..bb31c4d 100755..100644
--- a/lib/pleroma/web/metadata/providers/provider.ex
+++ b/lib/pleroma/web/metadata/providers/provider.ex
diff --git a/lib/pleroma/web/metadata/providers/rel_me.ex b/lib/pleroma/web/metadata/providers/rel_me.ex
index f0bee85..eabd8cb 100755..100644
--- a/lib/pleroma/web/metadata/providers/rel_me.ex
+++ b/lib/pleroma/web/metadata/providers/rel_me.ex
@@ -8,12 +8,20 @@ defmodule Pleroma.Web.Metadata.Providers.RelMe do
@impl Provider
def build_tags(%{user: user}) do
- bio_tree = Floki.parse_fragment!(user.bio)
+ profile_tree =
+ user.bio
+ |> append_fields_tag(user.fields)
+ |> Floki.parse_fragment!()
- (Floki.attribute(bio_tree, "link[rel~=me]", "href") ++
- Floki.attribute(bio_tree, "a[rel~=me]", "href"))
+ (Floki.attribute(profile_tree, "link[rel~=me]", "href") ++
+ Floki.attribute(profile_tree, "a[rel~=me]", "href"))
|> Enum.map(fn link ->
{:link, [rel: "me", href: link], []}
end)
end
+
+ defp append_fields_tag(bio, fields) do
+ fields
+ |> Enum.reduce(bio, fn %{"value" => v}, res -> res <> v end)
+ end
end
diff --git a/lib/pleroma/web/metadata/providers/restrict_indexing.ex b/lib/pleroma/web/metadata/providers/restrict_indexing.ex
index a43a7c9..a43a7c9 100755..100644
--- a/lib/pleroma/web/metadata/providers/restrict_indexing.ex
+++ b/lib/pleroma/web/metadata/providers/restrict_indexing.ex
diff --git a/lib/pleroma/web/metadata/providers/twitter_card.ex b/lib/pleroma/web/metadata/providers/twitter_card.ex
index 2dac22e..426022c 100755..100644
--- a/lib/pleroma/web/metadata/providers/twitter_card.ex
+++ b/lib/pleroma/web/metadata/providers/twitter_card.ex
@@ -76,9 +76,10 @@ defmodule Pleroma.Web.Metadata.Providers.TwitterCard do
{:meta, [name: "twitter:card", content: "summary_large_image"], []},
{:meta,
[
- name: "twitter:player",
+ name: "twitter:image",
content: MediaProxy.url(url["href"])
- ], []}
+ ], []},
+ {:meta, [name: "twitter:image:alt", content: truncate(attachment["name"])], []}
| acc
]
|> maybe_add_dimensions(url)
@@ -130,4 +131,12 @@ defmodule Pleroma.Web.Metadata.Providers.TwitterCard do
metadata
end
end
+
+ defp truncate(nil), do: ""
+
+ defp truncate(text) do
+ # truncate to 420 characters
+ # see https://developer.twitter.com/en/docs/twitter-for-websites/cards/overview/markup
+ Pleroma.Formatter.truncate(text, 420)
+ end
end
diff --git a/lib/pleroma/web/metadata/utils.ex b/lib/pleroma/web/metadata/utils.ex
index 80a8be9..80a8be9 100755..100644
--- a/lib/pleroma/web/metadata/utils.ex
+++ b/lib/pleroma/web/metadata/utils.ex
diff --git a/lib/pleroma/web/mongoose_im/mongoose_im_controller.ex b/lib/pleroma/web/mongoose_im/mongoose_im_controller.ex
index 0945ebb..0945ebb 100755..100644
--- a/lib/pleroma/web/mongoose_im/mongoose_im_controller.ex
+++ b/lib/pleroma/web/mongoose_im/mongoose_im_controller.ex
diff --git a/lib/pleroma/web/multipart.ex b/lib/pleroma/web/multipart.ex
new file mode 100644
index 0000000..e24bb14
--- /dev/null
+++ b/lib/pleroma/web/multipart.ex
@@ -0,0 +1,22 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+# <https://hexdocs.pm/plug/Plug.Parsers.MULTIPART.html#module-dynamic-configuration>
+defmodule Pleroma.Web.Multipart do
+ @multipart Plug.Parsers.MULTIPART
+
+ def init(opts) do
+ opts
+ end
+
+ def parse(conn, "multipart", subtype, headers, opts) do
+ length = Pleroma.Config.get([:instance, :upload_limit])
+ opts = @multipart.init([length: length] ++ opts)
+ @multipart.parse(conn, "multipart", subtype, headers, opts)
+ end
+
+ def parse(conn, _type, _subtype, _headers, _opts) do
+ {:next, conn}
+ end
+end
diff --git a/lib/pleroma/web/nodeinfo/nodeinfo.ex b/lib/pleroma/web/nodeinfo/nodeinfo.ex
index 9e27ac2..4d5a9a5 100755..100644
--- a/lib/pleroma/web/nodeinfo/nodeinfo.ex
+++ b/lib/pleroma/web/nodeinfo/nodeinfo.ex
@@ -6,7 +6,7 @@ defmodule Pleroma.Web.Nodeinfo.Nodeinfo do
alias Pleroma.Config
alias Pleroma.Stats
alias Pleroma.User
- alias Pleroma.Web.Federator.Publisher
+ alias Pleroma.Web.ActivityPub.Publisher
alias Pleroma.Web.MastodonAPI.InstanceView
# returns a nodeinfo 2.0 map, since 2.1 just adds a repository field
diff --git a/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex b/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex
index 85c2393..85c2393 100755..100644
--- a/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex
+++ b/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex
diff --git a/lib/pleroma/web/o_auth.ex b/lib/pleroma/web/o_auth.ex
index d8c68df..d8c68df 100755..100644
--- a/lib/pleroma/web/o_auth.ex
+++ b/lib/pleroma/web/o_auth.ex
diff --git a/lib/pleroma/web/o_auth/app.ex b/lib/pleroma/web/o_auth/app.ex
index 0aa6553..0aa6553 100755..100644
--- a/lib/pleroma/web/o_auth/app.ex
+++ b/lib/pleroma/web/o_auth/app.ex
diff --git a/lib/pleroma/web/o_auth/authorization.ex b/lib/pleroma/web/o_auth/authorization.ex
index 593d2d6..22e5bfc 100755..100644
--- a/lib/pleroma/web/o_auth/authorization.ex
+++ b/lib/pleroma/web/o_auth/authorization.ex
@@ -28,7 +28,7 @@ defmodule Pleroma.Web.OAuth.Authorization do
end
@spec create_authorization(App.t(), User.t() | %{}, [String.t()] | nil) ::
- {:ok, Authorization.t()} | {:error, Changeset.t()}
+ {:ok, Authorization.t()} | {:error, Ecto.Changeset.t()}
def create_authorization(%App{} = app, %User{} = user, scopes \\ nil) do
%{
scopes: scopes || app.scopes,
@@ -39,7 +39,7 @@ defmodule Pleroma.Web.OAuth.Authorization do
|> Repo.insert()
end
- @spec create_changeset(map()) :: Changeset.t()
+ @spec create_changeset(map()) :: Ecto.Changeset.t()
def create_changeset(attrs \\ %{}) do
%Authorization{}
|> cast(attrs, [:user_id, :app_id, :scopes, :valid_until])
@@ -58,7 +58,7 @@ defmodule Pleroma.Web.OAuth.Authorization do
put_change(changeset, :valid_until, NaiveDateTime.add(NaiveDateTime.utc_now(), lifespan))
end
- @spec use_changeset(Authtorizatiton.t(), map()) :: Changeset.t()
+ @spec use_changeset(Authorization.t(), map()) :: Ecto.Changeset.t()
def use_changeset(%Authorization{} = auth, params) do
auth
|> cast(params, [:used])
@@ -66,7 +66,7 @@ defmodule Pleroma.Web.OAuth.Authorization do
end
@spec use_token(Authorization.t()) ::
- {:ok, Authorization.t()} | {:error, Changeset.t()} | {:error, String.t()}
+ {:ok, Authorization.t()} | {:error, Ecto.Changeset.t()} | {:error, String.t()}
def use_token(%Authorization{used: false, valid_until: valid_until} = auth) do
if NaiveDateTime.diff(NaiveDateTime.utc_now(), valid_until) < 0 do
Repo.update(use_changeset(auth, %{used: true}))
diff --git a/lib/pleroma/web/o_auth/fallback_controller.ex b/lib/pleroma/web/o_auth/fallback_controller.ex
index 684a52c..684a52c 100755..100644
--- a/lib/pleroma/web/o_auth/fallback_controller.ex
+++ b/lib/pleroma/web/o_auth/fallback_controller.ex
diff --git a/lib/pleroma/web/o_auth/mfa_controller.ex b/lib/pleroma/web/o_auth/mfa_controller.ex
index c4bc4a8..c4bc4a8 100755..100644
--- a/lib/pleroma/web/o_auth/mfa_controller.ex
+++ b/lib/pleroma/web/o_auth/mfa_controller.ex
diff --git a/lib/pleroma/web/o_auth/mfa_view.ex b/lib/pleroma/web/o_auth/mfa_view.ex
index bcadafe..bcadafe 100755..100644
--- a/lib/pleroma/web/o_auth/mfa_view.ex
+++ b/lib/pleroma/web/o_auth/mfa_view.ex
diff --git a/lib/pleroma/web/o_auth/o_auth_controller.ex b/lib/pleroma/web/o_auth/o_auth_controller.ex
index c1fb4f3..47b0321 100755..100644
--- a/lib/pleroma/web/o_auth/o_auth_controller.ex
+++ b/lib/pleroma/web/o_auth/o_auth_controller.ex
@@ -310,7 +310,7 @@ defmodule Pleroma.Web.OAuth.OAuthController do
after_token_exchange(conn, %{token: token})
else
_error ->
- handle_token_exchange_error(conn, :invalid_credentails)
+ handle_token_exchange_error(conn, :invalid_credentials)
end
end
@@ -610,13 +610,8 @@ defmodule Pleroma.Web.OAuth.OAuthController do
end
end
- @spec validate_scopes(App.t(), map() | list()) ::
+ @spec validate_scopes(App.t(), list()) ::
{:ok, list()} | {:error, :missing_scopes | :unsupported_scopes}
- defp validate_scopes(%App{} = app, params) when is_map(params) do
- requested_scopes = Scopes.fetch_scopes(params, app.scopes)
- validate_scopes(app, requested_scopes)
- end
-
defp validate_scopes(%App{} = app, requested_scopes) when is_list(requested_scopes) do
Scopes.validate(requested_scopes, app.scopes)
end
diff --git a/lib/pleroma/web/o_auth/o_auth_view.ex b/lib/pleroma/web/o_auth/o_auth_view.ex
index 108102c..108102c 100755..100644
--- a/lib/pleroma/web/o_auth/o_auth_view.ex
+++ b/lib/pleroma/web/o_auth/o_auth_view.ex
diff --git a/lib/pleroma/web/o_auth/scopes.ex b/lib/pleroma/web/o_auth/scopes.ex
index f33fc21..f33fc21 100755..100644
--- a/lib/pleroma/web/o_auth/scopes.ex
+++ b/lib/pleroma/web/o_auth/scopes.ex
diff --git a/lib/pleroma/web/o_auth/token.ex b/lib/pleroma/web/o_auth/token.ex
index 26de7bb..a5ad2e9 100755..100644
--- a/lib/pleroma/web/o_auth/token.ex
+++ b/lib/pleroma/web/o_auth/token.ex
@@ -56,7 +56,8 @@ defmodule Pleroma.Web.OAuth.Token do
|> Repo.find_resource()
end
- @spec exchange_token(App.t(), Authorization.t()) :: {:ok, Token.t()} | {:error, Changeset.t()}
+ @spec exchange_token(App.t(), Authorization.t()) ::
+ {:ok, Token.t()} | {:error, Ecto.Changeset.t()}
def exchange_token(app, auth) do
with {:ok, auth} <- Authorization.use_token(auth),
true <- auth.app_id == app.id do
@@ -95,7 +96,7 @@ defmodule Pleroma.Web.OAuth.Token do
|> validate_required([:valid_until])
end
- @spec create(App.t(), User.t(), map()) :: {:ok, Token} | {:error, Changeset.t()}
+ @spec create(App.t(), User.t(), map()) :: {:ok, Token} | {:error, Ecto.Changeset.t()}
def create(%App{} = app, %User{} = user, attrs \\ %{}) do
with {:ok, token} <- do_create(app, user, attrs) do
if Pleroma.Config.get([:oauth2, :clean_expired_tokens]) do
@@ -137,9 +138,9 @@ defmodule Pleroma.Web.OAuth.Token do
|> Repo.all()
end
- def is_expired?(%__MODULE__{valid_until: valid_until}) do
+ def expired?(%__MODULE__{valid_until: valid_until}) do
NaiveDateTime.diff(NaiveDateTime.utc_now(), valid_until) > 0
end
- def is_expired?(_), do: false
+ def expired?(_), do: false
end
diff --git a/lib/pleroma/web/o_auth/token/query.ex b/lib/pleroma/web/o_auth/token/query.ex
index 4a4d2d3..6853ec8 100755..100644
--- a/lib/pleroma/web/o_auth/token/query.ex
+++ b/lib/pleroma/web/o_auth/token/query.ex
@@ -9,10 +9,10 @@ defmodule Pleroma.Web.OAuth.Token.Query do
import Ecto.Query, only: [from: 2]
- @type query :: Ecto.Queryable.t() | Token.t()
-
alias Pleroma.Web.OAuth.Token
+ @type query :: Ecto.Queryable.t() | Token.t()
+
@spec get_by_refresh_token(query, String.t()) :: query
def get_by_refresh_token(query \\ Token, refresh_token) do
from(q in query, where: q.refresh_token == ^refresh_token)
diff --git a/lib/pleroma/web/o_auth/token/strategy/refresh_token.ex b/lib/pleroma/web/o_auth/token/strategy/refresh_token.ex
index 6b0d950..6b0d950 100755..100644
--- a/lib/pleroma/web/o_auth/token/strategy/refresh_token.ex
+++ b/lib/pleroma/web/o_auth/token/strategy/refresh_token.ex
diff --git a/lib/pleroma/web/o_auth/token/strategy/revoke.ex b/lib/pleroma/web/o_auth/token/strategy/revoke.ex
index 3b265b3..3b265b3 100755..100644
--- a/lib/pleroma/web/o_auth/token/strategy/revoke.ex
+++ b/lib/pleroma/web/o_auth/token/strategy/revoke.ex
diff --git a/lib/pleroma/web/o_auth/token/utils.ex b/lib/pleroma/web/o_auth/token/utils.ex
index 773cd97..773cd97 100755..100644
--- a/lib/pleroma/web/o_auth/token/utils.ex
+++ b/lib/pleroma/web/o_auth/token/utils.ex
diff --git a/lib/pleroma/web/o_status/o_status_controller.ex b/lib/pleroma/web/o_status/o_status_controller.ex
index ea4994b..ee7ef4a 100755..100644
--- a/lib/pleroma/web/o_status/o_status_controller.ex
+++ b/lib/pleroma/web/o_status/o_status_controller.ex
@@ -37,7 +37,7 @@ defmodule Pleroma.Web.OStatus.OStatusController do
with id <- Endpoint.url() <> conn.request_path,
{_, %Activity{} = activity} <-
{:activity, Activity.get_create_by_object_ap_id_with_object(id)},
- {_, true} <- {:public?, Visibility.is_public?(activity)} do
+ {_, true} <- {:public?, Visibility.public?(activity)} do
redirect(conn, to: "/notice/#{activity.id}")
else
reason when reason in [{:public?, false}, {:activity, nil}] ->
@@ -56,7 +56,7 @@ defmodule Pleroma.Web.OStatus.OStatusController do
def activity(conn, _params) do
with id <- Endpoint.url() <> conn.request_path,
{_, %Activity{} = activity} <- {:activity, Activity.normalize(id)},
- {_, true} <- {:public?, Visibility.is_public?(activity)} do
+ {_, true} <- {:public?, Visibility.public?(activity)} do
redirect(conn, to: "/notice/#{activity.id}")
else
reason when reason in [{:public?, false}, {:activity, nil}] ->
@@ -69,7 +69,7 @@ defmodule Pleroma.Web.OStatus.OStatusController do
def notice(%{assigns: %{format: format}} = conn, %{"id" => id}) do
with {_, %Activity{} = activity} <- {:activity, Activity.get_by_id_with_object(id)},
- {_, true} <- {:public?, Visibility.is_public?(activity)},
+ {_, true} <- {:public?, Visibility.public?(activity)},
%User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]) do
cond do
format in ["json", "activity+json"] ->
@@ -106,13 +106,12 @@ defmodule Pleroma.Web.OStatus.OStatusController do
# Returns an HTML embedded <audio> or <video> player suitable for embed iframes.
def notice_player(conn, %{"id" => id}) do
with %Activity{data: %{"type" => "Create"}} = activity <- Activity.get_by_id_with_object(id),
- true <- Visibility.is_public?(activity),
+ true <- Visibility.public?(activity),
{_, true} <- {:visible?, Visibility.visible_for_user?(activity, _reading_user = nil)},
%Object{} = object <- Object.normalize(activity, fetch: false),
%{data: %{"attachment" => [%{"url" => [url | _]} | _]}} <- object,
true <- String.starts_with?(url["mediaType"], ["audio", "video"]) do
conn
- |> put_layout(:metadata_player)
|> put_resp_header("x-frame-options", "ALLOW")
|> put_resp_header(
"content-security-policy",
diff --git a/lib/pleroma/web/pleroma_api/controllers/account_controller.ex b/lib/pleroma/web/pleroma_api/controllers/account_controller.ex
index 591391b..591391b 100755..100644
--- a/lib/pleroma/web/pleroma_api/controllers/account_controller.ex
+++ b/lib/pleroma/web/pleroma_api/controllers/account_controller.ex
diff --git a/lib/pleroma/web/pleroma_api/controllers/app_controller.ex b/lib/pleroma/web/pleroma_api/controllers/app_controller.ex
index 3e84f75..3e84f75 100755..100644
--- a/lib/pleroma/web/pleroma_api/controllers/app_controller.ex
+++ b/lib/pleroma/web/pleroma_api/controllers/app_controller.ex
diff --git a/lib/pleroma/web/pleroma_api/controllers/backup_controller.ex b/lib/pleroma/web/pleroma_api/controllers/backup_controller.ex
index b9daed2..b9daed2 100755..100644
--- a/lib/pleroma/web/pleroma_api/controllers/backup_controller.ex
+++ b/lib/pleroma/web/pleroma_api/controllers/backup_controller.ex
diff --git a/lib/pleroma/web/pleroma_api/controllers/bookmark_folder_controller.ex b/lib/pleroma/web/pleroma_api/controllers/bookmark_folder_controller.ex
new file mode 100644
index 0000000..6d6e2e9
--- /dev/null
+++ b/lib/pleroma/web/pleroma_api/controllers/bookmark_folder_controller.ex
@@ -0,0 +1,68 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2024 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.PleromaAPI.BookmarkFolderController do
+ use Pleroma.Web, :controller
+
+ alias Pleroma.BookmarkFolder
+ alias Pleroma.Web.Plugs.OAuthScopesPlug
+
+ plug(Pleroma.Web.ApiSpec.CastAndValidate)
+
+ # Note: scope not present in Mastodon: read:bookmarks
+ plug(OAuthScopesPlug, %{scopes: ["read:bookmarks"]} when action == :index)
+
+ # Note: scope not present in Mastodon: write:bookmarks
+ plug(
+ OAuthScopesPlug,
+ %{scopes: ["write:bookmarks"]} when action in [:create, :update, :delete]
+ )
+
+ defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.PleromaBookmarkFolderOperation
+
+ action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
+
+ def index(%{assigns: %{user: user}} = conn, _params) do
+ with folders <- BookmarkFolder.for_user(user.id) do
+ conn
+ |> render("index.json", %{folders: folders, as: :folder})
+ end
+ end
+
+ def create(
+ %{assigns: %{user: user}, private: %{open_api_spex: %{body_params: params}}} = conn,
+ _
+ ) do
+ with {:ok, folder} <- BookmarkFolder.create(user.id, params[:name], params[:emoji]) do
+ render(conn, "show.json", folder: folder)
+ end
+ end
+
+ def update(
+ %{
+ assigns: %{user: user},
+ private: %{open_api_spex: %{body_params: params, params: %{id: id}}}
+ } = conn,
+ _
+ ) do
+ with true <- BookmarkFolder.belongs_to_user?(id, user.id),
+ {:ok, folder} <- BookmarkFolder.update(id, params[:name], params[:emoji]) do
+ render(conn, "show.json", folder: folder)
+ else
+ false -> {:error, :forbidden}
+ end
+ end
+
+ def delete(
+ %{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: id}}}} = conn,
+ _
+ ) do
+ with true <- BookmarkFolder.belongs_to_user?(id, user.id),
+ {:ok, folder} <- BookmarkFolder.delete(id) do
+ render(conn, "show.json", folder: folder)
+ else
+ false -> {:error, :forbidden}
+ end
+ end
+end
diff --git a/lib/pleroma/web/pleroma_api/controllers/chat_controller.ex b/lib/pleroma/web/pleroma_api/controllers/chat_controller.ex
index 3d7b6a4..58780ac 100755..100644
--- a/lib/pleroma/web/pleroma_api/controllers/chat_controller.ex
+++ b/lib/pleroma/web/pleroma_api/controllers/chat_controller.ex
@@ -38,14 +38,24 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do
%{scopes: ["read:chats"]} when action in [:messages, :index, :index2, :show]
)
- plug(Pleroma.Web.ApiSpec.CastAndValidate)
+ plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.ChatOperation
- def delete_message(%{assigns: %{user: %{id: user_id} = user}} = conn, %{
- message_id: message_id,
- id: chat_id
- }) do
+ def delete_message(
+ %{
+ assigns: %{user: %{id: user_id} = user},
+ private: %{
+ open_api_spex: %{
+ params: %{
+ message_id: message_id,
+ id: chat_id
+ }
+ }
+ }
+ } = conn,
+ _
+ ) do
with %MessageReference{} = cm_ref <-
MessageReference.get_by_id(message_id),
^chat_id <- to_string(cm_ref.chat_id),
@@ -72,11 +82,14 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do
defp remove_or_delete(cm_ref, _), do: MessageReference.delete(cm_ref)
def post_chat_message(
- %{body_params: params, assigns: %{user: user}} = conn,
- %{id: id}
+ %{
+ private: %{open_api_spex: %{body_params: params, params: %{id: id}}},
+ assigns: %{user: user}
+ } = conn,
+ _
) do
with {:ok, chat} <- Chat.get_by_user_and_id(user, id),
- %User{} = recipient <- User.get_cached_by_ap_id(chat.recipient),
+ {_, %User{} = recipient} <- {:user, User.get_cached_by_ap_id(chat.recipient)},
{:ok, activity} <-
CommonAPI.post_chat_message(user, recipient, params[:content],
media_id: params[:media_id],
@@ -97,12 +110,20 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do
conn
|> put_status(:bad_request)
|> json(%{error: message})
+
+ {:user, nil} ->
+ conn
+ |> put_status(:bad_request)
+ |> json(%{error: "Recipient does not exist"})
end
end
def mark_message_as_read(
- %{assigns: %{user: %{id: user_id}}} = conn,
- %{id: chat_id, message_id: message_id}
+ %{
+ assigns: %{user: %{id: user_id}},
+ private: %{open_api_spex: %{params: %{id: chat_id, message_id: message_id}}}
+ } = conn,
+ _
) do
with %MessageReference{} = cm_ref <- MessageReference.get_by_id(message_id),
^chat_id <- to_string(cm_ref.chat_id),
@@ -115,8 +136,16 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do
end
def mark_as_read(
- %{body_params: %{last_read_id: last_read_id}, assigns: %{user: user}} = conn,
- %{id: id}
+ %{
+ assigns: %{user: user},
+ private: %{
+ open_api_spex: %{
+ body_params: %{last_read_id: last_read_id},
+ params: %{id: id}
+ }
+ }
+ } = conn,
+ _
) do
with {:ok, chat} <- Chat.get_by_user_and_id(user, id),
{_n, _} <- MessageReference.set_all_seen_for_chat(chat, last_read_id) do
@@ -124,7 +153,13 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do
end
end
- def messages(%{assigns: %{user: user}} = conn, %{id: id} = params) do
+ def messages(
+ %{
+ assigns: %{user: user},
+ private: %{open_api_spex: %{params: %{id: id} = params}}
+ } = conn,
+ _
+ ) do
with {:ok, chat} <- Chat.get_by_user_and_id(user, id) do
chat_message_refs =
chat
@@ -138,7 +173,7 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do
end
end
- def index(%{assigns: %{user: user}} = conn, params) do
+ def index(%{assigns: %{user: user}, private: %{open_api_spex: %{params: params}}} = conn, _) do
chats =
index_query(user, params)
|> Repo.all()
@@ -146,7 +181,7 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do
render(conn, "index.json", chats: chats)
end
- def index2(%{assigns: %{user: user}} = conn, params) do
+ def index2(%{assigns: %{user: user}, private: %{open_api_spex: %{params: params}}} = conn, _) do
chats =
index_query(user, params)
|> Pagination.fetch_paginated(params)
@@ -166,14 +201,14 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do
|> where([c], c.recipient not in ^exclude_users)
end
- def create(%{assigns: %{user: user}} = conn, %{id: id}) do
+ def create(%{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: id}}}} = conn, _) do
with %User{ap_id: recipient} <- User.get_cached_by_id(id),
{:ok, %Chat{} = chat} <- Chat.get_or_create(user.id, recipient) do
render(conn, "show.json", chat: chat)
end
end
- def show(%{assigns: %{user: user}} = conn, %{id: id}) do
+ def show(%{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: id}}}} = conn, _) do
with {:ok, chat} <- Chat.get_by_user_and_id(user, id) do
render(conn, "show.json", chat: chat)
end
diff --git a/lib/pleroma/web/pleroma_api/controllers/conversation_controller.ex b/lib/pleroma/web/pleroma_api/controllers/conversation_controller.ex
index 37990db..37990db 100755..100644
--- a/lib/pleroma/web/pleroma_api/controllers/conversation_controller.ex
+++ b/lib/pleroma/web/pleroma_api/controllers/conversation_controller.ex
diff --git a/lib/pleroma/web/pleroma_api/controllers/emoji_file_controller.ex b/lib/pleroma/web/pleroma_api/controllers/emoji_file_controller.ex
index f854cf9..00fb304 100755..100644
--- a/lib/pleroma/web/pleroma_api/controllers/emoji_file_controller.ex
+++ b/lib/pleroma/web/pleroma_api/controllers/emoji_file_controller.ex
@@ -8,7 +8,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiFileController do
alias Pleroma.Emoji.Pack
alias Pleroma.Web.ApiSpec
- plug(Pleroma.Web.ApiSpec.CastAndValidate)
+ plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
plug(
Pleroma.Web.Plugs.OAuthScopesPlug,
@@ -22,7 +22,10 @@ defmodule Pleroma.Web.PleromaAPI.EmojiFileController do
defdelegate open_api_operation(action), to: ApiSpec.PleromaEmojiFileOperation
- def create(%{body_params: params} = conn, %{name: pack_name}) do
+ def create(
+ %{private: %{open_api_spex: %{body_params: params, params: %{name: pack_name}}}} = conn,
+ _
+ ) do
filename = params[:filename] || get_filename(params[:file])
shortcode = params[:shortcode] || Path.basename(filename, Path.extname(filename))
@@ -49,7 +52,17 @@ defmodule Pleroma.Web.PleromaAPI.EmojiFileController do
end
end
- def update(%{body_params: %{shortcode: shortcode} = params} = conn, %{name: pack_name}) do
+ def update(
+ %{
+ private: %{
+ open_api_spex: %{
+ body_params: %{shortcode: shortcode} = params,
+ params: %{name: pack_name}
+ }
+ }
+ } = conn,
+ _
+ ) do
new_shortcode = params[:new_shortcode]
new_filename = params[:new_filename]
force = params[:force]
@@ -80,7 +93,10 @@ defmodule Pleroma.Web.PleromaAPI.EmojiFileController do
end
end
- def delete(conn, %{name: pack_name, shortcode: shortcode}) do
+ def delete(
+ %{private: %{open_api_spex: %{params: %{name: pack_name, shortcode: shortcode}}}} = conn,
+ _
+ ) do
with {:ok, pack} <- Pack.load_pack(pack_name),
{:ok, pack} <- Pack.delete_file(pack, shortcode) do
json(conn, pack.files)
diff --git a/lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex b/lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex
index 420fea1..32360d2 100755..100644
--- a/lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex
+++ b/lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex
@@ -7,7 +7,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackController do
alias Pleroma.Emoji.Pack
- plug(Pleroma.Web.ApiSpec.CastAndValidate)
+ plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
plug(
Pleroma.Web.Plugs.OAuthScopesPlug,
@@ -26,7 +26,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackController do
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.PleromaEmojiPackOperation
- def remote(conn, params) do
+ def remote(%{private: %{open_api_spex: %{params: params}}} = conn, _) do
with {:ok, packs} <-
Pack.list_remote(url: params.url, page_size: params.page_size, page: params.page) do
json(conn, packs)
@@ -38,7 +38,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackController do
end
end
- def index(conn, params) do
+ def index(%{private: %{open_api_spex: %{params: params}}} = conn, _) do
emoji_path =
[:instance, :static_dir]
|> Pleroma.Config.get!()
@@ -61,7 +61,11 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackController do
end
end
- def show(conn, %{name: name, page: page, page_size: page_size}) do
+ def show(
+ %{private: %{open_api_spex: %{params: %{name: name, page: page, page_size: page_size}}}} =
+ conn,
+ _
+ ) do
name = String.trim(name)
with {:ok, pack} <- Pack.show(name: name, page: page, page_size: page_size) do
@@ -90,7 +94,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackController do
end
end
- def archive(conn, %{name: name}) do
+ def archive(%{private: %{open_api_spex: %{params: %{name: name}}}} = conn, _) do
with {:ok, archive} <- Pack.get_archive(name) do
send_download(conn, {:binary, archive}, filename: "#{name}.zip")
else
@@ -109,7 +113,10 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackController do
end
end
- def download(%{body_params: %{url: url, name: name} = params} = conn, _) do
+ def download(
+ %{private: %{open_api_spex: %{body_params: %{url: url, name: name} = params}}} = conn,
+ _
+ ) do
with {:ok, _pack} <- Pack.download(name, url, params[:as]) do
json(conn, "ok")
else
@@ -130,7 +137,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackController do
end
end
- def create(conn, %{name: name}) do
+ def create(%{private: %{open_api_spex: %{params: %{name: name}}}} = conn, _) do
name = String.trim(name)
with {:ok, _pack} <- Pack.create(name) do
@@ -159,7 +166,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackController do
end
end
- def delete(conn, %{name: name}) do
+ def delete(%{private: %{open_api_spex: %{params: %{name: name}}}} = conn, _) do
name = String.trim(name)
with {:ok, deleted} when deleted != [] <- Pack.delete(name) do
@@ -184,7 +191,11 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackController do
end
end
- def update(%{body_params: %{metadata: metadata}} = conn, %{name: name}) do
+ def update(
+ %{private: %{open_api_spex: %{body_params: %{metadata: metadata}, params: %{name: name}}}} =
+ conn,
+ _
+ ) do
with {:ok, pack} <- Pack.update_metadata(name, metadata) do
json(conn, pack.pack)
else
diff --git a/lib/pleroma/web/pleroma_api/controllers/emoji_reaction_controller.ex b/lib/pleroma/web/pleroma_api/controllers/emoji_reaction_controller.ex
index 78fd0b2..662cc15 100755..100644
--- a/lib/pleroma/web/pleroma_api/controllers/emoji_reaction_controller.ex
+++ b/lib/pleroma/web/pleroma_api/controllers/emoji_reaction_controller.ex
@@ -28,8 +28,8 @@ defmodule Pleroma.Web.PleromaAPI.EmojiReactionController do
def index(%{assigns: %{user: user}} = conn, %{id: activity_id} = params) do
with true <- Pleroma.Config.get([:instance, :show_reactions]),
%Activity{} = activity <- Activity.get_by_id_with_object(activity_id),
- %Object{data: %{"reactions" => reactions}} when is_list(reactions) <-
- Object.normalize(activity, fetch: false) do
+ %Object{} = object <- Object.normalize(activity, fetch: false),
+ reactions <- Object.get_emoji_reactions(object) do
reactions =
reactions
|> filter(params)
@@ -50,29 +50,32 @@ defmodule Pleroma.Web.PleromaAPI.EmojiReactionController do
if not with_muted, do: User.cached_muted_users_ap_ids(user), else: []
end
- filter_emoji = fn emoji, users ->
+ filter_emoji = fn emoji, users, url ->
case Enum.reject(users, &(&1 in exclude_ap_ids)) do
[] -> nil
- users -> {emoji, users}
+ users -> {emoji, users, url}
end
end
reactions
|> Stream.map(fn
- [emoji, users] when is_list(users) -> filter_emoji.(emoji, users)
- {emoji, users} when is_list(users) -> filter_emoji.(emoji, users)
- _ -> nil
+ [emoji, users, url] when is_list(users) -> filter_emoji.(emoji, users, url)
end)
|> Stream.reject(&is_nil/1)
end
defp filter(reactions, %{emoji: emoji}) when is_binary(emoji) do
- Enum.filter(reactions, fn [e, _] -> e == emoji end)
+ Enum.filter(reactions, fn [e, _, _] -> e == emoji end)
end
defp filter(reactions, _), do: reactions
def create(%{assigns: %{user: user}} = conn, %{id: activity_id, emoji: emoji}) do
+ emoji =
+ emoji
+ |> Pleroma.Emoji.fully_qualify_emoji()
+ |> Pleroma.Emoji.maybe_quote()
+
with {:ok, _activity} <- CommonAPI.react_with_emoji(activity_id, user, emoji) do
activity = Activity.get_by_id(activity_id)
@@ -83,6 +86,11 @@ defmodule Pleroma.Web.PleromaAPI.EmojiReactionController do
end
def delete(%{assigns: %{user: user}} = conn, %{id: activity_id, emoji: emoji}) do
+ emoji =
+ emoji
+ |> Pleroma.Emoji.fully_qualify_emoji()
+ |> Pleroma.Emoji.maybe_quote()
+
with {:ok, _activity} <- CommonAPI.unreact_with_emoji(activity_id, user, emoji) do
activity = Activity.get_by_id(activity_id)
diff --git a/lib/pleroma/web/pleroma_api/controllers/instances_controller.ex b/lib/pleroma/web/pleroma_api/controllers/instances_controller.ex
index 6257e31..6257e31 100755..100644
--- a/lib/pleroma/web/pleroma_api/controllers/instances_controller.ex
+++ b/lib/pleroma/web/pleroma_api/controllers/instances_controller.ex
diff --git a/lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex b/lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex
index 66e9d84..3208cde 100755..100644
--- a/lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex
+++ b/lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex
@@ -10,7 +10,7 @@ defmodule Pleroma.Web.PleromaAPI.MascotController do
alias Pleroma.Web.Plugs.OAuthScopesPlug
plug(Majic.Plug, [pool: Pleroma.MajicPool] when action in [:update])
- plug(Pleroma.Web.ApiSpec.CastAndValidate)
+ plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
plug(OAuthScopesPlug, %{scopes: ["read:accounts"]} when action == :show)
plug(OAuthScopesPlug, %{scopes: ["write:accounts"]} when action != :show)
@@ -22,9 +22,13 @@ defmodule Pleroma.Web.PleromaAPI.MascotController do
end
@doc "PUT /api/v1/pleroma/mascot"
- def update(%{assigns: %{user: user}, body_params: %{file: file}} = conn, _) do
+ def update(
+ %{assigns: %{user: user}, private: %{open_api_spex: %{body_params: %{file: file}}}} =
+ conn,
+ _
+ ) do
with {:content_type, "image" <> _} <- {:content_type, file.content_type},
- {:ok, object} <- ActivityPub.upload(file, actor: User.ap_id(user)) do
+ {_, {:ok, object}} <- {:upload, ActivityPub.upload(file, actor: User.ap_id(user))} do
attachment = render_attachment(object)
{:ok, _user} = User.mascot_update(user, attachment)
@@ -32,6 +36,9 @@ defmodule Pleroma.Web.PleromaAPI.MascotController do
else
{:content_type, _} ->
render_error(conn, :unsupported_media_type, "mascots can only be images")
+
+ {:upload, {:error, _}} ->
+ render_error(conn, :error, "error uploading file")
end
end
diff --git a/lib/pleroma/web/pleroma_api/controllers/notification_controller.ex b/lib/pleroma/web/pleroma_api/controllers/notification_controller.ex
index 87ea81c..f860eaf 100755..100644
--- a/lib/pleroma/web/pleroma_api/controllers/notification_controller.ex
+++ b/lib/pleroma/web/pleroma_api/controllers/notification_controller.ex
@@ -7,7 +7,7 @@ defmodule Pleroma.Web.PleromaAPI.NotificationController do
alias Pleroma.Notification
- plug(Pleroma.Web.ApiSpec.CastAndValidate)
+ plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
plug(
Pleroma.Web.Plugs.OAuthScopesPlug,
@@ -16,7 +16,13 @@ defmodule Pleroma.Web.PleromaAPI.NotificationController do
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.PleromaNotificationOperation
- def mark_as_read(%{assigns: %{user: user}, body_params: %{id: notification_id}} = conn, _) do
+ def mark_as_read(
+ %{
+ assigns: %{user: user},
+ private: %{open_api_spex: %{body_params: %{id: notification_id}}}
+ } = conn,
+ _
+ ) do
with {:ok, notification} <- Notification.read_one(user, notification_id) do
render(conn, "show.json", notification: notification, for: user)
else
@@ -27,7 +33,11 @@ defmodule Pleroma.Web.PleromaAPI.NotificationController do
end
end
- def mark_as_read(%{assigns: %{user: user}, body_params: %{max_id: max_id}} = conn, _) do
+ def mark_as_read(
+ %{assigns: %{user: user}, private: %{open_api_spex: %{body_params: %{max_id: max_id}}}} =
+ conn,
+ _
+ ) do
notifications =
user
|> Notification.set_read_up_to(max_id)
diff --git a/lib/pleroma/web/pleroma_api/controllers/report_controller.ex b/lib/pleroma/web/pleroma_api/controllers/report_controller.ex
index 1f0a82c..1f0a82c 100755..100644
--- a/lib/pleroma/web/pleroma_api/controllers/report_controller.ex
+++ b/lib/pleroma/web/pleroma_api/controllers/report_controller.ex
diff --git a/lib/pleroma/web/pleroma_api/controllers/scrobble_controller.ex b/lib/pleroma/web/pleroma_api/controllers/scrobble_controller.ex
index bf6dc50..bf6dc50 100755..100644
--- a/lib/pleroma/web/pleroma_api/controllers/scrobble_controller.ex
+++ b/lib/pleroma/web/pleroma_api/controllers/scrobble_controller.ex
diff --git a/lib/pleroma/web/pleroma_api/controllers/settings_controller.ex b/lib/pleroma/web/pleroma_api/controllers/settings_controller.ex
index 1136575..1136575 100755..100644
--- a/lib/pleroma/web/pleroma_api/controllers/settings_controller.ex
+++ b/lib/pleroma/web/pleroma_api/controllers/settings_controller.ex
diff --git a/lib/pleroma/web/pleroma_api/controllers/status_controller.ex b/lib/pleroma/web/pleroma_api/controllers/status_controller.ex
new file mode 100644
index 0000000..482662f
--- /dev/null
+++ b/lib/pleroma/web/pleroma_api/controllers/status_controller.ex
@@ -0,0 +1,66 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.PleromaAPI.StatusController do
+ use Pleroma.Web, :controller
+
+ import Pleroma.Web.ControllerHelper, only: [add_link_headers: 2]
+
+ require Ecto.Query
+ require Pleroma.Constants
+
+ alias Pleroma.Activity
+ alias Pleroma.User
+ alias Pleroma.Web.ActivityPub.ActivityPub
+ alias Pleroma.Web.ActivityPub.Visibility
+ alias Pleroma.Web.MastodonAPI.StatusView
+ alias Pleroma.Web.Plugs.OAuthScopesPlug
+
+ plug(Pleroma.Web.ApiSpec.CastAndValidate)
+
+ action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
+
+ plug(
+ OAuthScopesPlug,
+ %{scopes: ["read:statuses"], fallback: :proceed_unauthenticated} when action == :quotes
+ )
+
+ defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.PleromaStatusOperation
+
+ @doc "GET /api/v1/pleroma/statuses/:id/quotes"
+ def quotes(%{assigns: %{user: user}} = conn, %{id: id} = params) do
+ with %Activity{object: object} = activity <- Activity.get_by_id_with_object(id),
+ true <- Visibility.visible_for_user?(activity, user) do
+ params =
+ params
+ |> Map.put(:type, "Create")
+ |> Map.put(:blocking_user, user)
+ |> Map.put(:quote_url, object.data["id"])
+
+ recipients =
+ if user do
+ [Pleroma.Constants.as_public()] ++ [user.ap_id | User.following(user)]
+ else
+ [Pleroma.Constants.as_public()]
+ end
+
+ activities =
+ recipients
+ |> ActivityPub.fetch_activities(params)
+ |> Enum.reverse()
+
+ conn
+ |> add_link_headers(activities)
+ |> put_view(StatusView)
+ |> render("index.json",
+ activities: activities,
+ for: user,
+ as: :activity
+ )
+ else
+ nil -> {:error, :not_found}
+ false -> {:error, :not_found}
+ end
+ end
+end
diff --git a/lib/pleroma/web/pleroma_api/controllers/two_factor_authentication_controller.ex b/lib/pleroma/web/pleroma_api/controllers/two_factor_authentication_controller.ex
index e69847b..e69847b 100755..100644
--- a/lib/pleroma/web/pleroma_api/controllers/two_factor_authentication_controller.ex
+++ b/lib/pleroma/web/pleroma_api/controllers/two_factor_authentication_controller.ex
diff --git a/lib/pleroma/web/pleroma_api/controllers/user_import_controller.ex b/lib/pleroma/web/pleroma_api/controllers/user_import_controller.ex
index 90428a5..96466f1 100755..100644
--- a/lib/pleroma/web/pleroma_api/controllers/user_import_controller.ex
+++ b/lib/pleroma/web/pleroma_api/controllers/user_import_controller.ex
@@ -15,14 +15,21 @@ defmodule Pleroma.Web.PleromaAPI.UserImportController do
plug(OAuthScopesPlug, %{scopes: ["follow", "write:blocks"]} when action == :blocks)
plug(OAuthScopesPlug, %{scopes: ["follow", "write:mutes"]} when action == :mutes)
- plug(Pleroma.Web.ApiSpec.CastAndValidate)
+ plug(Pleroma.Web.ApiSpec.CastAndValidate, replace_params: false)
defdelegate open_api_operation(action), to: ApiSpec.UserImportOperation
- def follow(%{body_params: %{list: %Plug.Upload{path: path}}} = conn, _) do
- follow(%Plug.Conn{conn | body_params: %{list: File.read!(path)}}, %{})
+ def follow(
+ %{private: %{open_api_spex: %{body_params: %{list: %Plug.Upload{path: path}}}}} = conn,
+ _
+ ) do
+ list = File.read!(path)
+ do_follow(conn, list)
end
- def follow(%{assigns: %{user: follower}, body_params: %{list: list}} = conn, _) do
+ def follow(%{private: %{open_api_spex: %{body_params: %{list: list}}}} = conn, _),
+ do: do_follow(conn, list)
+
+ def do_follow(%{assigns: %{user: follower}} = conn, list) do
identifiers =
list
|> String.split("\n")
@@ -35,20 +42,34 @@ defmodule Pleroma.Web.PleromaAPI.UserImportController do
json(conn, "job started")
end
- def blocks(%{body_params: %{list: %Plug.Upload{path: path}}} = conn, _) do
- blocks(%Plug.Conn{conn | body_params: %{list: File.read!(path)}}, %{})
+ def blocks(
+ %{private: %{open_api_spex: %{body_params: %{list: %Plug.Upload{path: path}}}}} = conn,
+ _
+ ) do
+ list = File.read!(path)
+ do_block(conn, list)
end
- def blocks(%{assigns: %{user: blocker}, body_params: %{list: list}} = conn, _) do
+ def blocks(%{private: %{open_api_spex: %{body_params: %{list: list}}}} = conn, _),
+ do: do_block(conn, list)
+
+ defp do_block(%{assigns: %{user: blocker}} = conn, list) do
User.Import.blocks_import(blocker, prepare_user_identifiers(list))
json(conn, "job started")
end
- def mutes(%{body_params: %{list: %Plug.Upload{path: path}}} = conn, _) do
- mutes(%Plug.Conn{conn | body_params: %{list: File.read!(path)}}, %{})
+ def mutes(
+ %{private: %{open_api_spex: %{body_params: %{list: %Plug.Upload{path: path}}}}} = conn,
+ _
+ ) do
+ list = File.read!(path)
+ do_mute(conn, list)
end
- def mutes(%{assigns: %{user: user}, body_params: %{list: list}} = conn, _) do
+ def mutes(%{private: %{open_api_spex: %{body_params: %{list: list}}}} = conn, _),
+ do: do_mute(conn, list)
+
+ defp do_mute(%{assigns: %{user: user}} = conn, list) do
User.Import.mutes_import(user, prepare_user_identifiers(list))
json(conn, "job started")
end
diff --git a/lib/pleroma/web/pleroma_api/views/account_view.ex b/lib/pleroma/web/pleroma_api/views/account_view.ex
index 910bcee..910bcee 100755..100644
--- a/lib/pleroma/web/pleroma_api/views/account_view.ex
+++ b/lib/pleroma/web/pleroma_api/views/account_view.ex
diff --git a/lib/pleroma/web/pleroma_api/views/app_view.ex b/lib/pleroma/web/pleroma_api/views/app_view.ex
index 1fdc3c2..1fdc3c2 100755..100644
--- a/lib/pleroma/web/pleroma_api/views/app_view.ex
+++ b/lib/pleroma/web/pleroma_api/views/app_view.ex
diff --git a/lib/pleroma/web/pleroma_api/views/backup_view.ex b/lib/pleroma/web/pleroma_api/views/backup_view.ex
index d778590..20403ae 100755..100644
--- a/lib/pleroma/web/pleroma_api/views/backup_view.ex
+++ b/lib/pleroma/web/pleroma_api/views/backup_view.ex
@@ -9,12 +9,22 @@ defmodule Pleroma.Web.PleromaAPI.BackupView do
alias Pleroma.Web.CommonAPI.Utils
def render("show.json", %{backup: %Backup{} = backup}) do
+ # To deal with records before the migration
+ state =
+ if backup.state == :invalid do
+ if backup.processed, do: :complete, else: :failed
+ else
+ backup.state
+ end
+
%{
id: backup.id,
content_type: backup.content_type,
url: download_url(backup),
file_size: backup.file_size,
processed: backup.processed,
+ state: to_string(state),
+ processed_number: backup.processed_number,
inserted_at: Utils.to_masto_date(backup.inserted_at)
}
end
diff --git a/lib/pleroma/web/pleroma_api/views/bookmark_folder_view.ex b/lib/pleroma/web/pleroma_api/views/bookmark_folder_view.ex
new file mode 100644
index 0000000..12decb8
--- /dev/null
+++ b/lib/pleroma/web/pleroma_api/views/bookmark_folder_view.ex
@@ -0,0 +1,42 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2024 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.PleromaAPI.BookmarkFolderView do
+ use Pleroma.Web, :view
+
+ alias Pleroma.BookmarkFolder
+ alias Pleroma.Emoji
+ alias Pleroma.Web.Endpoint
+
+ def render("show.json", %{folder: %BookmarkFolder{} = folder}) do
+ %{
+ id: folder.id |> to_string(),
+ name: folder.name,
+ emoji: folder.emoji,
+ emoji_url: get_emoji_url(folder.emoji)
+ }
+ end
+
+ def render("index.json", %{folders: folders} = opts) do
+ render_many(folders, __MODULE__, "show.json", Map.delete(opts, :folders))
+ end
+
+ defp get_emoji_url(nil) do
+ nil
+ end
+
+ defp get_emoji_url(emoji) do
+ if Emoji.unicode?(emoji) do
+ nil
+ else
+ emoji = Emoji.get(emoji)
+
+ if emoji != nil do
+ Endpoint.url() |> URI.merge(emoji.file) |> to_string()
+ else
+ nil
+ end
+ end
+ end
+end
diff --git a/lib/pleroma/web/pleroma_api/views/chat/message_reference_view.ex b/lib/pleroma/web/pleroma_api/views/chat/message_reference_view.ex
index 241bf00..a1c88d0 100755..100644
--- a/lib/pleroma/web/pleroma_api/views/chat/message_reference_view.ex
+++ b/lib/pleroma/web/pleroma_api/views/chat/message_reference_view.ex
@@ -9,6 +9,7 @@ defmodule Pleroma.Web.PleromaAPI.Chat.MessageReferenceView do
alias Pleroma.User
alias Pleroma.Web.CommonAPI.Utils
alias Pleroma.Web.MastodonAPI.StatusView
+ alias Pleroma.Web.RichMedia.Card
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
@@ -23,6 +24,12 @@ defmodule Pleroma.Web.PleromaAPI.Chat.MessageReferenceView do
}
}
) do
+ card =
+ case Card.get_by_object(object) do
+ %Card{} = card_data -> StatusView.render("card.json", card_data)
+ _ -> nil
+ end
+
%{
id: id |> to_string(),
content: chat_message["content"],
@@ -34,11 +41,7 @@ defmodule Pleroma.Web.PleromaAPI.Chat.MessageReferenceView do
chat_message["attachment"] &&
StatusView.render("attachment.json", attachment: chat_message["attachment"]),
unread: unread,
- card:
- StatusView.render(
- "card.json",
- Pleroma.Web.RichMedia.Helpers.fetch_data_for_object(object)
- )
+ card: card
}
|> put_idempotency_key()
end
diff --git a/lib/pleroma/web/pleroma_api/views/chat_view.ex b/lib/pleroma/web/pleroma_api/views/chat_view.ex
index db6c13c..db6c13c 100755..100644
--- a/lib/pleroma/web/pleroma_api/views/chat_view.ex
+++ b/lib/pleroma/web/pleroma_api/views/chat_view.ex
diff --git a/lib/pleroma/web/pleroma_api/views/conversation_view.ex b/lib/pleroma/web/pleroma_api/views/conversation_view.ex
index 2c9c8d1..2c9c8d1 100755..100644
--- a/lib/pleroma/web/pleroma_api/views/conversation_view.ex
+++ b/lib/pleroma/web/pleroma_api/views/conversation_view.ex
diff --git a/lib/pleroma/web/pleroma_api/views/emoji_reaction_view.ex b/lib/pleroma/web/pleroma_api/views/emoji_reaction_view.ex
index 68ebd82..6df4ab9 100755..100644
--- a/lib/pleroma/web/pleroma_api/views/emoji_reaction_view.ex
+++ b/lib/pleroma/web/pleroma_api/views/emoji_reaction_view.ex
@@ -7,17 +7,30 @@ defmodule Pleroma.Web.PleromaAPI.EmojiReactionView do
alias Pleroma.Web.MastodonAPI.AccountView
+ def emoji_name(emoji, nil), do: emoji
+
+ def emoji_name(emoji, url) do
+ url = URI.parse(url)
+
+ if url.host == Pleroma.Web.Endpoint.host() do
+ emoji
+ else
+ "#{emoji}@#{url.host}"
+ end
+ end
+
def render("index.json", %{emoji_reactions: emoji_reactions} = opts) do
render_many(emoji_reactions, __MODULE__, "show.json", opts)
end
- def render("show.json", %{emoji_reaction: {emoji, user_ap_ids}, user: user}) do
+ def render("show.json", %{emoji_reaction: {emoji, user_ap_ids, url}, user: user}) do
users = fetch_users(user_ap_ids)
%{
- name: emoji,
+ name: emoji_name(emoji, url),
count: length(users),
accounts: render(AccountView, "index.json", users: users, for: user),
+ url: Pleroma.Web.MediaProxy.url(url),
me: !!(user && user.ap_id in user_ap_ids)
}
end
diff --git a/lib/pleroma/web/pleroma_api/views/notification_view.ex b/lib/pleroma/web/pleroma_api/views/notification_view.ex
index db7f948..db7f948 100755..100644
--- a/lib/pleroma/web/pleroma_api/views/notification_view.ex
+++ b/lib/pleroma/web/pleroma_api/views/notification_view.ex
diff --git a/lib/pleroma/web/pleroma_api/views/report_view.ex b/lib/pleroma/web/pleroma_api/views/report_view.ex
index 127e8f0..127e8f0 100755..100644
--- a/lib/pleroma/web/pleroma_api/views/report_view.ex
+++ b/lib/pleroma/web/pleroma_api/views/report_view.ex
diff --git a/lib/pleroma/web/pleroma_api/views/scrobble_view.ex b/lib/pleroma/web/pleroma_api/views/scrobble_view.ex
index a5985fb..edf0a23 100755..100644
--- a/lib/pleroma/web/pleroma_api/views/scrobble_view.ex
+++ b/lib/pleroma/web/pleroma_api/views/scrobble_view.ex
@@ -27,6 +27,7 @@ defmodule Pleroma.Web.PleromaAPI.ScrobbleView do
title: object.data["title"] |> HTML.strip_tags(),
artist: object.data["artist"] |> HTML.strip_tags(),
album: object.data["album"] |> HTML.strip_tags(),
+ externalLink: object.data["externalLink"],
length: object.data["length"]
}
end
diff --git a/lib/pleroma/web/plug.ex b/lib/pleroma/web/plug.ex
index 29ab52e..29ab52e 100755..100644
--- a/lib/pleroma/web/plug.ex
+++ b/lib/pleroma/web/plug.ex
diff --git a/lib/pleroma/web/plugs/admin_secret_authentication_plug.ex b/lib/pleroma/web/plugs/admin_secret_authentication_plug.ex
index 2e4702f..2e4702f 100755..100644
--- a/lib/pleroma/web/plugs/admin_secret_authentication_plug.ex
+++ b/lib/pleroma/web/plugs/admin_secret_authentication_plug.ex
diff --git a/lib/pleroma/web/plugs/authentication_plug.ex b/lib/pleroma/web/plugs/authentication_plug.ex
index f912a15..f912a15 100755..100644
--- a/lib/pleroma/web/plugs/authentication_plug.ex
+++ b/lib/pleroma/web/plugs/authentication_plug.ex
diff --git a/lib/pleroma/web/plugs/basic_auth_decoder_plug.ex b/lib/pleroma/web/plugs/basic_auth_decoder_plug.ex
index 3eb13f9..3eb13f9 100755..100644
--- a/lib/pleroma/web/plugs/basic_auth_decoder_plug.ex
+++ b/lib/pleroma/web/plugs/basic_auth_decoder_plug.ex
diff --git a/lib/pleroma/web/plugs/cache.ex b/lib/pleroma/web/plugs/cache.ex
index 6674778..5a7e86e 100755..100644
--- a/lib/pleroma/web/plugs/cache.ex
+++ b/lib/pleroma/web/plugs/cache.ex
@@ -20,7 +20,7 @@ defmodule Pleroma.Web.Plugs.Cache do
- `ttl`: An expiration time (time-to-live). This value should be in milliseconds or `nil` to disable expiration. Defaults to `nil`.
- `query_params`: Take URL query string into account (`true`), ignore it (`false`) or limit to specific params only (list). Defaults to `true`.
- - `tracking_fun`: A function that is called on successfull responses, no matter if the request is cached or not. It should accept a conn as the first argument and the value assigned to `tracking_fun_data` as the second.
+ - `tracking_fun`: A function that is called on successful responses, no matter if the request is cached or not. It should accept a conn as the first argument and the value assigned to `tracking_fun_data` as the second.
Additionally, you can overwrite the TTL inside a controller action by assigning `cache_ttl` to the connection struct:
diff --git a/lib/pleroma/web/plugs/digest_plug.ex b/lib/pleroma/web/plugs/digest_plug.ex
index 20e265f..20e265f 100755..100644
--- a/lib/pleroma/web/plugs/digest_plug.ex
+++ b/lib/pleroma/web/plugs/digest_plug.ex
diff --git a/lib/pleroma/web/plugs/ensure_authenticated_plug.ex b/lib/pleroma/web/plugs/ensure_authenticated_plug.ex
index 8044a6b..8044a6b 100755..100644
--- a/lib/pleroma/web/plugs/ensure_authenticated_plug.ex
+++ b/lib/pleroma/web/plugs/ensure_authenticated_plug.ex
diff --git a/lib/pleroma/web/plugs/ensure_privileged_plug.ex b/lib/pleroma/web/plugs/ensure_privileged_plug.ex
index f886c87..f886c87 100755..100644
--- a/lib/pleroma/web/plugs/ensure_privileged_plug.ex
+++ b/lib/pleroma/web/plugs/ensure_privileged_plug.ex
diff --git a/lib/pleroma/web/plugs/ensure_public_or_authenticated_plug.ex b/lib/pleroma/web/plugs/ensure_public_or_authenticated_plug.ex
index e98a3b6..e98a3b6 100755..100644
--- a/lib/pleroma/web/plugs/ensure_public_or_authenticated_plug.ex
+++ b/lib/pleroma/web/plugs/ensure_public_or_authenticated_plug.ex
diff --git a/lib/pleroma/web/plugs/ensure_user_token_assigns_plug.ex b/lib/pleroma/web/plugs/ensure_user_token_assigns_plug.ex
index 5c57d27..5c57d27 100755..100644
--- a/lib/pleroma/web/plugs/ensure_user_token_assigns_plug.ex
+++ b/lib/pleroma/web/plugs/ensure_user_token_assigns_plug.ex
diff --git a/lib/pleroma/web/plugs/expect_authenticated_check_plug.ex b/lib/pleroma/web/plugs/expect_authenticated_check_plug.ex
index d1403e2..d1403e2 100755..100644
--- a/lib/pleroma/web/plugs/expect_authenticated_check_plug.ex
+++ b/lib/pleroma/web/plugs/expect_authenticated_check_plug.ex
diff --git a/lib/pleroma/web/plugs/expect_public_or_authenticated_check_plug.ex b/lib/pleroma/web/plugs/expect_public_or_authenticated_check_plug.ex
index a74c763..a74c763 100755..100644
--- a/lib/pleroma/web/plugs/expect_public_or_authenticated_check_plug.ex
+++ b/lib/pleroma/web/plugs/expect_public_or_authenticated_check_plug.ex
diff --git a/lib/pleroma/web/plugs/federating_plug.ex b/lib/pleroma/web/plugs/federating_plug.ex
index d5b8ef3..d5b8ef3 100755..100644
--- a/lib/pleroma/web/plugs/federating_plug.ex
+++ b/lib/pleroma/web/plugs/federating_plug.ex
diff --git a/lib/pleroma/web/plugs/frontend_static.ex b/lib/pleroma/web/plugs/frontend_static.ex
index 6ab8e46..6ab8e46 100755..100644
--- a/lib/pleroma/web/plugs/frontend_static.ex
+++ b/lib/pleroma/web/plugs/frontend_static.ex
diff --git a/lib/pleroma/web/plugs/http_security_plug.ex b/lib/pleroma/web/plugs/http_security_plug.ex
index 34895c8..a27dcd0 100755..100644
--- a/lib/pleroma/web/plugs/http_security_plug.ex
+++ b/lib/pleroma/web/plugs/http_security_plug.ex
@@ -93,19 +93,27 @@ defmodule Pleroma.Web.Plugs.HTTPSecurityPlug do
img_src = "img-src 'self' data: blob:"
media_src = "media-src 'self'"
+ connect_src = ["connect-src 'self' blob: ", static_url, ?\s, websocket_url]
# Strict multimedia CSP enforcement only when MediaProxy is enabled
- {img_src, media_src} =
+ {img_src, media_src, connect_src} =
if Config.get([:media_proxy, :enabled]) &&
!Config.get([:media_proxy, :proxy_opts, :redirect_on_failure]) do
sources = build_csp_multimedia_source_list()
- {[img_src, sources], [media_src, sources]}
+
+ {
+ [img_src, sources],
+ [media_src, sources],
+ [connect_src, sources]
+ }
else
- {[img_src, " https:"], [media_src, " https:"]}
+ {
+ [img_src, " https:"],
+ [media_src, " https:"],
+ [connect_src, " https:"]
+ }
end
- connect_src = ["connect-src 'self' blob: ", static_url, ?\s, websocket_url]
-
connect_src =
if Config.get(:env) == :dev do
[connect_src, " http://localhost:3035/"]
@@ -193,7 +201,7 @@ defmodule Pleroma.Web.Plugs.HTTPSecurityPlug do
def warn_if_disabled do
unless Config.get([:http_security, :enabled]) do
- Logger.warn("
+ Logger.warning("
.i;;;;i.
iYcviii;vXY:
.YXi .i1c.
diff --git a/lib/pleroma/web/plugs/http_signature_plug.ex b/lib/pleroma/web/plugs/http_signature_plug.ex
index 4bf3252..e814efc 100755..100644
--- a/lib/pleroma/web/plugs/http_signature_plug.ex
+++ b/lib/pleroma/web/plugs/http_signature_plug.ex
@@ -16,7 +16,7 @@ defmodule Pleroma.Web.Plugs.HTTPSignaturePlug do
end
def call(conn, _opts) do
- if get_format(conn) == "activity+json" do
+ if get_format(conn) in ["json", "activity+json"] do
conn
|> maybe_assign_valid_signature()
|> maybe_require_signature()
diff --git a/lib/pleroma/web/plugs/idempotency_plug.ex b/lib/pleroma/web/plugs/idempotency_plug.ex
index a3b7af8..a3b7af8 100755..100644
--- a/lib/pleroma/web/plugs/idempotency_plug.ex
+++ b/lib/pleroma/web/plugs/idempotency_plug.ex
diff --git a/lib/pleroma/web/plugs/instance_static.ex b/lib/pleroma/web/plugs/instance_static.ex
index 75bfdd6..75bfdd6 100755..100644
--- a/lib/pleroma/web/plugs/instance_static.ex
+++ b/lib/pleroma/web/plugs/instance_static.ex
diff --git a/lib/pleroma/web/plugs/mapped_signature_to_identity_plug.ex b/lib/pleroma/web/plugs/mapped_signature_to_identity_plug.ex
index c6d5310..c6d5310 100755..100644
--- a/lib/pleroma/web/plugs/mapped_signature_to_identity_plug.ex
+++ b/lib/pleroma/web/plugs/mapped_signature_to_identity_plug.ex
diff --git a/lib/pleroma/web/plugs/o_auth_plug.ex b/lib/pleroma/web/plugs/o_auth_plug.ex
index ba04ddb..b59ac9d 100755..100644
--- a/lib/pleroma/web/plugs/o_auth_plug.ex
+++ b/lib/pleroma/web/plugs/o_auth_plug.ex
@@ -23,14 +23,14 @@ defmodule Pleroma.Web.Plugs.OAuthPlug do
def call(conn, _) do
with {:ok, token_str} <- fetch_token_str(conn) do
with {:ok, user, user_token} <- fetch_user_and_token(token_str),
- false <- Token.is_expired?(user_token) do
+ false <- Token.expired?(user_token) do
conn
|> assign(:token, user_token)
|> assign(:user, user)
else
_ ->
with {:ok, app, app_token} <- fetch_app_and_token(token_str),
- false <- Token.is_expired?(app_token) do
+ false <- Token.expired?(app_token) do
conn
|> assign(:token, app_token)
|> assign(:app, app)
diff --git a/lib/pleroma/web/plugs/o_auth_scopes_plug.ex b/lib/pleroma/web/plugs/o_auth_scopes_plug.ex
index faf0fd8..faf0fd8 100755..100644
--- a/lib/pleroma/web/plugs/o_auth_scopes_plug.ex
+++ b/lib/pleroma/web/plugs/o_auth_scopes_plug.ex
diff --git a/lib/pleroma/web/plugs/plug_helper.ex b/lib/pleroma/web/plugs/plug_helper.ex
index 21bf035..21bf035 100755..100644
--- a/lib/pleroma/web/plugs/plug_helper.ex
+++ b/lib/pleroma/web/plugs/plug_helper.ex
diff --git a/lib/pleroma/web/plugs/rate_limiter.ex b/lib/pleroma/web/plugs/rate_limiter.ex
index 2080b06..aa79dbf 100755..100644
--- a/lib/pleroma/web/plugs/rate_limiter.ex
+++ b/lib/pleroma/web/plugs/rate_limiter.ex
@@ -89,7 +89,7 @@ defmodule Pleroma.Web.Plugs.RateLimiter do
end
defp handle_disabled(conn) do
- Logger.warn(
+ Logger.warning(
"Rate limiter disabled due to forwarded IP not being found. Please ensure your reverse proxy is providing the X-Forwarded-For header or disable the RemoteIP plug/rate limiter."
)
diff --git a/lib/pleroma/web/plugs/rate_limiter/limiter_supervisor.ex b/lib/pleroma/web/plugs/rate_limiter/limiter_supervisor.ex
index a96be67..a96be67 100755..100644
--- a/lib/pleroma/web/plugs/rate_limiter/limiter_supervisor.ex
+++ b/lib/pleroma/web/plugs/rate_limiter/limiter_supervisor.ex
diff --git a/lib/pleroma/web/plugs/rate_limiter/supervisor.ex b/lib/pleroma/web/plugs/rate_limiter/supervisor.ex
index f00f3d9..5f79a3e 100755..100644
--- a/lib/pleroma/web/plugs/rate_limiter/supervisor.ex
+++ b/lib/pleroma/web/plugs/rate_limiter/supervisor.ex
@@ -14,7 +14,7 @@ defmodule Pleroma.Web.Plugs.RateLimiter.Supervisor do
Pleroma.Web.Plugs.RateLimiter.LimiterSupervisor
]
- opts = [strategy: :one_for_one, name: Pleroma.Web.Streamer.Supervisor]
+ opts = [strategy: :one_for_one]
Supervisor.init(children, opts)
end
end
diff --git a/lib/pleroma/web/plugs/remote_ip.ex b/lib/pleroma/web/plugs/remote_ip.ex
index f207d9f..9f733a9 100755..100644
--- a/lib/pleroma/web/plugs/remote_ip.ex
+++ b/lib/pleroma/web/plugs/remote_ip.ex
@@ -43,6 +43,6 @@ defmodule Pleroma.Web.Plugs.RemoteIp do
InetCidr.v6?(InetCidr.parse_address!(proxy)) -> proxy <> "/128"
end
- InetCidr.parse(proxy, true)
+ InetCidr.parse_cidr!(proxy, true)
end
end
diff --git a/lib/pleroma/web/plugs/set_format_plug.ex b/lib/pleroma/web/plugs/set_format_plug.ex
index 84c67e7..84c67e7 100755..100644
--- a/lib/pleroma/web/plugs/set_format_plug.ex
+++ b/lib/pleroma/web/plugs/set_format_plug.ex
diff --git a/lib/pleroma/web/plugs/set_locale_plug.ex b/lib/pleroma/web/plugs/set_locale_plug.ex
index 271912a..271912a 100755..100644
--- a/lib/pleroma/web/plugs/set_locale_plug.ex
+++ b/lib/pleroma/web/plugs/set_locale_plug.ex
diff --git a/lib/pleroma/web/plugs/set_user_session_id_plug.ex b/lib/pleroma/web/plugs/set_user_session_id_plug.ex
index c372145..c372145 100755..100644
--- a/lib/pleroma/web/plugs/set_user_session_id_plug.ex
+++ b/lib/pleroma/web/plugs/set_user_session_id_plug.ex
diff --git a/lib/pleroma/web/plugs/static_fe_plug.ex b/lib/pleroma/web/plugs/static_fe_plug.ex
index 9a364fd..9a364fd 100755..100644
--- a/lib/pleroma/web/plugs/static_fe_plug.ex
+++ b/lib/pleroma/web/plugs/static_fe_plug.ex
diff --git a/lib/pleroma/web/plugs/trailing_format_plug.ex b/lib/pleroma/web/plugs/trailing_format_plug.ex
index a883ba5..a883ba5 100755..100644
--- a/lib/pleroma/web/plugs/trailing_format_plug.ex
+++ b/lib/pleroma/web/plugs/trailing_format_plug.ex
diff --git a/lib/pleroma/web/plugs/uploaded_media.ex b/lib/pleroma/web/plugs/uploaded_media.ex
index ad81432..f1076da 100755..100644
--- a/lib/pleroma/web/plugs/uploaded_media.ex
+++ b/lib/pleroma/web/plugs/uploaded_media.ex
@@ -35,9 +35,9 @@ defmodule Pleroma.Web.Plugs.UploadedMedia do
conn =
case fetch_query_params(conn) do
%{query_params: %{"name" => name}} = conn ->
- name = String.replace(name, "\"", "\\\"")
+ name = String.replace(name, ~s["], ~s[\\"])
- put_resp_header(conn, "content-disposition", "filename=\"#{name}\"")
+ put_resp_header(conn, "content-disposition", ~s[inline; filename="#{name}"])
conn ->
conn
@@ -105,7 +105,7 @@ defmodule Pleroma.Web.Plugs.UploadedMedia do
end
defp get_media(conn, unknown, _, _) do
- Logger.error("#{__MODULE__}: Unknown get startegy: #{inspect(unknown)}")
+ Logger.error("#{__MODULE__}: Unknown get strategy: #{inspect(unknown)}")
conn
|> send_resp(:internal_server_error, dgettext("errors", "Internal Error"))
diff --git a/lib/pleroma/web/plugs/user_enabled_plug.ex b/lib/pleroma/web/plugs/user_enabled_plug.ex
index ca10416..ca10416 100755..100644
--- a/lib/pleroma/web/plugs/user_enabled_plug.ex
+++ b/lib/pleroma/web/plugs/user_enabled_plug.ex
diff --git a/lib/pleroma/web/plugs/user_fetcher_plug.ex b/lib/pleroma/web/plugs/user_fetcher_plug.ex
index 87bc273..87bc273 100755..100644
--- a/lib/pleroma/web/plugs/user_fetcher_plug.ex
+++ b/lib/pleroma/web/plugs/user_fetcher_plug.ex
diff --git a/lib/pleroma/web/plugs/user_is_admin_plug.ex b/lib/pleroma/web/plugs/user_is_admin_plug.ex
index 548eb9b..548eb9b 100755..100644
--- a/lib/pleroma/web/plugs/user_is_admin_plug.ex
+++ b/lib/pleroma/web/plugs/user_is_admin_plug.ex
diff --git a/lib/pleroma/web/plugs/user_is_staff_plug.ex b/lib/pleroma/web/plugs/user_is_staff_plug.ex
index 951e146..951e146 100755..100644
--- a/lib/pleroma/web/plugs/user_is_staff_plug.ex
+++ b/lib/pleroma/web/plugs/user_is_staff_plug.ex
diff --git a/lib/pleroma/web/plugs/user_tracking_plug.ex b/lib/pleroma/web/plugs/user_tracking_plug.ex
index 9b52fd5..9b52fd5 100755..100644
--- a/lib/pleroma/web/plugs/user_tracking_plug.ex
+++ b/lib/pleroma/web/plugs/user_tracking_plug.ex
diff --git a/lib/pleroma/web/preload.ex b/lib/pleroma/web/preload.ex
index 4485383..6a4a888 100755..100644
--- a/lib/pleroma/web/preload.ex
+++ b/lib/pleroma/web/preload.ex
@@ -11,7 +11,7 @@ defmodule Pleroma.Web.Preload do
terms =
params
|> parser.generate_terms()
- |> Enum.map(fn {k, v} -> {k, Base.encode64(Jason.encode!(v))} end)
+ |> Enum.map(fn {k, v} -> {k, Base.encode64(Jason.encode!(v, escape: :html_safe))} end)
|> Enum.into(%{})
Map.merge(acc, terms)
@@ -19,7 +19,7 @@ defmodule Pleroma.Web.Preload do
rendered_html =
preload_data
- |> Jason.encode!()
+ |> Jason.encode!(escape: :html_safe)
|> build_script_tag()
|> HTML.safe_to_string()
diff --git a/lib/pleroma/web/preload/providers/instance.ex b/lib/pleroma/web/preload/providers/instance.ex
index 6183f7b..6183f7b 100755..100644
--- a/lib/pleroma/web/preload/providers/instance.ex
+++ b/lib/pleroma/web/preload/providers/instance.ex
diff --git a/lib/pleroma/web/preload/providers/provider.ex b/lib/pleroma/web/preload/providers/provider.ex
index 85e2bad..85e2bad 100755..100644
--- a/lib/pleroma/web/preload/providers/provider.ex
+++ b/lib/pleroma/web/preload/providers/provider.ex
diff --git a/lib/pleroma/web/preload/providers/timelines.ex b/lib/pleroma/web/preload/providers/timelines.ex
index 1031f48..1031f48 100755..100644
--- a/lib/pleroma/web/preload/providers/timelines.ex
+++ b/lib/pleroma/web/preload/providers/timelines.ex
diff --git a/lib/pleroma/web/preload/providers/user.ex b/lib/pleroma/web/preload/providers/user.ex
index 74550cd..74550cd 100755..100644
--- a/lib/pleroma/web/preload/providers/user.ex
+++ b/lib/pleroma/web/preload/providers/user.ex
diff --git a/lib/pleroma/web/push.ex b/lib/pleroma/web/push.ex
index 9665b0b..0d43f40 100755..100644
--- a/lib/pleroma/web/push.ex
+++ b/lib/pleroma/web/push.ex
@@ -9,7 +9,7 @@ defmodule Pleroma.Web.Push do
def init do
unless enabled() do
- Logger.warn("""
+ Logger.warning("""
VAPID key pair is not found. If you wish to enabled web push, please run
mix web_push.gen.keypair
diff --git a/lib/pleroma/web/push/impl.ex b/lib/pleroma/web/push/impl.ex
index 3c5f007..36f44d8 100755..100644
--- a/lib/pleroma/web/push/impl.ex
+++ b/lib/pleroma/web/push/impl.ex
@@ -57,7 +57,7 @@ defmodule Pleroma.Web.Push.Impl do
end
def perform(_) do
- Logger.warn("Unknown notification type")
+ Logger.warning("Unknown notification type")
{:error, :unknown_type}
end
diff --git a/lib/pleroma/web/push/subscription.ex b/lib/pleroma/web/push/subscription.ex
index 6fc45bd..6fc45bd 100755..100644
--- a/lib/pleroma/web/push/subscription.ex
+++ b/lib/pleroma/web/push/subscription.ex
diff --git a/lib/pleroma/web/rel_me.ex b/lib/pleroma/web/rel_me.ex
index ceb6a05..ceb6a05 100755..100644
--- a/lib/pleroma/web/rel_me.ex
+++ b/lib/pleroma/web/rel_me.ex
diff --git a/lib/pleroma/web/rich_media/backfill.ex b/lib/pleroma/web/rich_media/backfill.ex
new file mode 100644
index 0000000..4ec50e1
--- /dev/null
+++ b/lib/pleroma/web/rich_media/backfill.ex
@@ -0,0 +1,101 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.RichMedia.Backfill do
+ alias Pleroma.Web.RichMedia.Card
+ alias Pleroma.Web.RichMedia.Parser
+ alias Pleroma.Web.RichMedia.Parser.TTL
+ alias Pleroma.Workers.RichMediaExpirationWorker
+
+ require Logger
+
+ @backfiller Pleroma.Config.get([__MODULE__, :provider], Pleroma.Web.RichMedia.Backfill.Task)
+ @cachex Pleroma.Config.get([:cachex, :provider], Cachex)
+ @max_attempts 3
+ @retry 5_000
+
+ def start(%{url: url} = args) when is_binary(url) do
+ url_hash = Card.url_to_hash(url)
+
+ args =
+ args
+ |> Map.put(:attempt, 1)
+ |> Map.put(:url_hash, url_hash)
+
+ @backfiller.run(args)
+ end
+
+ def run(%{url: url, url_hash: url_hash, attempt: attempt} = args)
+ when attempt <= @max_attempts do
+ case Parser.parse(url) do
+ {:ok, fields} ->
+ {:ok, card} = Card.create(url, fields)
+
+ maybe_schedule_expiration(url, fields)
+
+ if Map.has_key?(args, :activity_id) do
+ stream_update(args)
+ end
+
+ warm_cache(url_hash, card)
+
+ {:error, {:invalid_metadata, fields}} ->
+ Logger.debug("Rich media incomplete or invalid metadata for #{url}: #{inspect(fields)}")
+ negative_cache(url_hash)
+
+ {:error, :body_too_large} ->
+ Logger.error("Rich media error for #{url}: :body_too_large")
+ negative_cache(url_hash)
+
+ {:error, {:content_type, type}} ->
+ Logger.debug("Rich media error for #{url}: :content_type is #{type}")
+ negative_cache(url_hash)
+
+ e ->
+ Logger.debug("Rich media error for #{url}: #{inspect(e)}")
+
+ :timer.sleep(@retry * attempt)
+
+ run(%{args | attempt: attempt + 1})
+ end
+ end
+
+ def run(%{url: url, url_hash: url_hash}) do
+ Logger.debug("Rich media failure for #{url}")
+
+ negative_cache(url_hash, :timer.minutes(15))
+ end
+
+ defp maybe_schedule_expiration(url, fields) do
+ case TTL.process(fields, url) do
+ {:ok, ttl} when is_number(ttl) ->
+ timestamp = DateTime.from_unix!(ttl)
+
+ RichMediaExpirationWorker.new(%{"url" => url}, scheduled_at: timestamp)
+ |> Oban.insert()
+
+ _ ->
+ :ok
+ end
+ end
+
+ defp stream_update(%{activity_id: activity_id}) do
+ Pleroma.Activity.get_by_id(activity_id)
+ |> Pleroma.Activity.normalize()
+ |> Pleroma.Web.ActivityPub.ActivityPub.stream_out()
+ end
+
+ defp warm_cache(key, val), do: @cachex.put(:rich_media_cache, key, val)
+ defp negative_cache(key, ttl \\ nil), do: @cachex.put(:rich_media_cache, key, nil, ttl: ttl)
+end
+
+defmodule Pleroma.Web.RichMedia.Backfill.Task do
+ alias Pleroma.Web.RichMedia.Backfill
+
+ def run(args) do
+ Task.Supervisor.start_child(Pleroma.TaskSupervisor, Backfill, :run, [args],
+ name: {:global, {:rich_media, args.url_hash}}
+ )
+ end
+end
diff --git a/lib/pleroma/web/rich_media/card.ex b/lib/pleroma/web/rich_media/card.ex
new file mode 100644
index 0000000..36a1ae4
--- /dev/null
+++ b/lib/pleroma/web/rich_media/card.ex
@@ -0,0 +1,157 @@
+defmodule Pleroma.Web.RichMedia.Card do
+ use Ecto.Schema
+ import Ecto.Changeset
+ import Ecto.Query
+
+ alias Pleroma.Activity
+ alias Pleroma.HTML
+ alias Pleroma.Object
+ alias Pleroma.Repo
+ alias Pleroma.Web.RichMedia.Backfill
+ alias Pleroma.Web.RichMedia.Parser
+
+ @cachex Pleroma.Config.get([:cachex, :provider], Cachex)
+ @config_impl Application.compile_env(:pleroma, [__MODULE__, :config_impl], Pleroma.Config)
+
+ @type t :: %__MODULE__{}
+
+ schema "rich_media_card" do
+ field(:url_hash, :binary)
+ field(:fields, :map)
+
+ timestamps()
+ end
+
+ @doc false
+ def changeset(card, attrs) do
+ card
+ |> cast(attrs, [:url_hash, :fields])
+ |> validate_required([:url_hash, :fields])
+ |> unique_constraint(:url_hash)
+ end
+
+ @spec create(String.t(), map()) :: {:ok, t()}
+ def create(url, fields) do
+ url_hash = url_to_hash(url)
+
+ fields = Map.put_new(fields, "url", url)
+
+ %__MODULE__{}
+ |> changeset(%{url_hash: url_hash, fields: fields})
+ |> Repo.insert(on_conflict: {:replace, [:fields]}, conflict_target: :url_hash)
+ end
+
+ @spec delete(String.t()) :: {:ok, Ecto.Schema.t()} | {:error, Ecto.Changeset.t()} | :ok
+ def delete(url) do
+ url_hash = url_to_hash(url)
+ @cachex.del(:rich_media_cache, url_hash)
+
+ case get_by_url(url) do
+ %__MODULE__{} = card -> Repo.delete(card)
+ nil -> :ok
+ end
+ end
+
+ @spec get_by_url(String.t() | nil) :: t() | nil | :error
+ def get_by_url(url) when is_binary(url) do
+ if @config_impl.get([:rich_media, :enabled]) do
+ url_hash = url_to_hash(url)
+
+ @cachex.fetch!(:rich_media_cache, url_hash, fn _ ->
+ result =
+ __MODULE__
+ |> where(url_hash: ^url_hash)
+ |> Repo.one()
+
+ case result do
+ %__MODULE__{} = card -> {:commit, card}
+ _ -> {:ignore, nil}
+ end
+ end)
+ else
+ :error
+ end
+ end
+
+ def get_by_url(nil), do: nil
+
+ @spec get_or_backfill_by_url(String.t(), map()) :: t() | nil
+ def get_or_backfill_by_url(url, backfill_opts \\ %{}) do
+ case get_by_url(url) do
+ %__MODULE__{} = card ->
+ card
+
+ nil ->
+ backfill_opts = Map.put(backfill_opts, :url, url)
+
+ Backfill.start(backfill_opts)
+
+ nil
+
+ :error ->
+ nil
+ end
+ end
+
+ @spec get_by_object(Object.t()) :: t() | nil | :error
+ def get_by_object(object) do
+ case HTML.extract_first_external_url_from_object(object) do
+ nil -> nil
+ url -> get_or_backfill_by_url(url)
+ end
+ end
+
+ @spec get_by_activity(Activity.t()) :: t() | nil | :error
+ # Fake/Draft activity
+ def get_by_activity(%Activity{id: "pleroma:fakeid"} = activity) do
+ with %Object{} = object <- Object.normalize(activity, fetch: false),
+ url when not is_nil(url) <- HTML.extract_first_external_url_from_object(object) do
+ case get_by_url(url) do
+ # Cache hit
+ %__MODULE__{} = card ->
+ card
+
+ # Cache miss, but fetch for rendering the Draft
+ _ ->
+ with {:ok, fields} <- Parser.parse(url),
+ {:ok, card} <- create(url, fields) do
+ card
+ else
+ _ -> nil
+ end
+ end
+ else
+ _ ->
+ nil
+ end
+ end
+
+ def get_by_activity(activity) do
+ with %Object{} = object <- Object.normalize(activity, fetch: false),
+ {_, nil} <- {:cached, get_cached_url(object, activity.id)} do
+ nil
+ else
+ {:cached, url} ->
+ get_or_backfill_by_url(url, %{activity_id: activity.id})
+
+ _ ->
+ :error
+ end
+ end
+
+ @spec url_to_hash(String.t()) :: String.t()
+ def url_to_hash(url) do
+ :crypto.hash(:sha256, url) |> Base.encode16(case: :lower)
+ end
+
+ defp get_cached_url(object, activity_id) do
+ key = "URL|#{activity_id}"
+
+ @cachex.fetch!(:scrubber_cache, key, fn _ ->
+ url = HTML.extract_first_external_url_from_object(object)
+ Activity.HTML.add_cache_key_for(activity_id, key)
+
+ {:commit, url}
+ end)
+ end
+end
diff --git a/lib/pleroma/web/rich_media/helpers.ex b/lib/pleroma/web/rich_media/helpers.ex
index 0488df3..1199944 100755..100644
--- a/lib/pleroma/web/rich_media/helpers.ex
+++ b/lib/pleroma/web/rich_media/helpers.ex
@@ -3,86 +3,13 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.RichMedia.Helpers do
- alias Pleroma.Activity
alias Pleroma.Config
- alias Pleroma.HTML
- alias Pleroma.Object
- alias Pleroma.Web.RichMedia.Parser
-
- @options [
- pool: :media,
- max_body: 2_000_000,
- recv_timeout: 2_000
- ]
-
- @spec validate_page_url(URI.t() | binary()) :: :ok | :error
- defp validate_page_url(page_url) when is_binary(page_url) do
- validate_tld = Config.get([Pleroma.Formatter, :validate_tld])
-
- page_url
- |> Linkify.Parser.url?(validate_tld: validate_tld)
- |> parse_uri(page_url)
- end
-
- defp validate_page_url(%URI{host: host, scheme: "https", authority: authority})
- when is_binary(authority) do
- cond do
- host in Config.get([:rich_media, :ignore_hosts], []) ->
- :error
-
- get_tld(host) in Config.get([:rich_media, :ignore_tld], []) ->
- :error
-
- true ->
- :ok
- end
- end
-
- defp validate_page_url(_), do: :error
-
- defp parse_uri(true, url) do
- url
- |> URI.parse()
- |> validate_page_url
- end
-
- defp parse_uri(_, _), do: :error
-
- defp get_tld(host) do
- host
- |> String.split(".")
- |> Enum.reverse()
- |> hd
- end
-
- def fetch_data_for_object(object) do
- with true <- Config.get([:rich_media, :enabled]),
- {:ok, page_url} <-
- HTML.extract_first_external_url_from_object(object),
- :ok <- validate_page_url(page_url),
- {:ok, rich_media} <- Parser.parse(page_url) do
- %{page_url: page_url, rich_media: rich_media}
- else
- _ -> %{}
- end
- end
-
- def fetch_data_for_activity(%Activity{data: %{"type" => "Create"}} = activity) do
- with true <- Config.get([:rich_media, :enabled]),
- %Object{} = object <- Object.normalize(activity, fetch: false) do
- fetch_data_for_object(object)
- else
- _ -> %{}
- end
- end
-
- def fetch_data_for_activity(_), do: %{}
def rich_media_get(url) do
headers = [{"user-agent", Pleroma.Application.user_agent() <> "; Bot"}]
head_check =
- case Pleroma.HTTP.head(url, headers, @options) do
+ case Pleroma.HTTP.head(url, headers, http_options()) do
# If the HEAD request didn't reach the server for whatever reason,
# we assume the GET that comes right after won't either
{:error, _} = e ->
@@ -97,7 +24,7 @@ defmodule Pleroma.Web.RichMedia.Helpers do
:ok
end
- with :ok <- head_check, do: Pleroma.HTTP.get(url, headers, @options)
+ with :ok <- head_check, do: Pleroma.HTTP.get(url, headers, http_options())
end
defp check_content_type(headers) do
@@ -113,12 +40,13 @@ defmodule Pleroma.Web.RichMedia.Helpers do
end
end
- @max_body @options[:max_body]
defp check_content_length(headers) do
+ max_body = Keyword.get(http_options(), :max_body)
+
case List.keyfind(headers, "content-length", 0) do
{_, maybe_content_length} ->
case Integer.parse(maybe_content_length) do
- {content_length, ""} when content_length <= @max_body -> :ok
+ {content_length, ""} when content_length <= max_body -> :ok
{_, ""} -> {:error, :body_too_large}
_ -> :ok
end
@@ -127,4 +55,11 @@ defmodule Pleroma.Web.RichMedia.Helpers do
:ok
end
end
+
+ defp http_options do
+ [
+ pool: :media,
+ max_body: Config.get([:rich_media, :max_body], 5_000_000)
+ ]
+ end
end
diff --git a/lib/pleroma/web/rich_media/parser.ex b/lib/pleroma/web/rich_media/parser.ex
index dbe81ea..37cf290 100755..100644
--- a/lib/pleroma/web/rich_media/parser.ex
+++ b/lib/pleroma/web/rich_media/parser.ex
@@ -5,137 +5,28 @@
defmodule Pleroma.Web.RichMedia.Parser do
require Logger
- @cachex Pleroma.Config.get([:cachex, :provider], Cachex)
+ @config_impl Application.compile_env(:pleroma, [__MODULE__, :config_impl], Pleroma.Config)
defp parsers do
Pleroma.Config.get([:rich_media, :parsers])
end
- def parse(nil), do: {:error, "No URL provided"}
-
- if Pleroma.Config.get(:env) == :test do
- @spec parse(String.t()) :: {:ok, map()} | {:error, any()}
- def parse(url), do: parse_url(url)
- else
- @spec parse(String.t()) :: {:ok, map()} | {:error, any()}
- def parse(url) do
- with {:ok, data} <- get_cached_or_parse(url),
- {:ok, _} <- set_ttl_based_on_image(data, url) do
- {:ok, data}
- end
- end
-
- defp get_cached_or_parse(url) do
- case @cachex.fetch(:rich_media_cache, url, fn ->
- case parse_url(url) do
- {:ok, _} = res ->
- {:commit, res}
-
- {:error, reason} = e ->
- # Unfortunately we have to log errors here, instead of doing that
- # along with ttl setting at the bottom. Otherwise we can get log spam
- # if more than one process was waiting for the rich media card
- # while it was generated. Ideally we would set ttl here as well,
- # so we don't override it number_of_waiters_on_generation
- # times, but one, obviously, can't set ttl for not-yet-created entry
- # and Cachex doesn't support returning ttl from the fetch callback.
- log_error(url, reason)
- {:commit, e}
- end
- end) do
- {action, res} when action in [:commit, :ok] ->
- case res do
- {:ok, _data} = res ->
- res
-
- {:error, reason} = e ->
- if action == :commit, do: set_error_ttl(url, reason)
- e
- end
-
- {:error, e} ->
- {:error, {:cachex_error, e}}
- end
- end
-
- defp set_error_ttl(_url, :body_too_large), do: :ok
- defp set_error_ttl(_url, {:content_type, _}), do: :ok
-
- # The TTL is not set for the errors above, since they are unlikely to change
- # with time
-
- defp set_error_ttl(url, _reason) do
- ttl = Pleroma.Config.get([:rich_media, :failure_backoff], 60_000)
- @cachex.expire(:rich_media_cache, url, ttl)
- :ok
- end
-
- defp log_error(url, {:invalid_metadata, data}) do
- Logger.debug(fn -> "Incomplete or invalid metadata for #{url}: #{inspect(data)}" end)
- end
-
- defp log_error(url, reason) do
- Logger.warn(fn -> "Rich media error for #{url}: #{inspect(reason)}" end)
- end
- end
-
- @doc """
- Set the rich media cache based on the expiration time of image.
-
- Adopt behaviour `Pleroma.Web.RichMedia.Parser.TTL`
-
- ## Example
-
- defmodule MyModule do
- @behaviour Pleroma.Web.RichMedia.Parser.TTL
- def ttl(data, url) do
- image_url = Map.get(data, :image)
- # do some parsing in the url and get the ttl of the image
- # and return ttl is unix time
- parse_ttl_from_url(image_url)
- end
- end
+ def parse(nil), do: nil
- Define the module in the config
-
- config :pleroma, :rich_media,
- ttl_setters: [MyModule]
- """
- @spec set_ttl_based_on_image(map(), String.t()) ::
- {:ok, Integer.t() | :noop} | {:error, :no_key}
- def set_ttl_based_on_image(data, url) do
- case get_ttl_from_image(data, url) do
- {:ok, ttl} when is_number(ttl) ->
- ttl = ttl * 1000
-
- case @cachex.expire_at(:rich_media_cache, url, ttl) do
- {:ok, true} -> {:ok, ttl}
- {:ok, false} -> {:error, :no_key}
- end
-
- _ ->
- {:ok, :noop}
+ @spec parse(String.t()) :: {:ok, map()} | {:error, any()}
+ def parse(url) do
+ with :ok <- validate_page_url(url),
+ {:ok, data} <- parse_url(url) do
+ data = Map.put(data, "url", url)
+ {:ok, data}
end
end
- defp get_ttl_from_image(data, url) do
- [:rich_media, :ttl_setters]
- |> Pleroma.Config.get()
- |> Enum.reduce({:ok, nil}, fn
- module, {:ok, _ttl} ->
- module.ttl(data, url)
-
- _, error ->
- error
- end)
- end
-
- def parse_url(url) do
+ defp parse_url(url) do
with {:ok, %Tesla.Env{body: html}} <- Pleroma.Web.RichMedia.Helpers.rich_media_get(url),
{:ok, html} <- Floki.parse_document(html) do
html
|> maybe_parse()
- |> Map.put("url", url)
|> clean_parsed_data()
|> check_parsed_data()
end
@@ -166,4 +57,46 @@ defmodule Pleroma.Web.RichMedia.Parser do
end)
|> Map.new()
end
+
+ @spec validate_page_url(URI.t() | binary()) :: :ok | :error
+ defp validate_page_url(page_url) when is_binary(page_url) do
+ validate_tld = @config_impl.get([Pleroma.Formatter, :validate_tld])
+
+ page_url
+ |> Linkify.Parser.url?(validate_tld: validate_tld)
+ |> parse_uri(page_url)
+ end
+
+ defp validate_page_url(%URI{host: host, scheme: "https"}) do
+ cond do
+ Linkify.Parser.ip?(host) ->
+ :error
+
+ host in @config_impl.get([:rich_media, :ignore_hosts], []) ->
+ :error
+
+ get_tld(host) in @config_impl.get([:rich_media, :ignore_tld], []) ->
+ :error
+
+ true ->
+ :ok
+ end
+ end
+
+ defp validate_page_url(_), do: :error
+
+ defp parse_uri(true, url) do
+ url
+ |> URI.parse()
+ |> validate_page_url
+ end
+
+ defp parse_uri(_, _), do: :error
+
+ defp get_tld(host) do
+ host
+ |> String.split(".")
+ |> Enum.reverse()
+ |> hd
+ end
end
diff --git a/lib/pleroma/web/rich_media/parser/ttl.ex b/lib/pleroma/web/rich_media/parser/ttl.ex
index 59d7f87..7e56375 100755..100644
--- a/lib/pleroma/web/rich_media/parser/ttl.ex
+++ b/lib/pleroma/web/rich_media/parser/ttl.ex
@@ -3,5 +3,18 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.RichMedia.Parser.TTL do
- @callback ttl(Map.t(), String.t()) :: Integer.t() | nil
+ @callback ttl(map(), String.t()) :: integer() | nil
+
+ @spec process(map(), String.t()) :: {:ok, integer() | nil}
+ def process(data, url) do
+ [:rich_media, :ttl_setters]
+ |> Pleroma.Config.get()
+ |> Enum.reduce_while({:ok, nil}, fn
+ module, acc ->
+ case module.ttl(data, url) do
+ ttl when is_number(ttl) -> {:halt, {:ok, ttl}}
+ _ -> {:cont, acc}
+ end
+ end)
+ end
end
diff --git a/lib/pleroma/web/rich_media/parser/ttl/aws_signed_url.ex b/lib/pleroma/web/rich_media/parser/ttl/aws_signed_url.ex
index fa41c16..948c727 100755..100644
--- a/lib/pleroma/web/rich_media/parser/ttl/aws_signed_url.ex
+++ b/lib/pleroma/web/rich_media/parser/ttl/aws_signed_url.ex
@@ -7,25 +7,26 @@ defmodule Pleroma.Web.RichMedia.Parser.TTL.AwsSignedUrl do
@impl true
def ttl(data, _url) do
- image = Map.get(data, :image)
+ image = Map.get(data, "image")
- if is_aws_signed_url(image) do
+ if aws_signed_url?(image) do
image
|> parse_query_params()
|> format_query_params()
|> get_expiration_timestamp()
else
- {:error, "Not aws signed url #{inspect(image)}"}
+ nil
end
end
- defp is_aws_signed_url(image) when is_binary(image) and image != "" do
+ defp aws_signed_url?(image) when is_binary(image) and image != "" do
%URI{host: host, query: query} = URI.parse(image)
- String.contains?(host, "amazonaws.com") and String.contains?(query, "X-Amz-Expires")
+ is_binary(host) and String.contains?(host, "amazonaws.com") and
+ String.contains?(query, "X-Amz-Expires")
end
- defp is_aws_signed_url(_), do: nil
+ defp aws_signed_url?(_), do: nil
defp parse_query_params(image) do
%URI{query: query} = URI.parse(image)
@@ -45,6 +46,6 @@ defmodule Pleroma.Web.RichMedia.Parser.TTL.AwsSignedUrl do
|> Map.get("X-Amz-Date")
|> Timex.parse("{ISO:Basic:Z}")
- {:ok, Timex.to_unix(date) + String.to_integer(Map.get(params, "X-Amz-Expires"))}
+ Timex.to_unix(date) + String.to_integer(Map.get(params, "X-Amz-Expires"))
end
end
diff --git a/lib/pleroma/web/rich_media/parser/ttl/opengraph.ex b/lib/pleroma/web/rich_media/parser/ttl/opengraph.ex
new file mode 100644
index 0000000..b068896
--- /dev/null
+++ b/lib/pleroma/web/rich_media/parser/ttl/opengraph.ex
@@ -0,0 +1,20 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.RichMedia.Parser.TTL.Opengraph do
+ @behaviour Pleroma.Web.RichMedia.Parser.TTL
+
+ @impl true
+ def ttl(%{"ttl" => ttl_string}, _url) when is_binary(ttl_string) do
+ try do
+ ttl = String.to_integer(ttl_string)
+ now = DateTime.utc_now() |> DateTime.to_unix()
+ now + ttl
+ rescue
+ _ -> nil
+ end
+ end
+
+ def ttl(_, _), do: nil
+end
diff --git a/lib/pleroma/web/rich_media/parsers/meta_tags_parser.ex b/lib/pleroma/web/rich_media/parsers/meta_tags_parser.ex
index 320a5f5..320a5f5 100755..100644
--- a/lib/pleroma/web/rich_media/parsers/meta_tags_parser.ex
+++ b/lib/pleroma/web/rich_media/parsers/meta_tags_parser.ex
diff --git a/lib/pleroma/web/rich_media/parsers/o_embed.ex b/lib/pleroma/web/rich_media/parsers/o_embed.ex
index 0f30317..0f30317 100755..100644
--- a/lib/pleroma/web/rich_media/parsers/o_embed.ex
+++ b/lib/pleroma/web/rich_media/parsers/o_embed.ex
diff --git a/lib/pleroma/web/rich_media/parsers/ogp.ex b/lib/pleroma/web/rich_media/parsers/ogp.ex
index b7f2b42..b7f2b42 100755..100644
--- a/lib/pleroma/web/rich_media/parsers/ogp.ex
+++ b/lib/pleroma/web/rich_media/parsers/ogp.ex
diff --git a/lib/pleroma/web/rich_media/parsers/twitter_card.ex b/lib/pleroma/web/rich_media/parsers/twitter_card.ex
index cc65372..cc65372 100755..100644
--- a/lib/pleroma/web/rich_media/parsers/twitter_card.ex
+++ b/lib/pleroma/web/rich_media/parsers/twitter_card.ex
diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex
index 8a6072f..86d6da8 100755..100644
--- a/lib/pleroma/web/router.ex
+++ b/lib/pleroma/web/router.ex
@@ -182,7 +182,7 @@ defmodule Pleroma.Web.Router do
end
pipeline :well_known do
- plug(:accepts, ["json", "jrd+json", "xml", "xrd+xml"])
+ plug(:accepts, ["json", "jrd", "jrd+json", "xml", "xrd+xml"])
end
pipeline :config do
@@ -224,11 +224,209 @@ defmodule Pleroma.Web.Router do
post("/remote_interaction", UtilController, :remote_interaction)
end
+ scope "/api/v1/pleroma", Pleroma.Web.PleromaAPI do
+ pipe_through(:pleroma_api)
+
+ get("/federation_status", InstancesController, :show)
+ end
+
scope "/api/v1/pleroma", Pleroma.Web do
pipe_through(:pleroma_api)
post("/uploader_callback/:upload_path", UploaderController, :callback)
end
+ # AdminAPI: only admins can perform these actions
+ scope "/api/v1/pleroma/admin", Pleroma.Web.AdminAPI do
+ pipe_through([:admin_api, :require_admin])
+
+ get("/users/:nickname/permission_group", AdminAPIController, :right_get)
+ get("/users/:nickname/permission_group/:permission_group", AdminAPIController, :right_get)
+
+ post("/users/:nickname/permission_group/:permission_group", AdminAPIController, :right_add)
+
+ delete(
+ "/users/:nickname/permission_group/:permission_group",
+ AdminAPIController,
+ :right_delete
+ )
+
+ post("/users/permission_group/:permission_group", AdminAPIController, :right_add_multiple)
+
+ delete(
+ "/users/permission_group/:permission_group",
+ AdminAPIController,
+ :right_delete_multiple
+ )
+
+ post("/users/follow", UserController, :follow)
+ post("/users/unfollow", UserController, :unfollow)
+ post("/users", UserController, :create)
+
+ patch("/users/suggest", UserController, :suggest)
+ patch("/users/unsuggest", UserController, :unsuggest)
+
+ get("/relay", RelayController, :index)
+ post("/relay", RelayController, :follow)
+ delete("/relay", RelayController, :unfollow)
+
+ get("/instance_document/:name", InstanceDocumentController, :show)
+ patch("/instance_document/:name", InstanceDocumentController, :update)
+ delete("/instance_document/:name", InstanceDocumentController, :delete)
+
+ get("/config", ConfigController, :show)
+ post("/config", ConfigController, :update)
+ get("/config/descriptions", ConfigController, :descriptions)
+ get("/need_reboot", AdminAPIController, :need_reboot)
+ get("/restart", AdminAPIController, :restart)
+
+ get("/oauth_app", OAuthAppController, :index)
+ post("/oauth_app", OAuthAppController, :create)
+ patch("/oauth_app/:id", OAuthAppController, :update)
+ delete("/oauth_app/:id", OAuthAppController, :delete)
+
+ get("/media_proxy_caches", MediaProxyCacheController, :index)
+ post("/media_proxy_caches/delete", MediaProxyCacheController, :delete)
+ post("/media_proxy_caches/purge", MediaProxyCacheController, :purge)
+
+ get("/frontends", FrontendController, :index)
+ post("/frontends/install", FrontendController, :install)
+
+ post("/backups", AdminAPIController, :create_backup)
+ end
+
+ # AdminAPI: admins and mods (staff) can perform these actions (if privileged by role)
+ scope "/api/v1/pleroma/admin", Pleroma.Web.AdminAPI do
+ pipe_through(:require_privileged_role_announcements_manage_announcements)
+
+ get("/announcements", AnnouncementController, :index)
+ post("/announcements", AnnouncementController, :create)
+ get("/announcements/:id", AnnouncementController, :show)
+ patch("/announcements/:id", AnnouncementController, :change)
+ delete("/announcements/:id", AnnouncementController, :delete)
+ end
+
+ # AdminAPI: admins and mods (staff) can perform these actions (if privileged by role)
+ scope "/api/v1/pleroma/admin", Pleroma.Web.AdminAPI do
+ pipe_through(:require_privileged_role_users_delete)
+
+ delete("/users", UserController, :delete)
+ end
+
+ # AdminAPI: admins and mods (staff) can perform these actions (if privileged by role)
+ scope "/api/v1/pleroma/admin", Pleroma.Web.AdminAPI do
+ pipe_through(:require_privileged_role_users_manage_credentials)
+
+ get("/users/:nickname/password_reset", AdminAPIController, :get_password_reset)
+ get("/users/:nickname/credentials", AdminAPIController, :show_user_credentials)
+ patch("/users/:nickname/credentials", AdminAPIController, :update_user_credentials)
+ put("/users/disable_mfa", AdminAPIController, :disable_mfa)
+ patch("/users/force_password_reset", AdminAPIController, :force_password_reset)
+ patch("/users/confirm_email", AdminAPIController, :confirm_email)
+ patch("/users/resend_confirmation_email", AdminAPIController, :resend_confirmation_email)
+ end
+
+ # AdminAPI: admins and mods (staff) can perform these actions (if privileged by role)
+ scope "/api/v1/pleroma/admin", Pleroma.Web.AdminAPI do
+ pipe_through(:require_privileged_role_messages_read)
+
+ get("/users/:nickname/statuses", AdminAPIController, :list_user_statuses)
+ get("/users/:nickname/chats", AdminAPIController, :list_user_chats)
+
+ get("/statuses", StatusController, :index)
+
+ get("/chats/:id", ChatController, :show)
+ get("/chats/:id/messages", ChatController, :messages)
+
+ get("/instances/:instance/statuses", InstanceController, :list_statuses)
+
+ get("/statuses/:id", StatusController, :show)
+ end
+
+ # AdminAPI: admins and mods (staff) can perform these actions (if privileged by role)
+ scope "/api/v1/pleroma/admin", Pleroma.Web.AdminAPI do
+ pipe_through(:require_privileged_role_users_manage_tags)
+
+ put("/users/tag", AdminAPIController, :tag_users)
+ delete("/users/tag", AdminAPIController, :untag_users)
+ end
+
+ # AdminAPI: admins and mods (staff) can perform these actions (if privileged by role)
+ scope "/api/v1/pleroma/admin", Pleroma.Web.AdminAPI do
+ pipe_through(:require_privileged_role_users_manage_activation_state)
+
+ patch("/users/:nickname/toggle_activation", UserController, :toggle_activation)
+ patch("/users/activate", UserController, :activate)
+ patch("/users/deactivate", UserController, :deactivate)
+ end
+
+ # AdminAPI: admins and mods (staff) can perform these actions (if privileged by role)
+ scope "/api/v1/pleroma/admin", Pleroma.Web.AdminAPI do
+ pipe_through(:require_privileged_role_users_manage_invites)
+
+ patch("/users/approve", UserController, :approve)
+ post("/users/invite_token", InviteController, :create)
+ get("/users/invites", InviteController, :index)
+ post("/users/revoke_invite", InviteController, :revoke)
+ post("/users/email_invite", InviteController, :email)
+ end
+
+ # AdminAPI: admins and mods (staff) can perform these actions (if privileged by role)
+ scope "/api/v1/pleroma/admin", Pleroma.Web.AdminAPI do
+ pipe_through(:require_privileged_role_reports_manage_reports)
+
+ get("/reports", ReportController, :index)
+ get("/reports/:id", ReportController, :show)
+ patch("/reports", ReportController, :update)
+ post("/reports/:id/notes", ReportController, :notes_create)
+ delete("/reports/:report_id/notes/:id", ReportController, :notes_delete)
+ end
+
+ # AdminAPI: admins and mods (staff) can perform these actions (if privileged by role)
+ scope "/api/v1/pleroma/admin", Pleroma.Web.AdminAPI do
+ pipe_through(:require_privileged_role_users_read)
+
+ get("/users", UserController, :index)
+ get("/users/:nickname", UserController, :show)
+ end
+
+ # AdminAPI: admins and mods (staff) can perform these actions (if privileged by role)
+ scope "/api/v1/pleroma/admin", Pleroma.Web.AdminAPI do
+ pipe_through(:require_privileged_role_messages_delete)
+
+ put("/statuses/:id", StatusController, :update)
+ delete("/statuses/:id", StatusController, :delete)
+
+ delete("/chats/:id/messages/:message_id", ChatController, :delete_message)
+ end
+
+ # AdminAPI: admins and mods (staff) can perform these actions (if privileged by role)
+ scope "/api/v1/pleroma/admin", Pleroma.Web.AdminAPI do
+ pipe_through(:require_privileged_role_emoji_manage_emoji)
+
+ post("/reload_emoji", AdminAPIController, :reload_emoji)
+ end
+
+ # AdminAPI: admins and mods (staff) can perform these actions (if privileged by role)
+ scope "/api/v1/pleroma/admin", Pleroma.Web.AdminAPI do
+ pipe_through(:require_privileged_role_instances_delete)
+
+ delete("/instances/:instance", InstanceController, :delete)
+ end
+
+ # AdminAPI: admins and mods (staff) can perform these actions (if privileged by role)
+ scope "/api/v1/pleroma/admin", Pleroma.Web.AdminAPI do
+ pipe_through(:require_privileged_role_moderation_log_read)
+
+ get("/moderation_log", AdminAPIController, :list_log)
+ end
+
+ # AdminAPI: admins and mods (staff) can perform these actions (if privileged by role)
+ scope "/api/v1/pleroma/admin", Pleroma.Web.AdminAPI do
+ pipe_through(:require_privileged_role_statistics_read)
+
+ get("/stats", AdminAPIController, :stats)
+ end
+
scope "/api/v1/pleroma/emoji", Pleroma.Web.PleromaAPI do
scope "/pack" do
pipe_through(:require_privileged_role_emoji_manage_emoji)
@@ -273,6 +471,8 @@ defmodule Pleroma.Web.Router do
get("/main/ostatus", UtilController, :show_subscribe_form)
get("/ostatus_subscribe", RemoteFollowController, :follow)
post("/ostatus_subscribe", RemoteFollowController, :do_follow)
+
+ get("/authorize_interaction", RemoteFollowController, :authorize_interaction)
end
scope "/api/pleroma", Pleroma.Web.TwitterAPI do
@@ -281,7 +481,7 @@ defmodule Pleroma.Web.Router do
post("/change_email", UtilController, :change_email)
post("/change_password", UtilController, :change_password)
post("/delete_account", UtilController, :delete_account)
- put("/notification_settings", UtilController, :update_notificaton_settings)
+ put("/notification_settings", UtilController, :update_notification_settings)
post("/disable_account", UtilController, :disable_account)
post("/move_account", UtilController, :move_account)
@@ -380,12 +580,19 @@ defmodule Pleroma.Web.Router do
get("/backups", BackupController, :index)
post("/backups", BackupController, :create)
+
+ get("/bookmark_folders", BookmarkFolderController, :index)
+ post("/bookmark_folders", BookmarkFolderController, :create)
+ patch("/bookmark_folders/:id", BookmarkFolderController, :update)
+ delete("/bookmark_folders/:id", BookmarkFolderController, :delete)
end
scope [] do
pipe_through(:api)
get("/accounts/:id/favourites", AccountController, :favourites)
get("/accounts/:id/endorsements", AccountController, :endorsements)
+
+ get("/statuses/:id/quotes", StatusController, :quotes)
end
scope [] do
@@ -410,7 +617,6 @@ defmodule Pleroma.Web.Router do
scope "/api/v1/pleroma", Pleroma.Web.PleromaAPI do
pipe_through(:api)
get("/accounts/:id/scrobbles", ScrobbleController, :index)
- get("/federation_status", InstancesController, :show)
end
scope "/api/v2/pleroma", Pleroma.Web.PleromaAPI do
@@ -562,7 +768,6 @@ defmodule Pleroma.Web.Router do
get("/statuses", StatusController, :index)
get("/statuses/:id", StatusController, :show)
get("/statuses/:id/context", StatusController, :context)
- get("/statuses/:id/card", StatusController, :card)
get("/statuses/:id/favourited_by", StatusController, :favourited_by)
get("/statuses/:id/reblogged_by", StatusController, :reblogged_by)
get("/statuses/:id/history", StatusController, :show_history)
@@ -582,11 +787,14 @@ defmodule Pleroma.Web.Router do
scope "/api/v2", Pleroma.Web.MastodonAPI do
pipe_through(:api)
+
get("/search", SearchController, :search2)
post("/media", MediaController, :create2)
get("/suggestions", SuggestionController, :index2)
+
+ get("/instance", InstanceController, :show2)
end
scope "/api", Pleroma.Web do
@@ -804,16 +1012,15 @@ defmodule Pleroma.Web.Router do
scope "/", Pleroma.Web.Fallback do
get("/registration/:token", RedirectController, :registration_page)
get("/:maybe_nickname_or_id", RedirectController, :redirector_with_meta)
- match(:*, "/api/pleroma*path", LegacyPleromaApiRerouterPlug, [])
- get("/api*path", RedirectController, :api_not_implemented)
+ match(:*, "/api/pleroma/*path", LegacyPleromaApiRerouterPlug, [])
+ get("/api/*path", RedirectController, :api_not_implemented)
get("/*path", RedirectController, :redirector_with_preload)
options("/*path", RedirectController, :empty)
end
- # TODO: Change to Phoenix.Router.routes/1 for Phoenix 1.6.0+
def get_api_routes do
- __MODULE__.__routes__()
+ Phoenix.Router.routes(__MODULE__)
|> Enum.reject(fn r -> r.plug == Pleroma.Web.Fallback.RedirectController end)
|> Enum.map(fn r ->
r.path
diff --git a/lib/pleroma/web/router.ex~ b/lib/pleroma/web/router.ex~
deleted file mode 100755
index c1a690e..0000000
--- a/lib/pleroma/web/router.ex~
+++ /dev/null
@@ -1,1017 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.Router do
- use Pleroma.Web, :router
- import Phoenix.LiveDashboard.Router
-
- pipeline :accepts_html do
- plug(:accepts, ["html"])
- end
-
- pipeline :accepts_html_xml do
- plug(:accepts, ["html", "xml", "rss", "atom"])
- end
-
- pipeline :accepts_html_json do
- plug(:accepts, ["html", "activity+json", "json"])
- end
-
- pipeline :accepts_html_xml_json do
- plug(:accepts, ["html", "xml", "rss", "atom", "activity+json", "json"])
- end
-
- pipeline :accepts_xml_rss_atom do
- plug(:accepts, ["xml", "rss", "atom"])
- end
-
- pipeline :browser do
- plug(:accepts, ["html"])
- plug(:fetch_session)
- end
-
- pipeline :oauth do
- plug(:fetch_session)
- plug(Pleroma.Web.Plugs.OAuthPlug)
- plug(Pleroma.Web.Plugs.UserEnabledPlug)
- plug(Pleroma.Web.Plugs.EnsureUserTokenAssignsPlug)
- end
-
- # Note: expects _user_ authentication (user-unbound app-bound tokens don't qualify)
- pipeline :expect_user_authentication do
- plug(Pleroma.Web.Plugs.ExpectAuthenticatedCheckPlug)
- end
-
- # Note: expects public instance or _user_ authentication (user-unbound tokens don't qualify)
- pipeline :expect_public_instance_or_user_authentication do
- plug(Pleroma.Web.Plugs.ExpectPublicOrAuthenticatedCheckPlug)
- end
-
- pipeline :authenticate do
- plug(Pleroma.Web.Plugs.OAuthPlug)
- plug(Pleroma.Web.Plugs.BasicAuthDecoderPlug)
- plug(Pleroma.Web.Plugs.UserFetcherPlug)
- plug(Pleroma.Web.Plugs.AuthenticationPlug)
- end
-
- pipeline :after_auth do
- plug(Pleroma.Web.Plugs.UserEnabledPlug)
- plug(Pleroma.Web.Plugs.SetUserSessionIdPlug)
- plug(Pleroma.Web.Plugs.EnsureUserTokenAssignsPlug)
- plug(Pleroma.Web.Plugs.UserTrackingPlug)
- end
-
- pipeline :base_api do
- plug(:accepts, ["json"])
- plug(:fetch_session)
- plug(:authenticate)
- plug(OpenApiSpex.Plug.PutApiSpec, module: Pleroma.Web.ApiSpec)
- end
-
- pipeline :no_auth_or_privacy_expectations_api do
- plug(:base_api)
- plug(:after_auth)
- plug(Pleroma.Web.Plugs.IdempotencyPlug)
- end
-
- # Pipeline for app-related endpoints (no user auth checks — app-bound tokens must be supported)
- pipeline :app_api do
- plug(:no_auth_or_privacy_expectations_api)
- end
-
- pipeline :api do
- plug(:expect_public_instance_or_user_authentication)
- plug(:no_auth_or_privacy_expectations_api)
- end
-
- pipeline :authenticated_api do
- plug(:expect_user_authentication)
- plug(:no_auth_or_privacy_expectations_api)
- plug(Pleroma.Web.Plugs.EnsureAuthenticatedPlug)
- end
-
- pipeline :admin_api do
- plug(:expect_user_authentication)
- plug(:base_api)
- plug(Pleroma.Web.Plugs.AdminSecretAuthenticationPlug)
- plug(:after_auth)
- plug(Pleroma.Web.Plugs.EnsureAuthenticatedPlug)
- plug(Pleroma.Web.Plugs.UserIsStaffPlug)
- plug(Pleroma.Web.Plugs.IdempotencyPlug)
- end
-
- pipeline :require_admin do
- plug(Pleroma.Web.Plugs.UserIsAdminPlug)
- end
-
- pipeline :require_privileged_role_users_delete do
- plug(:admin_api)
- plug(Pleroma.Web.Plugs.EnsurePrivilegedPlug, :users_delete)
- end
-
- pipeline :require_privileged_role_users_manage_credentials do
- plug(:admin_api)
- plug(Pleroma.Web.Plugs.EnsurePrivilegedPlug, :users_manage_credentials)
- end
-
- pipeline :require_privileged_role_messages_read do
- plug(:admin_api)
- plug(Pleroma.Web.Plugs.EnsurePrivilegedPlug, :messages_read)
- end
-
- pipeline :require_privileged_role_users_manage_tags do
- plug(:admin_api)
- plug(Pleroma.Web.Plugs.EnsurePrivilegedPlug, :users_manage_tags)
- end
-
- pipeline :require_privileged_role_users_manage_activation_state do
- plug(:admin_api)
- plug(Pleroma.Web.Plugs.EnsurePrivilegedPlug, :users_manage_activation_state)
- end
-
- pipeline :require_privileged_role_users_manage_invites do
- plug(:admin_api)
- plug(Pleroma.Web.Plugs.EnsurePrivilegedPlug, :users_manage_invites)
- end
-
- pipeline :require_privileged_role_reports_manage_reports do
- plug(:admin_api)
- plug(Pleroma.Web.Plugs.EnsurePrivilegedPlug, :reports_manage_reports)
- end
-
- pipeline :require_privileged_role_users_read do
- plug(:admin_api)
- plug(Pleroma.Web.Plugs.EnsurePrivilegedPlug, :users_read)
- end
-
- pipeline :require_privileged_role_messages_delete do
- plug(:admin_api)
- plug(Pleroma.Web.Plugs.EnsurePrivilegedPlug, :messages_delete)
- end
-
- pipeline :require_privileged_role_emoji_manage_emoji do
- plug(:admin_api)
- plug(Pleroma.Web.Plugs.EnsurePrivilegedPlug, :emoji_manage_emoji)
- end
-
- pipeline :require_privileged_role_instances_delete do
- plug(:admin_api)
- plug(Pleroma.Web.Plugs.EnsurePrivilegedPlug, :instances_delete)
- end
-
- pipeline :require_privileged_role_moderation_log_read do
- plug(:admin_api)
- plug(Pleroma.Web.Plugs.EnsurePrivilegedPlug, :moderation_log_read)
- end
-
- pipeline :require_privileged_role_statistics_read do
- plug(:admin_api)
- plug(Pleroma.Web.Plugs.EnsurePrivilegedPlug, :statistics_read)
- end
-
- pipeline :require_privileged_role_announcements_manage_announcements do
- plug(:admin_api)
- plug(Pleroma.Web.Plugs.EnsurePrivilegedPlug, :announcements_manage_announcements)
- end
-
- pipeline :pleroma_html do
- plug(:browser)
- plug(:authenticate)
- plug(Pleroma.Web.Plugs.EnsureUserTokenAssignsPlug)
- end
-
- pipeline :well_known do
- plug(:accepts, ["json", "jrd+json", "xml", "xrd+xml"])
- end
-
- pipeline :config do
- plug(:accepts, ["json", "xml"])
- plug(OpenApiSpex.Plug.PutApiSpec, module: Pleroma.Web.ApiSpec)
- end
-
- pipeline :pleroma_api do
- plug(:accepts, ["html", "json"])
- plug(OpenApiSpex.Plug.PutApiSpec, module: Pleroma.Web.ApiSpec)
- end
-
- pipeline :mailbox_preview do
- plug(:accepts, ["html"])
-
- plug(:put_secure_browser_headers, %{
- "content-security-policy" =>
- "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline' 'unsafe-eval'"
- })
- end
-
- pipeline :http_signature do
- plug(Pleroma.Web.Plugs.HTTPSignaturePlug)
- plug(Pleroma.Web.Plugs.MappedSignatureToIdentityPlug)
- end
-
- pipeline :static_fe do
- plug(Pleroma.Web.Plugs.StaticFEPlug)
- end
-
- scope "/api/v1/pleroma", Pleroma.Web.TwitterAPI do
- pipe_through(:pleroma_api)
-
- get("/password_reset/:token", PasswordController, :reset, as: :reset_password)
- post("/password_reset", PasswordController, :do_reset, as: :reset_password)
- get("/emoji", UtilController, :emoji)
- get("/captcha", UtilController, :captcha)
- get("/healthcheck", UtilController, :healthcheck)
- post("/remote_interaction", UtilController, :remote_interaction)
- end
-
- scope "/api/v1/pleroma", Pleroma.Web do
- pipe_through(:pleroma_api)
- post("/uploader_callback/:upload_path", UploaderController, :callback)
- end
-
- # AdminAPI: only admins can perform these actions
- scope "/api/v1/pleroma/admin", Pleroma.Web.AdminAPI do
- pipe_through([:admin_api, :require_admin])
-
- get("/users/:nickname/permission_group", AdminAPIController, :right_get)
- get("/users/:nickname/permission_group/:permission_group", AdminAPIController, :right_get)
-
- post("/users/:nickname/permission_group/:permission_group", AdminAPIController, :right_add)
-
- delete(
- "/users/:nickname/permission_group/:permission_group",
- AdminAPIController,
- :right_delete
- )
-
- post("/users/permission_group/:permission_group", AdminAPIController, :right_add_multiple)
-
- delete(
- "/users/permission_group/:permission_group",
- AdminAPIController,
- :right_delete_multiple
- )
-
- post("/users/follow", UserController, :follow)
- post("/users/unfollow", UserController, :unfollow)
- post("/users", UserController, :create)
-
- patch("/users/suggest", UserController, :suggest)
- patch("/users/unsuggest", UserController, :unsuggest)
-
- get("/relay", RelayController, :index)
- post("/relay", RelayController, :follow)
- delete("/relay", RelayController, :unfollow)
-
- get("/instance_document/:name", InstanceDocumentController, :show)
- patch("/instance_document/:name", InstanceDocumentController, :update)
- delete("/instance_document/:name", InstanceDocumentController, :delete)
-
- get("/config", ConfigController, :show)
- post("/config", ConfigController, :update)
- get("/config/descriptions", ConfigController, :descriptions)
- get("/need_reboot", AdminAPIController, :need_reboot)
- get("/restart", AdminAPIController, :restart)
-
- get("/oauth_app", OAuthAppController, :index)
- post("/oauth_app", OAuthAppController, :create)
- patch("/oauth_app/:id", OAuthAppController, :update)
- delete("/oauth_app/:id", OAuthAppController, :delete)
-
- get("/media_proxy_caches", MediaProxyCacheController, :index)
- post("/media_proxy_caches/delete", MediaProxyCacheController, :delete)
- post("/media_proxy_caches/purge", MediaProxyCacheController, :purge)
-
- get("/frontends", FrontendController, :index)
- post("/frontends/install", FrontendController, :install)
-
- post("/backups", AdminAPIController, :create_backup)
- end
-
- # AdminAPI: admins and mods (staff) can perform these actions (if privileged by role)
- scope "/api/v1/pleroma/admin", Pleroma.Web.AdminAPI do
- pipe_through(:require_privileged_role_announcements_manage_announcements)
-
- get("/announcements", AnnouncementController, :index)
- post("/announcements", AnnouncementController, :create)
- get("/announcements/:id", AnnouncementController, :show)
- patch("/announcements/:id", AnnouncementController, :change)
- delete("/announcements/:id", AnnouncementController, :delete)
- end
-
- # AdminAPI: admins and mods (staff) can perform these actions (if privileged by role)
- scope "/api/v1/pleroma/admin", Pleroma.Web.AdminAPI do
- pipe_through(:require_privileged_role_users_delete)
-
- delete("/users", UserController, :delete)
- end
-
- # AdminAPI: admins and mods (staff) can perform these actions (if privileged by role)
- scope "/api/v1/pleroma/admin", Pleroma.Web.AdminAPI do
- pipe_through(:require_privileged_role_users_manage_credentials)
-
- get("/users/:nickname/password_reset", AdminAPIController, :get_password_reset)
- get("/users/:nickname/credentials", AdminAPIController, :show_user_credentials)
- patch("/users/:nickname/credentials", AdminAPIController, :update_user_credentials)
- put("/users/disable_mfa", AdminAPIController, :disable_mfa)
- patch("/users/force_password_reset", AdminAPIController, :force_password_reset)
- patch("/users/confirm_email", AdminAPIController, :confirm_email)
- patch("/users/resend_confirmation_email", AdminAPIController, :resend_confirmation_email)
- end
-
- # AdminAPI: admins and mods (staff) can perform these actions (if privileged by role)
- scope "/api/v1/pleroma/admin", Pleroma.Web.AdminAPI do
- pipe_through(:require_privileged_role_messages_read)
-
- get("/users/:nickname/statuses", AdminAPIController, :list_user_statuses)
- get("/users/:nickname/chats", AdminAPIController, :list_user_chats)
-
- get("/statuses", StatusController, :index)
-
- get("/chats/:id", ChatController, :show)
- get("/chats/:id/messages", ChatController, :messages)
-
- get("/instances/:instance/statuses", InstanceController, :list_statuses)
-
- get("/statuses/:id", StatusController, :show)
- end
-
- # AdminAPI: admins and mods (staff) can perform these actions (if privileged by role)
- scope "/api/v1/pleroma/admin", Pleroma.Web.AdminAPI do
- pipe_through(:require_privileged_role_users_manage_tags)
-
- put("/users/tag", AdminAPIController, :tag_users)
- delete("/users/tag", AdminAPIController, :untag_users)
- end
-
- # AdminAPI: admins and mods (staff) can perform these actions (if privileged by role)
- scope "/api/v1/pleroma/admin", Pleroma.Web.AdminAPI do
- pipe_through(:require_privileged_role_users_manage_activation_state)
-
- patch("/users/:nickname/toggle_activation", UserController, :toggle_activation)
- patch("/users/activate", UserController, :activate)
- patch("/users/deactivate", UserController, :deactivate)
- end
-
- # AdminAPI: admins and mods (staff) can perform these actions (if privileged by role)
- scope "/api/v1/pleroma/admin", Pleroma.Web.AdminAPI do
- pipe_through(:require_privileged_role_users_manage_invites)
-
- patch("/users/approve", UserController, :approve)
- post("/users/invite_token", InviteController, :create)
- get("/users/invites", InviteController, :index)
- post("/users/revoke_invite", InviteController, :revoke)
- post("/users/email_invite", InviteController, :email)
- end
-
- # AdminAPI: admins and mods (staff) can perform these actions (if privileged by role)
- scope "/api/v1/pleroma/admin", Pleroma.Web.AdminAPI do
- pipe_through(:require_privileged_role_reports_manage_reports)
-
- get("/reports", ReportController, :index)
- get("/reports/:id", ReportController, :show)
- patch("/reports", ReportController, :update)
- post("/reports/:id/notes", ReportController, :notes_create)
- delete("/reports/:report_id/notes/:id", ReportController, :notes_delete)
- end
-
- # AdminAPI: admins and mods (staff) can perform these actions (if privileged by role)
- scope "/api/v1/pleroma/admin", Pleroma.Web.AdminAPI do
- pipe_through(:require_privileged_role_users_read)
-
- get("/users", UserController, :index)
- get("/users/:nickname", UserController, :show)
- end
-
- # AdminAPI: admins and mods (staff) can perform these actions (if privileged by role)
- scope "/api/v1/pleroma/admin", Pleroma.Web.AdminAPI do
- pipe_through(:require_privileged_role_messages_delete)
-
- put("/statuses/:id", StatusController, :update)
- delete("/statuses/:id", StatusController, :delete)
-
- delete("/chats/:id/messages/:message_id", ChatController, :delete_message)
- end
-
- # AdminAPI: admins and mods (staff) can perform these actions (if privileged by role)
- scope "/api/v1/pleroma/admin", Pleroma.Web.AdminAPI do
- pipe_through(:require_privileged_role_emoji_manage_emoji)
-
- post("/reload_emoji", AdminAPIController, :reload_emoji)
- end
-
- # AdminAPI: admins and mods (staff) can perform these actions (if privileged by role)
- scope "/api/v1/pleroma/admin", Pleroma.Web.AdminAPI do
- pipe_through(:require_privileged_role_instances_delete)
-
- delete("/instances/:instance", InstanceController, :delete)
- end
-
- # AdminAPI: admins and mods (staff) can perform these actions (if privileged by role)
- scope "/api/v1/pleroma/admin", Pleroma.Web.AdminAPI do
- pipe_through(:require_privileged_role_moderation_log_read)
-
- get("/moderation_log", AdminAPIController, :list_log)
- end
-
- # AdminAPI: admins and mods (staff) can perform these actions (if privileged by role)
- scope "/api/v1/pleroma/admin", Pleroma.Web.AdminAPI do
- pipe_through(:require_privileged_role_statistics_read)
-
- get("/stats", AdminAPIController, :stats)
- end
-
- scope "/api/v1/pleroma/emoji", Pleroma.Web.PleromaAPI do
- scope "/pack" do
- pipe_through(:require_privileged_role_emoji_manage_emoji)
-
- post("/", EmojiPackController, :create)
- patch("/", EmojiPackController, :update)
- delete("/", EmojiPackController, :delete)
- end
-
- scope "/pack" do
- pipe_through(:api)
-
- get("/", EmojiPackController, :show)
- end
-
- # Modifying packs
- scope "/packs" do
- pipe_through(:require_privileged_role_emoji_manage_emoji)
-
- get("/import", EmojiPackController, :import_from_filesystem)
- get("/remote", EmojiPackController, :remote)
- post("/download", EmojiPackController, :download)
-
- post("/files", EmojiFileController, :create)
- patch("/files", EmojiFileController, :update)
- delete("/files", EmojiFileController, :delete)
- end
-
- # Pack info / downloading
- scope "/packs" do
- pipe_through(:api)
-
- get("/", EmojiPackController, :index)
- get("/archive", EmojiPackController, :archive)
- end
- end
-
- scope "/", Pleroma.Web.TwitterAPI do
- pipe_through(:pleroma_html)
-
- post("/main/ostatus", UtilController, :remote_subscribe)
- get("/main/ostatus", UtilController, :show_subscribe_form)
- get("/ostatus_subscribe", RemoteFollowController, :follow)
- post("/ostatus_subscribe", RemoteFollowController, :do_follow)
- end
-
- scope "/api/pleroma", Pleroma.Web.TwitterAPI do
- pipe_through(:authenticated_api)
-
- post("/change_email", UtilController, :change_email)
- post("/change_password", UtilController, :change_password)
- post("/delete_account", UtilController, :delete_account)
- put("/notification_settings", UtilController, :update_notificaton_settings)
- post("/disable_account", UtilController, :disable_account)
- post("/move_account", UtilController, :move_account)
-
- put("/aliases", UtilController, :add_alias)
- get("/aliases", UtilController, :list_aliases)
- delete("/aliases", UtilController, :delete_alias)
- end
-
- scope "/api/pleroma", Pleroma.Web.PleromaAPI do
- pipe_through(:authenticated_api)
-
- post("/mutes_import", UserImportController, :mutes)
- post("/blocks_import", UserImportController, :blocks)
- post("/follow_import", UserImportController, :follow)
-
- get("/accounts/mfa", TwoFactorAuthenticationController, :settings)
- get("/accounts/mfa/backup_codes", TwoFactorAuthenticationController, :backup_codes)
- get("/accounts/mfa/setup/:method", TwoFactorAuthenticationController, :setup)
- post("/accounts/mfa/confirm/:method", TwoFactorAuthenticationController, :confirm)
- delete("/accounts/mfa/:method", TwoFactorAuthenticationController, :disable)
- end
-
- scope "/oauth", Pleroma.Web.OAuth do
- # Note: use /api/v1/accounts/verify_credentials for userinfo of signed-in user
-
- get("/registration_details", OAuthController, :registration_details)
-
- post("/mfa/verify", MFAController, :verify, as: :mfa_verify)
- get("/mfa", MFAController, :show)
-
- scope [] do
- pipe_through(:oauth)
-
- get("/authorize", OAuthController, :authorize)
- post("/authorize", OAuthController, :create_authorization)
- end
-
- scope [] do
- pipe_through(:fetch_session)
-
- post("/token", OAuthController, :token_exchange)
- post("/revoke", OAuthController, :token_revoke)
- post("/mfa/challenge", MFAController, :challenge)
- end
-
- scope [] do
- pipe_through(:browser)
-
- get("/prepare_request", OAuthController, :prepare_request)
- get("/:provider", OAuthController, :request)
- get("/:provider/callback", OAuthController, :callback)
- post("/register", OAuthController, :register)
- end
- end
-
- scope "/api/v1/pleroma", Pleroma.Web.PleromaAPI do
- pipe_through(:api)
-
- get("/apps", AppController, :index)
- get("/statuses/:id/reactions/:emoji", EmojiReactionController, :index)
- get("/statuses/:id/reactions", EmojiReactionController, :index)
- end
-
- scope "/api/v0/pleroma", Pleroma.Web.PleromaAPI do
- pipe_through(:authenticated_api)
- get("/reports", ReportController, :index)
- get("/reports/:id", ReportController, :show)
- end
-
- scope "/api/v1/pleroma", Pleroma.Web.PleromaAPI do
- scope [] do
- pipe_through(:authenticated_api)
-
- post("/chats/by-account-id/:id", ChatController, :create)
- get("/chats", ChatController, :index)
- get("/chats/:id", ChatController, :show)
- get("/chats/:id/messages", ChatController, :messages)
- post("/chats/:id/messages", ChatController, :post_chat_message)
- delete("/chats/:id/messages/:message_id", ChatController, :delete_message)
- post("/chats/:id/read", ChatController, :mark_as_read)
- post("/chats/:id/messages/:message_id/read", ChatController, :mark_message_as_read)
-
- get("/conversations/:id/statuses", ConversationController, :statuses)
- get("/conversations/:id", ConversationController, :show)
- post("/conversations/read", ConversationController, :mark_as_read)
- patch("/conversations/:id", ConversationController, :update)
-
- put("/statuses/:id/reactions/:emoji", EmojiReactionController, :create)
- delete("/statuses/:id/reactions/:emoji", EmojiReactionController, :delete)
- post("/notifications/read", NotificationController, :mark_as_read)
-
- get("/mascot", MascotController, :show)
- put("/mascot", MascotController, :update)
-
- post("/scrobble", ScrobbleController, :create)
-
- get("/backups", BackupController, :index)
- post("/backups", BackupController, :create)
- end
-
- scope [] do
- pipe_through(:api)
- get("/accounts/:id/favourites", AccountController, :favourites)
- get("/accounts/:id/endorsements", AccountController, :endorsements)
- end
-
- scope [] do
- pipe_through(:authenticated_api)
-
- post("/accounts/:id/subscribe", AccountController, :subscribe)
- post("/accounts/:id/unsubscribe", AccountController, :unsubscribe)
-
- get("/birthdays", AccountController, :birthdays)
- end
-
- scope [] do
- pipe_through(:authenticated_api)
-
- get("/settings/:app", SettingsController, :show)
- patch("/settings/:app", SettingsController, :update)
- end
-
- post("/accounts/confirmation_resend", AccountController, :confirmation_resend)
- end
-
- scope "/api/v1/pleroma", Pleroma.Web.PleromaAPI do
- pipe_through(:api)
- get("/accounts/:id/scrobbles", ScrobbleController, :index)
- get("/federation_status", InstancesController, :show)
- end
-
- scope "/api/v2/pleroma", Pleroma.Web.PleromaAPI do
- scope [] do
- pipe_through(:authenticated_api)
- get("/chats", ChatController, :index2)
- end
- end
-
- scope "/api/v1", Pleroma.Web.MastodonAPI do
- pipe_through(:authenticated_api)
-
- get("/accounts/verify_credentials", AccountController, :verify_credentials)
- patch("/accounts/update_credentials", AccountController, :update_credentials)
-
- get("/accounts/relationships", AccountController, :relationships)
- get("/accounts/:id/lists", AccountController, :lists)
- get("/accounts/:id/identity_proofs", AccountController, :identity_proofs)
- get("/endorsements", AccountController, :endorsements)
- get("/blocks", AccountController, :blocks)
- get("/mutes", AccountController, :mutes)
-
- post("/follows", AccountController, :follow_by_uri)
- post("/accounts/:id/follow", AccountController, :follow)
- post("/accounts/:id/unfollow", AccountController, :unfollow)
- post("/accounts/:id/block", AccountController, :block)
- post("/accounts/:id/unblock", AccountController, :unblock)
- post("/accounts/:id/mute", AccountController, :mute)
- post("/accounts/:id/unmute", AccountController, :unmute)
- post("/accounts/:id/note", AccountController, :note)
- post("/accounts/:id/pin", AccountController, :endorse)
- post("/accounts/:id/unpin", AccountController, :unendorse)
- post("/accounts/:id/remove_from_followers", AccountController, :remove_from_followers)
-
- get("/conversations", ConversationController, :index)
- post("/conversations/:id/read", ConversationController, :mark_as_read)
- delete("/conversations/:id", ConversationController, :delete)
-
- get("/domain_blocks", DomainBlockController, :index)
- post("/domain_blocks", DomainBlockController, :create)
- delete("/domain_blocks", DomainBlockController, :delete)
-
- get("/filters", FilterController, :index)
-
- post("/filters", FilterController, :create)
- get("/filters/:id", FilterController, :show)
- put("/filters/:id", FilterController, :update)
- delete("/filters/:id", FilterController, :delete)
-
- get("/follow_requests", FollowRequestController, :index)
- post("/follow_requests/:id/authorize", FollowRequestController, :authorize)
- post("/follow_requests/:id/reject", FollowRequestController, :reject)
-
- get("/lists", ListController, :index)
- get("/lists/:id", ListController, :show)
- get("/lists/:id/accounts", ListController, :list_accounts)
-
- delete("/lists/:id", ListController, :delete)
- post("/lists", ListController, :create)
- put("/lists/:id", ListController, :update)
- post("/lists/:id/accounts", ListController, :add_to_list)
- delete("/lists/:id/accounts", ListController, :remove_from_list)
-
- get("/markers", MarkerController, :index)
- post("/markers", MarkerController, :upsert)
-
- post("/media", MediaController, :create)
- get("/media/:id", MediaController, :show)
- put("/media/:id", MediaController, :update)
-
- get("/notifications", NotificationController, :index)
- get("/notifications/:id", NotificationController, :show)
-
- post("/notifications/:id/dismiss", NotificationController, :dismiss)
- post("/notifications/clear", NotificationController, :clear)
- delete("/notifications/destroy_multiple", NotificationController, :destroy_multiple)
- # Deprecated: was removed in Mastodon v3, use `/notifications/:id/dismiss` instead
- post("/notifications/dismiss", NotificationController, :dismiss_via_body)
-
- post("/polls/:id/votes", PollController, :vote)
-
- post("/reports", ReportController, :create)
-
- get("/scheduled_statuses", ScheduledActivityController, :index)
- get("/scheduled_statuses/:id", ScheduledActivityController, :show)
-
- put("/scheduled_statuses/:id", ScheduledActivityController, :update)
- delete("/scheduled_statuses/:id", ScheduledActivityController, :delete)
-
- # Unlike `GET /api/v1/accounts/:id/favourites`, demands authentication
- get("/favourites", StatusController, :favourites)
- get("/bookmarks", StatusController, :bookmarks)
-
- post("/statuses", StatusController, :create)
- put("/statuses/:id", StatusController, :update)
- delete("/statuses/:id", StatusController, :delete)
- post("/statuses/:id/reblog", StatusController, :reblog)
- post("/statuses/:id/unreblog", StatusController, :unreblog)
- post("/statuses/:id/favourite", StatusController, :favourite)
- post("/statuses/:id/unfavourite", StatusController, :unfavourite)
- post("/statuses/:id/pin", StatusController, :pin)
- post("/statuses/:id/unpin", StatusController, :unpin)
- post("/statuses/:id/bookmark", StatusController, :bookmark)
- post("/statuses/:id/unbookmark", StatusController, :unbookmark)
- post("/statuses/:id/mute", StatusController, :mute_conversation)
- post("/statuses/:id/unmute", StatusController, :unmute_conversation)
-
- post("/push/subscription", SubscriptionController, :create)
- get("/push/subscription", SubscriptionController, :show)
- put("/push/subscription", SubscriptionController, :update)
- delete("/push/subscription", SubscriptionController, :delete)
-
- get("/suggestions", SuggestionController, :index)
- delete("/suggestions/:account_id", SuggestionController, :dismiss)
-
- get("/timelines/home", TimelineController, :home)
- get("/timelines/direct", TimelineController, :direct)
- get("/timelines/list/:list_id", TimelineController, :list)
-
- get("/announcements", AnnouncementController, :index)
- post("/announcements/:id/dismiss", AnnouncementController, :mark_read)
- end
-
- scope "/api/v1", Pleroma.Web.MastodonAPI do
- pipe_through(:app_api)
-
- post("/apps", AppController, :create)
- get("/apps/verify_credentials", AppController, :verify_credentials)
- end
-
- scope "/api/v1", Pleroma.Web.MastodonAPI do
- pipe_through(:api)
-
- get("/accounts/search", SearchController, :account_search)
- get("/search", SearchController, :search)
-
- get("/accounts/lookup", AccountController, :lookup)
-
- get("/accounts/:id/statuses", AccountController, :statuses)
- get("/accounts/:id/followers", AccountController, :followers)
- get("/accounts/:id/following", AccountController, :following)
- get("/accounts/:id", AccountController, :show)
-
- post("/accounts", AccountController, :create)
-
- get("/instance", InstanceController, :show)
- get("/instance/peers", InstanceController, :peers)
-
- get("/statuses", StatusController, :index)
- get("/statuses/:id", StatusController, :show)
- get("/statuses/:id/context", StatusController, :context)
- get("/statuses/:id/card", StatusController, :card)
- get("/statuses/:id/favourited_by", StatusController, :favourited_by)
- get("/statuses/:id/reblogged_by", StatusController, :reblogged_by)
- get("/statuses/:id/history", StatusController, :show_history)
- get("/statuses/:id/source", StatusController, :show_source)
-
- get("/custom_emojis", CustomEmojiController, :index)
-
- get("/trends", MastodonAPIController, :empty_array)
-
- get("/timelines/public", TimelineController, :public)
- get("/timelines/tag/:tag", TimelineController, :hashtag)
-
- get("/polls/:id", PollController, :show)
-
- get("/directory", DirectoryController, :index)
- end
-
- scope "/api/v2", Pleroma.Web.MastodonAPI do
- pipe_through(:api)
- get("/search", SearchController, :search2)
-
- post("/media", MediaController, :create2)
-
- get("/suggestions", SuggestionController, :index2)
- end
-
- scope "/api", Pleroma.Web do
- pipe_through(:config)
-
- get("/pleroma/frontend_configurations", TwitterAPI.UtilController, :frontend_configurations)
- end
-
- scope "/api", Pleroma.Web do
- pipe_through(:api)
-
- get(
- "/account/confirm_email/:user_id/:token",
- TwitterAPI.Controller,
- :confirm_email,
- as: :confirm_email
- )
- end
-
- scope "/api" do
- pipe_through(:base_api)
-
- get("/openapi", OpenApiSpex.Plug.RenderSpec, [])
- end
-
- scope "/api", Pleroma.Web, as: :authenticated_twitter_api do
- pipe_through(:authenticated_api)
-
- get("/oauth_tokens", TwitterAPI.Controller, :oauth_tokens)
- delete("/oauth_tokens/:id", TwitterAPI.Controller, :revoke_token)
- end
-
- scope "/", Pleroma.Web do
- # Note: html format is supported only if static FE is enabled
- # Note: http signature is only considered for json requests (no auth for non-json requests)
- pipe_through([:accepts_html_json, :http_signature, :static_fe])
-
- get("/objects/:uuid", OStatus.OStatusController, :object)
- get("/activities/:uuid", OStatus.OStatusController, :activity)
- get("/notice/:id", OStatus.OStatusController, :notice)
-
- # Mastodon compatibility routes
- get("/users/:nickname/statuses/:id", OStatus.OStatusController, :object)
- get("/users/:nickname/statuses/:id/activity", OStatus.OStatusController, :activity)
- end
-
- scope "/", Pleroma.Web do
- # Note: html format is supported only if static FE is enabled
- # Note: http signature is only considered for json requests (no auth for non-json requests)
- pipe_through([:accepts_html_xml_json, :http_signature, :static_fe])
-
- # Note: returns user _profile_ for json requests, redirects to user _feed_ for non-json ones
- get("/users/:nickname", Feed.UserController, :feed_redirect, as: :user_feed)
- end
-
- scope "/", Pleroma.Web do
- pipe_through([:accepts_html_xml])
-
- get("/users/:nickname/feed", Feed.UserController, :feed, as: :user_feed)
- end
-
- scope "/", Pleroma.Web do
- pipe_through(:accepts_html)
- get("/notice/:id/embed_player", OStatus.OStatusController, :notice_player)
- end
-
- scope "/", Pleroma.Web do
- pipe_through(:accepts_xml_rss_atom)
- get("/tags/:tag", Feed.TagController, :feed, as: :tag_feed)
- end
-
- scope "/", Pleroma.Web do
- pipe_through(:browser)
- get("/mailer/unsubscribe/:token", Mailer.SubscriptionController, :unsubscribe)
- end
-
- pipeline :ap_service_actor do
- plug(:accepts, ["activity+json", "json"])
- end
-
- # Server to Server (S2S) AP interactions
- pipeline :activitypub do
- plug(:ap_service_actor)
- plug(:http_signature)
- end
-
- # Client to Server (C2S) AP interactions
- pipeline :activitypub_client do
- plug(:ap_service_actor)
- plug(:fetch_session)
- plug(:authenticate)
- plug(:after_auth)
- end
-
- scope "/", Pleroma.Web.ActivityPub do
- pipe_through([:activitypub_client])
-
- get("/api/ap/whoami", ActivityPubController, :whoami)
- get("/users/:nickname/inbox", ActivityPubController, :read_inbox)
-
- get("/users/:nickname/outbox", ActivityPubController, :outbox)
- post("/users/:nickname/outbox", ActivityPubController, :update_outbox)
- post("/api/ap/upload_media", ActivityPubController, :upload_media)
-
- # The following two are S2S as well, see `ActivityPub.fetch_follow_information_for_user/1`:
- get("/users/:nickname/followers", ActivityPubController, :followers)
- get("/users/:nickname/following", ActivityPubController, :following)
- get("/users/:nickname/collections/featured", ActivityPubController, :pinned)
- end
-
- scope "/", Pleroma.Web.ActivityPub do
- pipe_through(:activitypub)
- post("/inbox", ActivityPubController, :inbox)
- post("/users/:nickname/inbox", ActivityPubController, :inbox)
- end
-
- scope "/relay", Pleroma.Web.ActivityPub do
- pipe_through(:ap_service_actor)
-
- get("/", ActivityPubController, :relay)
-
- scope [] do
- pipe_through(:http_signature)
- post("/inbox", ActivityPubController, :inbox)
- end
-
- get("/following", ActivityPubController, :relay_following)
- get("/followers", ActivityPubController, :relay_followers)
- end
-
- scope "/internal/fetch", Pleroma.Web.ActivityPub do
- pipe_through(:ap_service_actor)
-
- get("/", ActivityPubController, :internal_fetch)
- post("/inbox", ActivityPubController, :inbox)
- end
-
- scope "/.well-known", Pleroma.Web do
- pipe_through(:well_known)
-
- get("/host-meta", WebFinger.WebFingerController, :host_meta)
- get("/webfinger", WebFinger.WebFingerController, :webfinger)
- get("/nodeinfo", Nodeinfo.NodeinfoController, :schemas)
- end
-
- scope "/nodeinfo", Pleroma.Web do
- get("/:version", Nodeinfo.NodeinfoController, :nodeinfo)
- end
-
- scope "/", Pleroma.Web do
- pipe_through(:api)
-
- get("/manifest.json", ManifestController, :show)
- end
-
- scope "/", Pleroma.Web do
- pipe_through(:pleroma_html)
-
- post("/auth/password", TwitterAPI.PasswordController, :request)
- end
-
- scope "/proxy/", Pleroma.Web do
- get("/preview/:sig/:url", MediaProxy.MediaProxyController, :preview)
- get("/preview/:sig/:url/:filename", MediaProxy.MediaProxyController, :preview)
- get("/:sig/:url", MediaProxy.MediaProxyController, :remote)
- get("/:sig/:url/:filename", MediaProxy.MediaProxyController, :remote)
- end
-
- if Pleroma.Config.get(:env) == :dev do
- scope "/dev" do
- pipe_through([:mailbox_preview])
-
- forward("/mailbox", Plug.Swoosh.MailboxPreview, base_path: "/dev/mailbox")
- end
- end
-
- scope "/" do
- pipe_through([:pleroma_html, :authenticate, :require_admin])
- live_dashboard("/phoenix/live_dashboard")
- end
-
- # Test-only routes needed to test action dispatching and plug chain execution
- if Pleroma.Config.get(:env) == :test do
- @test_actions [
- :do_oauth_check,
- :fallback_oauth_check,
- :skip_oauth_check,
- :fallback_oauth_skip_publicity_check,
- :skip_oauth_skip_publicity_check,
- :missing_oauth_check_definition
- ]
-
- scope "/test/api", Pleroma.Tests do
- pipe_through(:api)
-
- for action <- @test_actions do
- get("/#{action}", AuthTestController, action)
- end
- end
-
- scope "/test/authenticated_api", Pleroma.Tests do
- pipe_through(:authenticated_api)
-
- for action <- @test_actions do
- get("/#{action}", AuthTestController, action)
- end
- end
- end
-
- scope "/", Pleroma.Web.MongooseIM do
- get("/user_exists", MongooseIMController, :user_exists)
- get("/check_password", MongooseIMController, :check_password)
- end
-
- scope "/", Pleroma.Web.Fallback do
- get("/registration/:token", RedirectController, :registration_page)
- get("/:maybe_nickname_or_id", RedirectController, :redirector_with_meta)
- match(:*, "/api/pleroma*path", LegacyPleromaApiRerouterPlug, [])
- get("/api*path", RedirectController, :api_not_implemented)
- get("/*path", RedirectController, :redirector_with_preload)
-
- options("/*path", RedirectController, :empty)
- end
-
- # TODO: Change to Phoenix.Router.routes/1 for Phoenix 1.6.0+
- def get_api_routes do
- __MODULE__.__routes__()
- |> Enum.reject(fn r -> r.plug == Pleroma.Web.Fallback.RedirectController end)
- |> Enum.map(fn r ->
- r.path
- |> String.split("/", trim: true)
- |> List.first()
- end)
- |> Enum.uniq()
- end
-end
diff --git a/lib/pleroma/web/shout_channel.ex b/lib/pleroma/web/shout_channel.ex
index 928f0a1..928f0a1 100755..100644
--- a/lib/pleroma/web/shout_channel.ex
+++ b/lib/pleroma/web/shout_channel.ex
diff --git a/lib/pleroma/web/static_fe/static_fe_controller.ex b/lib/pleroma/web/static_fe/static_fe_controller.ex
index 97c41c6..012f8e4 100755..100644
--- a/lib/pleroma/web/static_fe/static_fe_controller.ex
+++ b/lib/pleroma/web/static_fe/static_fe_controller.ex
@@ -13,7 +13,6 @@ defmodule Pleroma.Web.StaticFE.StaticFEController do
alias Pleroma.Web.Metadata
alias Pleroma.Web.Router.Helpers
- plug(:put_layout, :static_fe)
plug(:assign_id)
@page_keys ["max_id", "min_id", "limit", "since_id", "order"]
@@ -22,10 +21,18 @@ defmodule Pleroma.Web.StaticFE.StaticFEController do
def show(%{assigns: %{notice_id: notice_id}} = conn, _params) do
with %Activity{local: true} = activity <-
Activity.get_by_id_with_object(notice_id),
- true <- Visibility.is_public?(activity.object),
+ true <- Visibility.public?(activity.object),
{_, true} <- {:visible?, Visibility.visible_for_user?(activity, _reading_user = nil)},
%User{} = user <- User.get_by_ap_id(activity.object.data["actor"]) do
- meta = Metadata.build_tags(%{activity_id: notice_id, object: activity.object, user: user})
+ url = Helpers.url(conn) <> conn.request_path
+
+ meta =
+ Metadata.build_tags(%{
+ activity_id: notice_id,
+ object: activity.object,
+ user: user,
+ url: url
+ })
timeline =
activity.object.data["context"]
diff --git a/lib/pleroma/web/static_fe/static_fe_view.ex b/lib/pleroma/web/static_fe/static_fe_view.ex
index 8e23a79..8e23a79 100755..100644
--- a/lib/pleroma/web/static_fe/static_fe_view.ex
+++ b/lib/pleroma/web/static_fe/static_fe_view.ex
diff --git a/lib/pleroma/web/streamer.ex b/lib/pleroma/web/streamer.ex
index b9a04cc..7065fda 100755..100644
--- a/lib/pleroma/web/streamer.ex
+++ b/lib/pleroma/web/streamer.ex
@@ -4,6 +4,7 @@
defmodule Pleroma.Web.Streamer do
require Logger
+ require Pleroma.Constants
alias Pleroma.Activity
alias Pleroma.Chat.MessageReference
@@ -19,12 +20,11 @@ defmodule Pleroma.Web.Streamer do
alias Pleroma.Web.Plugs.OAuthScopesPlug
alias Pleroma.Web.StreamerView
- @mix_env Mix.env()
@registry Pleroma.Web.StreamerRegistry
def registry, do: @registry
- @public_streams ["public", "public:local", "public:media", "public:local:media"]
+ @public_streams Pleroma.Constants.public_streams()
@local_streams ["public:local", "public:local:media"]
@user_streams ["user", "user:notification", "direct", "user:pleroma_chat"]
@@ -33,7 +33,7 @@ defmodule Pleroma.Web.Streamer do
stream :: String.t(),
User.t() | nil,
Token.t() | nil,
- Map.t() | nil
+ map() | nil
) ::
{:ok, topic :: String.t()} | {:error, :bad_topic} | {:error, :unauthorized}
def get_topic_and_add_socket(stream, user, oauth_token, params \\ %{}) do
@@ -59,10 +59,14 @@ defmodule Pleroma.Web.Streamer do
end
@doc "Expand and authorizes a stream"
- @spec get_topic(stream :: String.t(), User.t() | nil, Token.t() | nil, Map.t()) ::
- {:ok, topic :: String.t()} | {:error, :bad_topic}
+ @spec get_topic(stream :: String.t() | nil, User.t() | nil, Token.t() | nil, map()) ::
+ {:ok, topic :: String.t() | nil} | {:error, :bad_topic}
def get_topic(stream, user, oauth_token, params \\ %{})
+ def get_topic(nil = _stream, _user, _oauth_token, _params) do
+ {:ok, nil}
+ end
+
# Allow all public steams if the instance allows unauthenticated access.
# Otherwise, only allow users with valid oauth tokens.
def get_topic(stream, user, oauth_token, _params) when stream in @public_streams do
@@ -219,8 +223,8 @@ defmodule Pleroma.Web.Streamer do
end
defp do_stream("follow_relationship", item) do
- text = StreamerView.render("follow_relationships_update.json", item)
user_topic = "user:#{item.follower.id}"
+ text = StreamerView.render("follow_relationships_update.json", item, user_topic)
Logger.debug("Trying to push follow relationship update to #{user_topic}\n\n")
@@ -241,7 +245,7 @@ defmodule Pleroma.Web.Streamer do
defp do_stream("list", item) do
# filter the recipient list if the activity is not public, see #270.
recipient_lists =
- case Visibility.is_public?(item) do
+ case Visibility.public?(item) do
true ->
Pleroma.List.get_lists_from_activity(item)
@@ -266,9 +270,11 @@ defmodule Pleroma.Web.Streamer do
defp do_stream(topic, %Notification{} = item)
when topic in ["user", "user:notification"] do
- Registry.dispatch(@registry, "#{topic}:#{item.user_id}", fn list ->
+ user_topic = "#{topic}:#{item.user_id}"
+
+ Registry.dispatch(@registry, user_topic, fn list ->
Enum.each(list, fn {pid, _auth} ->
- send(pid, {:render_with_user, StreamerView, "notification.json", item})
+ send(pid, {:render_with_user, StreamerView, "notification.json", item, user_topic})
end)
end)
end
@@ -277,7 +283,7 @@ defmodule Pleroma.Web.Streamer do
when topic in ["user", "user:pleroma_chat"] do
topic = "#{topic}:#{user.id}"
- text = StreamerView.render("chat_update.json", %{chat_message_reference: cm_ref})
+ text = StreamerView.render("chat_update.json", %{chat_message_reference: cm_ref}, topic)
Registry.dispatch(@registry, topic, fn list ->
Enum.each(list, fn {pid, _auth} ->
@@ -305,7 +311,7 @@ defmodule Pleroma.Web.Streamer do
end
defp push_to_socket(topic, %Participation{} = participation) do
- rendered = StreamerView.render("conversation.json", participation)
+ rendered = StreamerView.render("conversation.json", participation, topic)
Registry.dispatch(@registry, topic, fn list ->
Enum.each(list, fn {pid, _} ->
@@ -333,12 +339,15 @@ defmodule Pleroma.Web.Streamer do
Pleroma.Activity.get_create_by_object_ap_id(item.object.data["id"])
|> Map.put(:object, item.object)
- anon_render = StreamerView.render("status_update.json", create_activity)
+ anon_render = StreamerView.render("status_update.json", create_activity, topic)
Registry.dispatch(@registry, topic, fn list ->
Enum.each(list, fn {pid, auth?} ->
if auth? do
- send(pid, {:render_with_user, StreamerView, "status_update.json", create_activity})
+ send(
+ pid,
+ {:render_with_user, StreamerView, "status_update.json", create_activity, topic}
+ )
else
send(pid, {:text, anon_render})
end
@@ -347,12 +356,12 @@ defmodule Pleroma.Web.Streamer do
end
defp push_to_socket(topic, item) do
- anon_render = StreamerView.render("update.json", item)
+ anon_render = StreamerView.render("update.json", item, topic)
Registry.dispatch(@registry, topic, fn list ->
Enum.each(list, fn {pid, auth?} ->
if auth? do
- send(pid, {:render_with_user, StreamerView, "update.json", item})
+ send(pid, {:render_with_user, StreamerView, "update.json", item, topic})
else
send(pid, {:text, anon_render})
end
@@ -386,25 +395,20 @@ defmodule Pleroma.Web.Streamer do
end
end
- # In test environement, only return true if the registry is started.
- # In benchmark environment, returns false.
- # In any other environment, always returns true.
- cond do
- @mix_env == :test ->
- def should_env_send? do
- case Process.whereis(@registry) do
- nil ->
- false
+ # In dev/prod the streamer registry is expected to be started, so return true
+ # In test it is possible to have the registry started for a test so it will check
+ # In benchmark it will never find the process alive and return false
+ def should_env_send? do
+ if Application.get_env(:pleroma, Pleroma.Application)[:streamer_registry] do
+ true
+ else
+ case Process.whereis(@registry) do
+ nil ->
+ false
- pid ->
- Process.alive?(pid)
- end
+ pid ->
+ Process.alive?(pid)
end
-
- @mix_env == :benchmark ->
- def should_env_send?, do: false
-
- true ->
- def should_env_send?, do: true
+ end
end
end
diff --git a/lib/pleroma/web/templates/email/digest.html.eex b/lib/pleroma/web/templates/email/digest.html.eex
index 1efc76e..1efc76e 100755..100644
--- a/lib/pleroma/web/templates/email/digest.html.eex
+++ b/lib/pleroma/web/templates/email/digest.html.eex
diff --git a/lib/pleroma/web/templates/email/new_users_digest.html.eex b/lib/pleroma/web/templates/email/new_users_digest.html.eex
index 40d9b83..40d9b83 100755..100644
--- a/lib/pleroma/web/templates/email/new_users_digest.html.eex
+++ b/lib/pleroma/web/templates/email/new_users_digest.html.eex
diff --git a/lib/pleroma/web/templates/embed/_attachment.html.eex b/lib/pleroma/web/templates/embed/_attachment.html.eex
index 7e04e95..7e04e95 100755..100644
--- a/lib/pleroma/web/templates/embed/_attachment.html.eex
+++ b/lib/pleroma/web/templates/embed/_attachment.html.eex
diff --git a/lib/pleroma/web/templates/embed/show.html.eex b/lib/pleroma/web/templates/embed/show.html.eex
index 092b52b..092b52b 100755..100644
--- a/lib/pleroma/web/templates/embed/show.html.eex
+++ b/lib/pleroma/web/templates/embed/show.html.eex
diff --git a/lib/pleroma/web/templates/feed/feed/_activity.atom.eex b/lib/pleroma/web/templates/feed/feed/_activity.atom.eex
index b774f79..b774f79 100755..100644
--- a/lib/pleroma/web/templates/feed/feed/_activity.atom.eex
+++ b/lib/pleroma/web/templates/feed/feed/_activity.atom.eex
diff --git a/lib/pleroma/web/templates/feed/feed/_activity.rss.eex b/lib/pleroma/web/templates/feed/feed/_activity.rss.eex
index 7de98f7..7de98f7 100755..100644
--- a/lib/pleroma/web/templates/feed/feed/_activity.rss.eex
+++ b/lib/pleroma/web/templates/feed/feed/_activity.rss.eex
diff --git a/lib/pleroma/web/templates/feed/feed/_author.atom.eex b/lib/pleroma/web/templates/feed/feed/_author.atom.eex
index 90be8a5..90be8a5 100755..100644
--- a/lib/pleroma/web/templates/feed/feed/_author.atom.eex
+++ b/lib/pleroma/web/templates/feed/feed/_author.atom.eex
diff --git a/lib/pleroma/web/templates/feed/feed/_author.rss.eex b/lib/pleroma/web/templates/feed/feed/_author.rss.eex
index 22477e6..22477e6 100755..100644
--- a/lib/pleroma/web/templates/feed/feed/_author.rss.eex
+++ b/lib/pleroma/web/templates/feed/feed/_author.rss.eex
diff --git a/lib/pleroma/web/templates/feed/feed/_tag_activity.atom.eex b/lib/pleroma/web/templates/feed/feed/_tag_activity.atom.eex
index 03c2229..03c2229 100755..100644
--- a/lib/pleroma/web/templates/feed/feed/_tag_activity.atom.eex
+++ b/lib/pleroma/web/templates/feed/feed/_tag_activity.atom.eex
diff --git a/lib/pleroma/web/templates/feed/feed/_tag_activity.xml.eex b/lib/pleroma/web/templates/feed/feed/_tag_activity.xml.eex
index 1b8c34b..1b8c34b 100755..100644
--- a/lib/pleroma/web/templates/feed/feed/_tag_activity.xml.eex
+++ b/lib/pleroma/web/templates/feed/feed/_tag_activity.xml.eex
diff --git a/lib/pleroma/web/templates/feed/feed/_tag_author.atom.eex b/lib/pleroma/web/templates/feed/feed/_tag_author.atom.eex
index 71c6968..71c6968 100755..100644
--- a/lib/pleroma/web/templates/feed/feed/_tag_author.atom.eex
+++ b/lib/pleroma/web/templates/feed/feed/_tag_author.atom.eex
diff --git a/lib/pleroma/web/templates/feed/feed/tag.atom.eex b/lib/pleroma/web/templates/feed/feed/tag.atom.eex
index 14b0ee5..14b0ee5 100755..100644
--- a/lib/pleroma/web/templates/feed/feed/tag.atom.eex
+++ b/lib/pleroma/web/templates/feed/feed/tag.atom.eex
diff --git a/lib/pleroma/web/templates/feed/feed/tag.rss.eex b/lib/pleroma/web/templates/feed/feed/tag.rss.eex
index 27dde56..27dde56 100755..100644
--- a/lib/pleroma/web/templates/feed/feed/tag.rss.eex
+++ b/lib/pleroma/web/templates/feed/feed/tag.rss.eex
diff --git a/lib/pleroma/web/templates/feed/feed/user.atom.eex b/lib/pleroma/web/templates/feed/feed/user.atom.eex
index e36bfc6..e36bfc6 100755..100644
--- a/lib/pleroma/web/templates/feed/feed/user.atom.eex
+++ b/lib/pleroma/web/templates/feed/feed/user.atom.eex
diff --git a/lib/pleroma/web/templates/feed/feed/user.rss.eex b/lib/pleroma/web/templates/feed/feed/user.rss.eex
index fae3fcf..fae3fcf 100755..100644
--- a/lib/pleroma/web/templates/feed/feed/user.rss.eex
+++ b/lib/pleroma/web/templates/feed/feed/user.rss.eex
diff --git a/lib/pleroma/web/templates/layout/app.html.eex b/lib/pleroma/web/templates/layout/app.html.eex
index e33bada..e33bada 100755..100644
--- a/lib/pleroma/web/templates/layout/app.html.eex
+++ b/lib/pleroma/web/templates/layout/app.html.eex
diff --git a/lib/pleroma/web/templates/layout/email.html.eex b/lib/pleroma/web/templates/layout/email.html.eex
index 5858e48..5858e48 100755..100644
--- a/lib/pleroma/web/templates/layout/email.html.eex
+++ b/lib/pleroma/web/templates/layout/email.html.eex
diff --git a/lib/pleroma/web/templates/layout/email_styled.html.eex b/lib/pleroma/web/templates/layout/email_styled.html.eex
index 82cabd8..82cabd8 100755..100644
--- a/lib/pleroma/web/templates/layout/email_styled.html.eex
+++ b/lib/pleroma/web/templates/layout/email_styled.html.eex
diff --git a/lib/pleroma/web/templates/layout/embed.html.eex b/lib/pleroma/web/templates/layout/embed.html.eex
index 1197288..1197288 100755..100644
--- a/lib/pleroma/web/templates/layout/embed.html.eex
+++ b/lib/pleroma/web/templates/layout/embed.html.eex
diff --git a/lib/pleroma/web/templates/layout/metadata_player.html.eex b/lib/pleroma/web/templates/layout/metadata_player.html.eex
index c00f6fa..c00f6fa 100755..100644
--- a/lib/pleroma/web/templates/layout/metadata_player.html.eex
+++ b/lib/pleroma/web/templates/layout/metadata_player.html.eex
diff --git a/lib/pleroma/web/templates/layout/static_fe.html.eex b/lib/pleroma/web/templates/layout/static_fe.html.eex
index e6adb52..e6adb52 100755..100644
--- a/lib/pleroma/web/templates/layout/static_fe.html.eex
+++ b/lib/pleroma/web/templates/layout/static_fe.html.eex
diff --git a/lib/pleroma/web/templates/mailer/subscription/unsubscribe_failure.html.eex b/lib/pleroma/web/templates/mailer/subscription/unsubscribe_failure.html.eex
index df090ff..df090ff 100755..100644
--- a/lib/pleroma/web/templates/mailer/subscription/unsubscribe_failure.html.eex
+++ b/lib/pleroma/web/templates/mailer/subscription/unsubscribe_failure.html.eex
diff --git a/lib/pleroma/web/templates/mailer/subscription/unsubscribe_success.html.eex b/lib/pleroma/web/templates/mailer/subscription/unsubscribe_success.html.eex
index cbce495..cbce495 100755..100644
--- a/lib/pleroma/web/templates/mailer/subscription/unsubscribe_success.html.eex
+++ b/lib/pleroma/web/templates/mailer/subscription/unsubscribe_success.html.eex
diff --git a/lib/pleroma/web/templates/o_auth/mfa/recovery.html.eex b/lib/pleroma/web/templates/o_auth/mfa/recovery.html.eex
index e45d13b..e3639aa 100755..100644
--- a/lib/pleroma/web/templates/o_auth/mfa/recovery.html.eex
+++ b/lib/pleroma/web/templates/o_auth/mfa/recovery.html.eex
@@ -1,8 +1,8 @@
-<%= if get_flash(@conn, :info) do %>
-<p class="alert alert-info" role="alert"><%= get_flash(@conn, :info) %></p>
+<%= if Phoenix.Flash.get(@flash, :info) do %>
+<p class="alert alert-info" role="alert"><%= Phoenix.Flash.get(@flash, :info) %></p>
<% end %>
-<%= if get_flash(@conn, :error) do %>
-<p class="alert alert-danger" role="alert"><%= get_flash(@conn, :error) %></p>
+<%= if Phoenix.Flash.get(@flash, :error) do %>
+<p class="alert alert-danger" role="alert"><%= Phoenix.Flash.get(@flash, :error) %></p>
<% end %>
<h2><%= Gettext.dpgettext("static_pages", "mfa recover page title", "Two-factor recovery") %></h2>
diff --git a/lib/pleroma/web/templates/o_auth/mfa/totp.html.eex b/lib/pleroma/web/templates/o_auth/mfa/totp.html.eex
index 50e6c04..f995b88 100755..100644
--- a/lib/pleroma/web/templates/o_auth/mfa/totp.html.eex
+++ b/lib/pleroma/web/templates/o_auth/mfa/totp.html.eex
@@ -1,8 +1,8 @@
-<%= if get_flash(@conn, :info) do %>
-<p class="alert alert-info" role="alert"><%= get_flash(@conn, :info) %></p>
+<%= if Phoenix.Flash.get(@flash, :info) do %>
+<p class="alert alert-info" role="alert"><%= Phoenix.Flash.get(@flash, :info) %></p>
<% end %>
-<%= if get_flash(@conn, :error) do %>
-<p class="alert alert-danger" role="alert"><%= get_flash(@conn, :error) %></p>
+<%= if Phoenix.Flash.get(@flash, :error) do %>
+<p class="alert alert-danger" role="alert"><%= Phoenix.Flash.get(@flash, :error) %></p>
<% end %>
<h2><%= Gettext.dpgettext("static_pages", "mfa auth page title", "Two-factor authentication") %></h2>
diff --git a/lib/pleroma/web/templates/o_auth/o_auth/_scopes.html.eex b/lib/pleroma/web/templates/o_auth/o_auth/_scopes.html.eex
index 73115e9..7585c4d 100755..100644
--- a/lib/pleroma/web/templates/o_auth/o_auth/_scopes.html.eex
+++ b/lib/pleroma/web/templates/o_auth/o_auth/_scopes.html.eex
@@ -8,7 +8,7 @@
<%= checkbox @form, :"scope_#{scope}", value: scope in @scopes && scope, checked_value: scope, unchecked_value: "", name: "authorization[scope][]" %>
<%= label @form, :"scope_#{scope}", String.capitalize(scope) %>
<%= if scope in @scopes && scope do %>
- <%= String.capitalize(scope) %>
+ <code><%= scope %></code> <%= :"Elixir.Gettext".dgettext(Gettext, "oauth_scopes", scope) %>
<% end %>
</div>
<% else %>
diff --git a/lib/pleroma/web/templates/o_auth/o_auth/consumer.html.eex b/lib/pleroma/web/templates/o_auth/o_auth/consumer.html.eex
index 98904ad..98904ad 100755..100644
--- a/lib/pleroma/web/templates/o_auth/o_auth/consumer.html.eex
+++ b/lib/pleroma/web/templates/o_auth/o_auth/consumer.html.eex
diff --git a/lib/pleroma/web/templates/o_auth/o_auth/oob_authorization_created.html.eex b/lib/pleroma/web/templates/o_auth/o_auth/oob_authorization_created.html.eex
index 76ed3fd..76ed3fd 100755..100644
--- a/lib/pleroma/web/templates/o_auth/o_auth/oob_authorization_created.html.eex
+++ b/lib/pleroma/web/templates/o_auth/o_auth/oob_authorization_created.html.eex
diff --git a/lib/pleroma/web/templates/o_auth/o_auth/oob_token_exists.html.eex b/lib/pleroma/web/templates/o_auth/o_auth/oob_token_exists.html.eex
index 754bf2e..754bf2e 100755..100644
--- a/lib/pleroma/web/templates/o_auth/o_auth/oob_token_exists.html.eex
+++ b/lib/pleroma/web/templates/o_auth/o_auth/oob_token_exists.html.eex
diff --git a/lib/pleroma/web/templates/o_auth/o_auth/register.html.eex b/lib/pleroma/web/templates/o_auth/o_auth/register.html.eex
index 1f661ef..e7f6526 100755..100644
--- a/lib/pleroma/web/templates/o_auth/o_auth/register.html.eex
+++ b/lib/pleroma/web/templates/o_auth/o_auth/register.html.eex
@@ -1,8 +1,8 @@
-<%= if get_flash(@conn, :info) do %>
- <p class="alert alert-info" role="alert"><%= get_flash(@conn, :info) %></p>
+<%= if Phoenix.Flash.get(@flash, :info) do %>
+ <p class="alert alert-info" role="alert"><%= Phoenix.Flash.get(@flash, :info) %></p>
<% end %>
-<%= if get_flash(@conn, :error) do %>
- <p class="alert alert-danger" role="alert"><%= get_flash(@conn, :error) %></p>
+<%= if Phoenix.Flash.get(@flash, :error) do %>
+ <p class="alert alert-danger" role="alert"><%= Phoenix.Flash.get(@flash, :error) %></p>
<% end %>
<h2><%= Gettext.dpgettext("static_pages", "oauth register page title", "Registration Details") %></h2>
diff --git a/lib/pleroma/web/templates/o_auth/o_auth/show.html.eex b/lib/pleroma/web/templates/o_auth/o_auth/show.html.eex
index b3654f3..6bc8eb6 100755..100644
--- a/lib/pleroma/web/templates/o_auth/o_auth/show.html.eex
+++ b/lib/pleroma/web/templates/o_auth/o_auth/show.html.eex
@@ -1,8 +1,8 @@
-<%= if get_flash(@conn, :info) do %>
-<p class="alert alert-info" role="alert"><%= get_flash(@conn, :info) %></p>
+<%= if Phoenix.Flash.get(@flash, :info) do %>
+<p class="alert alert-info" role="alert"><%= Phoenix.Flash.get(@flash, :info) %></p>
<% end %>
-<%= if get_flash(@conn, :error) do %>
-<p class="alert alert-danger" role="alert"><%= get_flash(@conn, :error) %></p>
+<%= if Phoenix.Flash.get(@flash, :error) do %>
+<p class="alert alert-danger" role="alert"><%= Phoenix.Flash.get(@flash, :error) %></p>
<% end %>
<%= form_for @conn, Routes.o_auth_path(@conn, :authorize), [as: "authorization"], fn f -> %>
@@ -13,7 +13,7 @@
<div class="account-header__avatar" style="background-image: url('<%= Pleroma.User.avatar_url(@user) %>')"></div>
<div class="account-header__meta">
<div class="account-header__display-name"><%= @user.name %></div>
- <div class="account-header__nickname">@<%= @user.nickname %>@<%= Pleroma.User.get_host(@user) %></div>
+ <div class="account-header__nickname">@<%= Pleroma.User.full_nickname(@user.nickname) %></div>
</div>
</div>
<% end %>
diff --git a/lib/pleroma/web/templates/static_fe/static_fe/_attachment.html.eex b/lib/pleroma/web/templates/static_fe/static_fe/_attachment.html.eex
index 4853e7f..4853e7f 100755..100644
--- a/lib/pleroma/web/templates/static_fe/static_fe/_attachment.html.eex
+++ b/lib/pleroma/web/templates/static_fe/static_fe/_attachment.html.eex
diff --git a/lib/pleroma/web/templates/static_fe/static_fe/_notice.html.eex b/lib/pleroma/web/templates/static_fe/static_fe/_notice.html.eex
index df02447..df02447 100755..100644
--- a/lib/pleroma/web/templates/static_fe/static_fe/_notice.html.eex
+++ b/lib/pleroma/web/templates/static_fe/static_fe/_notice.html.eex
diff --git a/lib/pleroma/web/templates/static_fe/static_fe/_user_card.html.eex b/lib/pleroma/web/templates/static_fe/static_fe/_user_card.html.eex
index 977b894..977b894 100755..100644
--- a/lib/pleroma/web/templates/static_fe/static_fe/_user_card.html.eex
+++ b/lib/pleroma/web/templates/static_fe/static_fe/_user_card.html.eex
diff --git a/lib/pleroma/web/templates/static_fe/static_fe/conversation.html.eex b/lib/pleroma/web/templates/static_fe/static_fe/conversation.html.eex
index 2acd848..2acd848 100755..100644
--- a/lib/pleroma/web/templates/static_fe/static_fe/conversation.html.eex
+++ b/lib/pleroma/web/templates/static_fe/static_fe/conversation.html.eex
diff --git a/lib/pleroma/web/templates/static_fe/static_fe/error.html.eex b/lib/pleroma/web/templates/static_fe/static_fe/error.html.eex
index d98a1eb..d98a1eb 100755..100644
--- a/lib/pleroma/web/templates/static_fe/static_fe/error.html.eex
+++ b/lib/pleroma/web/templates/static_fe/static_fe/error.html.eex
diff --git a/lib/pleroma/web/templates/static_fe/static_fe/profile.html.eex b/lib/pleroma/web/templates/static_fe/static_fe/profile.html.eex
index a14ca30..a14ca30 100755..100644
--- a/lib/pleroma/web/templates/static_fe/static_fe/profile.html.eex
+++ b/lib/pleroma/web/templates/static_fe/static_fe/profile.html.eex
diff --git a/lib/pleroma/web/templates/twitter_api/password/invalid_token.html.eex b/lib/pleroma/web/templates/twitter_api/password/invalid_token.html.eex
index 5ac0aa4..5ac0aa4 100755..100644
--- a/lib/pleroma/web/templates/twitter_api/password/invalid_token.html.eex
+++ b/lib/pleroma/web/templates/twitter_api/password/invalid_token.html.eex
diff --git a/lib/pleroma/web/templates/twitter_api/password/reset.html.eex b/lib/pleroma/web/templates/twitter_api/password/reset.html.eex
index 6a544af..6a544af 100755..100644
--- a/lib/pleroma/web/templates/twitter_api/password/reset.html.eex
+++ b/lib/pleroma/web/templates/twitter_api/password/reset.html.eex
diff --git a/lib/pleroma/web/templates/twitter_api/password/reset_failed.html.eex b/lib/pleroma/web/templates/twitter_api/password/reset_failed.html.eex
index 774e346..774e346 100755..100644
--- a/lib/pleroma/web/templates/twitter_api/password/reset_failed.html.eex
+++ b/lib/pleroma/web/templates/twitter_api/password/reset_failed.html.eex
diff --git a/lib/pleroma/web/templates/twitter_api/password/reset_success.html.eex b/lib/pleroma/web/templates/twitter_api/password/reset_success.html.eex
index 40f6bb3..40f6bb3 100755..100644
--- a/lib/pleroma/web/templates/twitter_api/password/reset_success.html.eex
+++ b/lib/pleroma/web/templates/twitter_api/password/reset_success.html.eex
diff --git a/lib/pleroma/web/templates/twitter_api/remote_follow/follow.html.eex b/lib/pleroma/web/templates/twitter_api/remote_follow/follow.html.eex
index e2d251f..e2d251f 100755..100644
--- a/lib/pleroma/web/templates/twitter_api/remote_follow/follow.html.eex
+++ b/lib/pleroma/web/templates/twitter_api/remote_follow/follow.html.eex
diff --git a/lib/pleroma/web/templates/twitter_api/remote_follow/follow_login.html.eex b/lib/pleroma/web/templates/twitter_api/remote_follow/follow_login.html.eex
index 26340a9..26340a9 100755..100644
--- a/lib/pleroma/web/templates/twitter_api/remote_follow/follow_login.html.eex
+++ b/lib/pleroma/web/templates/twitter_api/remote_follow/follow_login.html.eex
diff --git a/lib/pleroma/web/templates/twitter_api/remote_follow/follow_mfa.html.eex b/lib/pleroma/web/templates/twitter_api/remote_follow/follow_mfa.html.eex
index 638212c..638212c 100755..100644
--- a/lib/pleroma/web/templates/twitter_api/remote_follow/follow_mfa.html.eex
+++ b/lib/pleroma/web/templates/twitter_api/remote_follow/follow_mfa.html.eex
diff --git a/lib/pleroma/web/templates/twitter_api/remote_follow/followed.html.eex b/lib/pleroma/web/templates/twitter_api/remote_follow/followed.html.eex
index 2fb4cc5..2fb4cc5 100755..100644
--- a/lib/pleroma/web/templates/twitter_api/remote_follow/followed.html.eex
+++ b/lib/pleroma/web/templates/twitter_api/remote_follow/followed.html.eex
diff --git a/lib/pleroma/web/templates/twitter_api/util/status_interact.html.eex b/lib/pleroma/web/templates/twitter_api/util/status_interact.html.eex
index d771749..d771749 100755..100644
--- a/lib/pleroma/web/templates/twitter_api/util/status_interact.html.eex
+++ b/lib/pleroma/web/templates/twitter_api/util/status_interact.html.eex
diff --git a/lib/pleroma/web/templates/twitter_api/util/subscribe.html.eex b/lib/pleroma/web/templates/twitter_api/util/subscribe.html.eex
index 848660f..848660f 100755..100644
--- a/lib/pleroma/web/templates/twitter_api/util/subscribe.html.eex
+++ b/lib/pleroma/web/templates/twitter_api/util/subscribe.html.eex
diff --git a/lib/pleroma/web/translation_helpers.ex b/lib/pleroma/web/translation_helpers.ex
index e9638b0..e9638b0 100755..100644
--- a/lib/pleroma/web/translation_helpers.ex
+++ b/lib/pleroma/web/translation_helpers.ex
diff --git a/lib/pleroma/web/twitter_api/controller.ex b/lib/pleroma/web/twitter_api/controller.ex
index 6db3d60..6db3d60 100755..100644
--- a/lib/pleroma/web/twitter_api/controller.ex
+++ b/lib/pleroma/web/twitter_api/controller.ex
diff --git a/lib/pleroma/web/twitter_api/controllers/password_controller.ex b/lib/pleroma/web/twitter_api/controllers/password_controller.ex
index 31b7dd7..e5482de 100755..100644
--- a/lib/pleroma/web/twitter_api/controllers/password_controller.ex
+++ b/lib/pleroma/web/twitter_api/controllers/password_controller.ex
@@ -4,7 +4,7 @@
defmodule Pleroma.Web.TwitterAPI.PasswordController do
@moduledoc """
- The module containts functions for reset password.
+ The module contains functions for password reset.
"""
use Pleroma.Web, :controller
diff --git a/lib/pleroma/web/twitter_api/controllers/remote_follow_controller.ex b/lib/pleroma/web/twitter_api/controllers/remote_follow_controller.ex
index 6229d5d..1557d95 100755..100644
--- a/lib/pleroma/web/twitter_api/controllers/remote_follow_controller.ex
+++ b/lib/pleroma/web/twitter_api/controllers/remote_follow_controller.ex
@@ -29,7 +29,7 @@ defmodule Pleroma.Web.TwitterAPI.RemoteFollowController do
# GET /ostatus_subscribe
#
def follow(%{assigns: %{user: user}} = conn, %{"acct" => acct}) do
- case is_status?(acct) do
+ case status?(acct) do
true -> follow_status(conn, user, acct)
_ -> follow_account(conn, user, acct)
end
@@ -57,7 +57,7 @@ defmodule Pleroma.Web.TwitterAPI.RemoteFollowController do
defp follow_template(%User{} = _user), do: "follow.html"
defp follow_template(_), do: "follow_login.html"
- defp is_status?(acct) do
+ defp status?(acct) do
case Fetcher.fetch_and_contain_remote_object_from_id(acct) do
{:ok, %{"type" => type}} when type in @status_types ->
true
@@ -121,6 +121,13 @@ defmodule Pleroma.Web.TwitterAPI.RemoteFollowController do
render(conn, "followed.html", %{error: "Insufficient permissions: follow | write:follows."})
end
+ # GET /authorize_interaction
+ #
+ def authorize_interaction(conn, %{"uri" => uri}) do
+ conn
+ |> redirect(to: Routes.remote_follow_path(conn, :follow, %{acct: uri}))
+ end
+
defp handle_follow_error(conn, {:mfa_token, followee, _} = _) do
render(conn, "follow_login.html", %{error: "Wrong username or password", followee: followee})
end
diff --git a/lib/pleroma/web/twitter_api/controllers/util_controller.ex b/lib/pleroma/web/twitter_api/controllers/util_controller.ex
index d5a24ae..040fa32 100755..100644
--- a/lib/pleroma/web/twitter_api/controllers/util_controller.ex
+++ b/lib/pleroma/web/twitter_api/controllers/util_controller.ex
@@ -18,7 +18,8 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
alias Pleroma.Web.WebFinger
plug(
- Pleroma.Web.ApiSpec.CastAndValidate
+ Pleroma.Web.ApiSpec.CastAndValidate,
+ [replace_params: false]
when action != :remote_subscribe and action != :show_subscribe_form
)
@@ -35,7 +36,7 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
:change_email,
:change_password,
:delete_account,
- :update_notificaton_settings,
+ :update_notification_settings,
:disable_account,
:move_account,
:add_alias,
@@ -150,7 +151,10 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
end
end
- def remote_interaction(%{body_params: %{ap_id: ap_id, profile: profile}} = conn, _params) do
+ def remote_interaction(
+ %{private: %{open_api_spex: %{body_params: %{ap_id: ap_id, profile: profile}}}} = conn,
+ _params
+ ) do
with {:ok, %{"subscribe_address" => template}} <- WebFinger.finger(profile) do
conn
|> json(%{url: String.replace(template, "{uri}", ap_id)})
@@ -181,13 +185,16 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
json(conn, emoji)
end
- def update_notificaton_settings(%{assigns: %{user: user}} = conn, params) do
+ def update_notification_settings(%{assigns: %{user: user}} = conn, params) do
with {:ok, _} <- User.update_notification_settings(user, params) do
json(conn, %{status: "success"})
end
end
- def change_password(%{assigns: %{user: user}, body_params: body_params} = conn, %{}) do
+ def change_password(
+ %{assigns: %{user: user}, private: %{open_api_spex: %{body_params: body_params}}} = conn,
+ _
+ ) do
case CommonAPI.Utils.confirm_current_password(user, body_params.password) do
{:ok, user} ->
with {:ok, _user} <-
@@ -210,7 +217,10 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
end
end
- def change_email(%{assigns: %{user: user}, body_params: body_params} = conn, %{}) do
+ def change_email(
+ %{assigns: %{user: user}, private: %{open_api_spex: %{body_params: body_params}}} = conn,
+ _
+ ) do
case CommonAPI.Utils.confirm_current_password(user, body_params.password) do
{:ok, user} ->
with {:ok, _user} <- User.change_email(user, body_params.email) do
@@ -229,7 +239,13 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
end
end
- def delete_account(%{assigns: %{user: user}, body_params: body_params} = conn, params) do
+ def delete_account(
+ %{
+ assigns: %{user: user},
+ private: %{open_api_spex: %{body_params: body_params, params: params}}
+ } = conn,
+ _
+ ) do
# This endpoint can accept a query param or JSON body for backwards-compatibility.
# Submitting a JSON body is recommended, so passwords don't end up in server logs.
password = body_params[:password] || params[:password] || ""
@@ -244,7 +260,10 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
end
end
- def disable_account(%{assigns: %{user: user}} = conn, params) do
+ def disable_account(
+ %{assigns: %{user: user}, private: %{open_api_spex: %{params: params}}} = conn,
+ _
+ ) do
case CommonAPI.Utils.confirm_current_password(user, params[:password]) do
{:ok, user} ->
User.set_activation_async(user, false)
@@ -255,7 +274,10 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
end
end
- def move_account(%{assigns: %{user: user}, body_params: body_params} = conn, %{}) do
+ def move_account(
+ %{assigns: %{user: user}, private: %{open_api_spex: %{body_params: body_params}}} = conn,
+ _
+ ) do
case CommonAPI.Utils.confirm_current_password(user, body_params.password) do
{:ok, user} ->
with {:ok, target_user} <- find_or_fetch_user_by_nickname(body_params.target_account),
@@ -276,7 +298,10 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
end
end
- def add_alias(%{assigns: %{user: user}, body_params: body_params} = conn, _) do
+ def add_alias(
+ %{assigns: %{user: user}, private: %{open_api_spex: %{body_params: body_params}}} = conn,
+ _
+ ) do
with {:ok, alias_user} <- find_user_by_nickname(body_params.alias),
{:ok, _user} <- user |> User.add_alias(alias_user) do
json(conn, %{status: "success"})
@@ -291,7 +316,10 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
end
end
- def delete_alias(%{assigns: %{user: user}, body_params: body_params} = conn, _) do
+ def delete_alias(
+ %{assigns: %{user: user}, private: %{open_api_spex: %{body_params: body_params}}} = conn,
+ _
+ ) do
with {:ok, alias_user} <- find_user_by_nickname(body_params.alias),
{:ok, _user} <- user |> User.delete_alias(alias_user) do
json(conn, %{status: "success"})
@@ -306,7 +334,7 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
end
end
- def list_aliases(%{assigns: %{user: user}} = conn, %{}) do
+ def list_aliases(%{assigns: %{user: user}} = conn, _) do
alias_nicks =
user
|> User.alias_users()
@@ -319,7 +347,7 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
user = User.get_cached_by_nickname(nickname)
if user == nil do
- {:not_found, nil}
+ {:error, :not_found}
else
{:ok, user}
end
@@ -345,13 +373,16 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
end
def healthcheck(conn, _params) do
- with true <- Config.get([:instance, :healthcheck]),
+ with {:cfg, true} <- {:cfg, Config.get([:instance, :healthcheck])},
%{healthy: true} = info <- Healthcheck.system_info() do
json(conn, info)
else
%{healthy: false} = info ->
service_unavailable(conn, info)
+ {:cfg, false} ->
+ service_unavailable(conn, %{"error" => "Healthcheck disabled"})
+
_ ->
service_unavailable(conn, %{})
end
diff --git a/lib/pleroma/web/twitter_api/twitter_api.ex b/lib/pleroma/web/twitter_api/twitter_api.ex
index ef2eb75..ef2eb75 100755..100644
--- a/lib/pleroma/web/twitter_api/twitter_api.ex
+++ b/lib/pleroma/web/twitter_api/twitter_api.ex
diff --git a/lib/pleroma/web/twitter_api/views/password_view.ex b/lib/pleroma/web/twitter_api/views/password_view.ex
index 5579094..5579094 100755..100644
--- a/lib/pleroma/web/twitter_api/views/password_view.ex
+++ b/lib/pleroma/web/twitter_api/views/password_view.ex
diff --git a/lib/pleroma/web/twitter_api/views/remote_follow_view.ex b/lib/pleroma/web/twitter_api/views/remote_follow_view.ex
index 8902261..8902261 100755..100644
--- a/lib/pleroma/web/twitter_api/views/remote_follow_view.ex
+++ b/lib/pleroma/web/twitter_api/views/remote_follow_view.ex
diff --git a/lib/pleroma/web/twitter_api/views/token_view.ex b/lib/pleroma/web/twitter_api/views/token_view.ex
index 2e492c1..2e492c1 100755..100644
--- a/lib/pleroma/web/twitter_api/views/token_view.ex
+++ b/lib/pleroma/web/twitter_api/views/token_view.ex
diff --git a/lib/pleroma/web/twitter_api/views/util_view.ex b/lib/pleroma/web/twitter_api/views/util_view.ex
index 31b7c0c..31b7c0c 100755..100644
--- a/lib/pleroma/web/twitter_api/views/util_view.ex
+++ b/lib/pleroma/web/twitter_api/views/util_view.ex
diff --git a/lib/pleroma/web/uploader_controller.ex b/lib/pleroma/web/uploader_controller.ex
index d5c8049..d5c8049 100755..100644
--- a/lib/pleroma/web/uploader_controller.ex
+++ b/lib/pleroma/web/uploader_controller.ex
diff --git a/lib/pleroma/web/utils/guards.ex b/lib/pleroma/web/utils/guards.ex
index 8a61421..8a61421 100755..100644
--- a/lib/pleroma/web/utils/guards.ex
+++ b/lib/pleroma/web/utils/guards.ex
diff --git a/lib/pleroma/web/utils/params.ex b/lib/pleroma/web/utils/params.ex
index 636e3de..636e3de 100755..100644
--- a/lib/pleroma/web/utils/params.ex
+++ b/lib/pleroma/web/utils/params.ex
diff --git a/lib/pleroma/web/views/email_view.ex b/lib/pleroma/web/views/email_view.ex
index 9ab7082..9ab7082 100755..100644
--- a/lib/pleroma/web/views/email_view.ex
+++ b/lib/pleroma/web/views/email_view.ex
diff --git a/lib/pleroma/web/views/embed_view.ex b/lib/pleroma/web/views/embed_view.ex
index 1bfd8c5..1bfd8c5 100755..100644
--- a/lib/pleroma/web/views/embed_view.ex
+++ b/lib/pleroma/web/views/embed_view.ex
diff --git a/lib/pleroma/web/views/error_helpers.ex b/lib/pleroma/web/views/error_helpers.ex
index fd85f7c..fd85f7c 100755..100644
--- a/lib/pleroma/web/views/error_helpers.ex
+++ b/lib/pleroma/web/views/error_helpers.ex
diff --git a/lib/pleroma/web/views/error_view.ex b/lib/pleroma/web/views/error_view.ex
index 9ab1632..9ab1632 100755..100644
--- a/lib/pleroma/web/views/error_view.ex
+++ b/lib/pleroma/web/views/error_view.ex
diff --git a/lib/pleroma/web/views/layout_view.ex b/lib/pleroma/web/views/layout_view.ex
index 3161bb1..3161bb1 100755..100644
--- a/lib/pleroma/web/views/layout_view.ex
+++ b/lib/pleroma/web/views/layout_view.ex
diff --git a/lib/pleroma/web/views/mailer/subscription_view.ex b/lib/pleroma/web/views/mailer/subscription_view.ex
index 037fb65..037fb65 100755..100644
--- a/lib/pleroma/web/views/mailer/subscription_view.ex
+++ b/lib/pleroma/web/views/mailer/subscription_view.ex
diff --git a/lib/pleroma/web/views/manifest_view.ex b/lib/pleroma/web/views/manifest_view.ex
index 2ae8219..2ae8219 100755..100644
--- a/lib/pleroma/web/views/manifest_view.ex
+++ b/lib/pleroma/web/views/manifest_view.ex
diff --git a/lib/pleroma/web/views/streamer_view.ex b/lib/pleroma/web/views/streamer_view.ex
index 6a55242..f97570b 100755..100644
--- a/lib/pleroma/web/views/streamer_view.ex
+++ b/lib/pleroma/web/views/streamer_view.ex
@@ -11,8 +11,11 @@ defmodule Pleroma.Web.StreamerView do
alias Pleroma.User
alias Pleroma.Web.MastodonAPI.NotificationView
- def render("update.json", %Activity{} = activity, %User{} = user) do
+ require Pleroma.Constants
+
+ def render("update.json", %Activity{} = activity, %User{} = user, topic) do
%{
+ stream: render("stream.json", %{topic: topic}),
event: "update",
payload:
Pleroma.Web.MastodonAPI.StatusView.render(
@@ -25,8 +28,9 @@ defmodule Pleroma.Web.StreamerView do
|> Jason.encode!()
end
- def render("status_update.json", %Activity{} = activity, %User{} = user) do
+ def render("status_update.json", %Activity{} = activity, %User{} = user, topic) do
%{
+ stream: render("stream.json", %{topic: topic}),
event: "status.update",
payload:
Pleroma.Web.MastodonAPI.StatusView.render(
@@ -39,8 +43,9 @@ defmodule Pleroma.Web.StreamerView do
|> Jason.encode!()
end
- def render("notification.json", %Notification{} = notify, %User{} = user) do
+ def render("notification.json", %Notification{} = notify, %User{} = user, topic) do
%{
+ stream: render("stream.json", %{topic: topic}),
event: "notification",
payload:
NotificationView.render(
@@ -52,8 +57,9 @@ defmodule Pleroma.Web.StreamerView do
|> Jason.encode!()
end
- def render("update.json", %Activity{} = activity) do
+ def render("update.json", %Activity{} = activity, topic) do
%{
+ stream: render("stream.json", %{topic: topic}),
event: "update",
payload:
Pleroma.Web.MastodonAPI.StatusView.render(
@@ -65,8 +71,9 @@ defmodule Pleroma.Web.StreamerView do
|> Jason.encode!()
end
- def render("status_update.json", %Activity{} = activity) do
+ def render("status_update.json", %Activity{} = activity, topic) do
%{
+ stream: render("stream.json", %{topic: topic}),
event: "status.update",
payload:
Pleroma.Web.MastodonAPI.StatusView.render(
@@ -78,7 +85,7 @@ defmodule Pleroma.Web.StreamerView do
|> Jason.encode!()
end
- def render("chat_update.json", %{chat_message_reference: cm_ref}) do
+ def render("chat_update.json", %{chat_message_reference: cm_ref}, topic) do
# Explicitly giving the cmr for the object here, so we don't accidentally
# send a later 'last_message' that was inserted between inserting this and
# streaming it out
@@ -93,6 +100,7 @@ defmodule Pleroma.Web.StreamerView do
)
%{
+ stream: render("stream.json", %{topic: topic}),
event: "pleroma:chat_update",
payload:
representation
@@ -101,8 +109,9 @@ defmodule Pleroma.Web.StreamerView do
|> Jason.encode!()
end
- def render("follow_relationships_update.json", item) do
+ def render("follow_relationships_update.json", item, topic) do
%{
+ stream: render("stream.json", %{topic: topic}),
event: "pleroma:follow_relationships_update",
payload:
%{
@@ -123,8 +132,9 @@ defmodule Pleroma.Web.StreamerView do
|> Jason.encode!()
end
- def render("conversation.json", %Participation{} = participation) do
+ def render("conversation.json", %Participation{} = participation, topic) do
%{
+ stream: render("stream.json", %{topic: topic}),
event: "conversation",
payload:
Pleroma.Web.MastodonAPI.ConversationView.render("participation.json", %{
@@ -135,4 +145,39 @@ defmodule Pleroma.Web.StreamerView do
}
|> Jason.encode!()
end
+
+ def render("pleroma_respond.json", %{type: type, result: result} = params) do
+ %{
+ event: "pleroma:respond",
+ payload:
+ %{
+ result: result,
+ type: type
+ }
+ |> Map.merge(maybe_error(params))
+ |> Jason.encode!()
+ }
+ |> Jason.encode!()
+ end
+
+ def render("stream.json", %{topic: "user:pleroma_chat:" <> _}), do: ["user:pleroma_chat"]
+ def render("stream.json", %{topic: "user:notification:" <> _}), do: ["user:notification"]
+ def render("stream.json", %{topic: "user:" <> _}), do: ["user"]
+ def render("stream.json", %{topic: "direct:" <> _}), do: ["direct"]
+ def render("stream.json", %{topic: "list:" <> id}), do: ["list", id]
+ def render("stream.json", %{topic: "hashtag:" <> tag}), do: ["hashtag", tag]
+
+ def render("stream.json", %{topic: "public:remote:media:" <> instance}),
+ do: ["public:remote:media", instance]
+
+ def render("stream.json", %{topic: "public:remote:" <> instance}),
+ do: ["public:remote", instance]
+
+ def render("stream.json", %{topic: stream}) when stream in Pleroma.Constants.public_streams(),
+ do: [stream]
+
+ defp maybe_error(%{error: :bad_topic}), do: %{error: "bad_topic"}
+ defp maybe_error(%{error: :unauthorized}), do: %{error: "unauthorized"}
+ defp maybe_error(%{error: :already_authenticated}), do: %{error: "already_authenticated"}
+ defp maybe_error(_), do: %{}
end
diff --git a/lib/pleroma/web/web_finger.ex b/lib/pleroma/web/web_finger.ex
index f95dc24..26fb8af 100755..100644
--- a/lib/pleroma/web/web_finger.ex
+++ b/lib/pleroma/web/web_finger.ex
@@ -5,8 +5,8 @@
defmodule Pleroma.Web.WebFinger do
alias Pleroma.HTTP
alias Pleroma.User
+ alias Pleroma.Web.ActivityPub.Publisher
alias Pleroma.Web.Endpoint
- alias Pleroma.Web.Federator.Publisher
alias Pleroma.Web.XML
alias Pleroma.XmlBuilder
require Jason
@@ -70,7 +70,7 @@ defmodule Pleroma.Web.WebFinger do
def represent_user(user, "JSON") do
%{
- "subject" => "acct:#{user.nickname}@#{domain()}",
+ "subject" => "acct:#{user.nickname}@#{host()}",
"aliases" => gather_aliases(user),
"links" => gather_links(user)
}
@@ -90,13 +90,13 @@ defmodule Pleroma.Web.WebFinger do
:XRD,
%{xmlns: "http://docs.oasis-open.org/ns/xri/xrd-1.0"},
[
- {:Subject, "acct:#{user.nickname}@#{domain()}"}
+ {:Subject, "acct:#{user.nickname}@#{host()}"}
] ++ aliases ++ links
}
|> XmlBuilder.to_doc()
end
- defp domain do
+ def host do
Pleroma.Config.get([__MODULE__, :domain]) || Pleroma.Web.Endpoint.host()
end
@@ -163,7 +163,7 @@ defmodule Pleroma.Web.WebFinger do
get_template_from_xml(body)
else
error ->
- Logger.warn("Can't find LRDD template in #{inspect(meta_url)}: #{inspect(error)}")
+ Logger.warning("Can't find LRDD template in #{inspect(meta_url)}: #{inspect(error)}")
{:error, :lrdd_not_found}
end
end
diff --git a/lib/pleroma/web/web_finger/web_finger_controller.ex b/lib/pleroma/web/web_finger/web_finger_controller.ex
index 9e5efb7..021df9b 100755..100644
--- a/lib/pleroma/web/web_finger/web_finger_controller.ex
+++ b/lib/pleroma/web/web_finger/web_finger_controller.ex
@@ -30,7 +30,7 @@ defmodule Pleroma.Web.WebFinger.WebFingerController do
end
def webfinger(%{assigns: %{format: format}} = conn, %{"resource" => resource})
- when format in ["json", "jrd+json"] do
+ when format in ["jrd", "json", "jrd+json"] do
with {:ok, response} <- WebFinger.webfinger(resource, "JSON") do
json(conn, response)
else
diff --git a/lib/pleroma/web/xml.ex b/lib/pleroma/web/xml.ex
index 380a80a..64329e4 100755..100644
--- a/lib/pleroma/web/xml.ex
+++ b/lib/pleroma/web/xml.ex
@@ -31,7 +31,7 @@ defmodule Pleroma.Web.XML do
|> :binary.bin_to_list()
|> :xmerl_scan.string(
quiet: true,
- fetch_fun: fn _, _ -> raise "Resolving external entities not supported" end
+ allow_entities: false
)
{:ok, doc}