Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/diaspora/diaspora.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Neff <benjamin@coding4coffee.ch>2017-08-19 23:34:33 +0300
committerBenjamin Neff <benjamin@coding4coffee.ch>2017-08-19 23:38:38 +0300
commit7153df5c86a770776894a55c4c41973d043033ad (patch)
tree3a78cc4ea244d95a2cd7623c4be0e0f2dd402168
parent8bed8a84a336d51a7983636eab9670d85fdd1fc5 (diff)
parentbf47e1bc931eaa23bd98b2fb559e80a226f478d9 (diff)
Merge branch 'release/0.7.0.0'v0.7.0.0
-rw-r--r--.gitignore23
-rw-r--r--.rubocop.yml12
-rw-r--r--.ruby-version2
-rw-r--r--.travis.yml7
-rw-r--r--CONTRIBUTING.md42
-rw-r--r--Changelog.md60
-rw-r--r--Gemfile151
-rw-r--r--Gemfile.lock626
-rw-r--r--app/assets/javascripts/app/app.js6
-rw-r--r--app/assets/javascripts/app/models/post.js6
-rw-r--r--app/assets/javascripts/app/models/post/interactions.js35
-rw-r--r--app/assets/javascripts/app/models/stream.js12
-rw-r--r--app/assets/javascripts/app/pages/single-post-viewer.js5
-rw-r--r--app/assets/javascripts/app/router.js8
-rw-r--r--app/assets/javascripts/app/views/comment_mention_view.js10
-rw-r--r--app/assets/javascripts/app/views/comment_stream_view.js60
-rw-r--r--app/assets/javascripts/app/views/comment_view.js3
-rw-r--r--app/assets/javascripts/app/views/content_view.js7
-rw-r--r--app/assets/javascripts/app/views/conversations_form_view.js13
-rw-r--r--app/assets/javascripts/app/views/conversations_inbox_view.js16
-rw-r--r--app/assets/javascripts/app/views/help_view.js31
-rw-r--r--app/assets/javascripts/app/views/infinite_stream_view.js6
-rw-r--r--app/assets/javascripts/app/views/notification_dropdown_view.js1
-rw-r--r--app/assets/javascripts/app/views/preview_post_view.js11
-rw-r--r--app/assets/javascripts/app/views/publisher/mention_view.js85
-rw-r--r--app/assets/javascripts/app/views/publisher_view.js56
-rw-r--r--app/assets/javascripts/app/views/single-post-viewer/single_post_comment_stream.js7
-rw-r--r--app/assets/javascripts/app/views/single-post-viewer/single_post_interaction_counts.js29
-rw-r--r--app/assets/javascripts/helpers/markdown_editor.js15
-rw-r--r--app/assets/javascripts/jasmine-load-all.js2
-rw-r--r--app/assets/javascripts/jsxc.js2
-rw-r--r--app/assets/javascripts/main.js8
-rw-r--r--app/assets/javascripts/mobile/mobile.js6
-rw-r--r--app/assets/javascripts/mobile/mobile_comments.js4
-rw-r--r--app/assets/javascripts/mobile/mobile_conversations.js1
-rw-r--r--app/assets/javascripts/mobile/mobile_file_uploader.js1
-rw-r--r--app/assets/javascripts/mobile/mobile_post_actions.js8
-rw-r--r--app/assets/javascripts/mobile/publisher.js2
-rw-r--r--app/assets/stylesheets/_application.scss1
-rw-r--r--app/assets/stylesheets/base.scss2
-rw-r--r--app/assets/stylesheets/bootstrap-complete.scss2
-rw-r--r--app/assets/stylesheets/color_themes/_color_theme_override_dark.scss17
-rw-r--r--app/assets/stylesheets/color_themes/dark/_style.scss3
-rw-r--r--app/assets/stylesheets/comments.scss26
-rw-r--r--app/assets/stylesheets/conversations.scss6
-rw-r--r--app/assets/stylesheets/header.scss244
-rw-r--r--app/assets/stylesheets/markdown-editor.scss20
-rw-r--r--app/assets/stylesheets/mentions.scss91
-rw-r--r--app/assets/stylesheets/mobile/comments.scss12
-rw-r--r--app/assets/stylesheets/mobile/header.scss13
-rw-r--r--app/assets/stylesheets/mobile/markdown_editor.scss6
-rw-r--r--app/assets/stylesheets/mobile/mobile.scss44
-rw-r--r--app/assets/stylesheets/publisher.scss41
-rw-r--r--app/assets/stylesheets/single-post-view.scss11
-rw-r--r--app/assets/stylesheets/typeahead.scss18
-rw-r--r--app/assets/templates/comment-stream_tpl.jst.hbs13
-rw-r--r--app/assets/templates/faq_getting_help_tpl.jst.hbs1
-rw-r--r--app/assets/templates/faq_posts_and_posting_tpl.jst.hbs6
-rw-r--r--app/assets/templates/feedback_tpl.jst.hbs30
-rw-r--r--app/assets/templates/header_tpl.jst.hbs55
-rw-r--r--app/assets/templates/help_tpl.jst.hbs12
-rw-r--r--app/assets/templates/single-post-viewer/single-post-interaction-counts_tpl.jst.hbs12
-rw-r--r--app/assets/templates/stream-element_tpl.jst.hbs51
-rw-r--r--app/controllers/admin/admin_controller.rb6
-rw-r--r--app/controllers/api/openid_connect/authorizations_controller.rb2
-rw-r--r--app/controllers/api/openid_connect/discovery_controller.rb11
-rw-r--r--app/controllers/api/openid_connect/token_endpoint_controller.rb3
-rw-r--r--app/controllers/application_controller.rb2
-rw-r--r--app/controllers/aspect_memberships_controller.rb31
-rw-r--r--app/controllers/aspects_controller.rb8
-rw-r--r--app/controllers/blocks_controller.rb32
-rw-r--r--app/controllers/comments_controller.rb20
-rw-r--r--app/controllers/conversations_controller.rb6
-rw-r--r--app/controllers/home_controller.rb2
-rw-r--r--app/controllers/invitations_controller.rb6
-rw-r--r--app/controllers/likes_controller.rb8
-rw-r--r--app/controllers/messages_controller.rb8
-rw-r--r--app/controllers/node_info_controller.rb5
-rw-r--r--app/controllers/notifications_controller.rb21
-rw-r--r--app/controllers/participations_controller.rb8
-rw-r--r--app/controllers/people_controller.rb10
-rw-r--r--app/controllers/photos_controller.rb25
-rw-r--r--app/controllers/poll_participations_controller.rb9
-rw-r--r--app/controllers/posts_controller.rb26
-rw-r--r--app/controllers/profiles_controller.rb4
-rw-r--r--app/controllers/report_controller.rb2
-rw-r--r--app/controllers/reshares_controller.rb4
-rw-r--r--app/controllers/search_controller.rb12
-rw-r--r--app/controllers/sessions_controller.rb4
-rw-r--r--app/controllers/status_messages_controller.rb30
-rw-r--r--app/controllers/tag_followings_controller.rb8
-rw-r--r--app/controllers/tags_controller.rb4
-rw-r--r--app/controllers/users_controller.rb15
-rw-r--r--app/helpers/analytics_helper.rb69
-rw-r--r--app/helpers/application_helper.rb8
-rw-r--r--app/helpers/interim_stream_hackiness_helper.rb10
-rw-r--r--app/helpers/meta_data_helper.rb2
-rw-r--r--app/helpers/mobile_helper.rb34
-rw-r--r--app/helpers/notifications_helper.rb56
-rw-r--r--app/helpers/users_helper.rb8
-rw-r--r--app/mailers/application_mailer.rb3
-rw-r--r--app/mailers/diaspora_devise_mailer.rb2
-rw-r--r--app/mailers/export_mailer.rb4
-rw-r--r--app/mailers/maintenance.rb4
-rw-r--r--app/mailers/notification_mailers/also_commented.rb1
-rw-r--r--app/mailers/notification_mailers/base.rb7
-rw-r--r--app/mailers/notification_mailers/comment_on_post.rb1
-rw-r--r--app/mailers/notification_mailers/mentioned.rb2
-rw-r--r--app/mailers/notification_mailers/mentioned_in_comment.rb12
-rw-r--r--app/mailers/notification_mailers/private_message.rb3
-rw-r--r--app/mailers/notification_mailers/started_sharing.rb4
-rw-r--r--app/mailers/notifier.rb48
-rw-r--r--app/mailers/report_mailer.rb4
-rw-r--r--app/models/account_deletion.rb20
-rw-r--r--app/models/account_migration.rb165
-rw-r--r--app/models/api/openid_connect/authorization.rb5
-rw-r--r--app/models/api/openid_connect/o_auth_access_token.rb3
-rw-r--r--app/models/api/openid_connect/o_auth_application.rb2
-rw-r--r--app/models/api/openid_connect/pairwise_pseudonymous_identifier.rb5
-rw-r--r--app/models/application_record.rb3
-rw-r--r--app/models/aspect.rb2
-rw-r--r--app/models/aspect_membership.rb2
-rw-r--r--app/models/aspect_visibility.rb4
-rw-r--r--app/models/block.rb5
-rw-r--r--app/models/comment.rb14
-rw-r--r--app/models/comment_signature.rb3
-rw-r--r--app/models/contact.rb5
-rw-r--r--app/models/conversation.rb2
-rw-r--r--app/models/conversation_visibility.rb4
-rw-r--r--app/models/invitation_code.rb4
-rw-r--r--app/models/like.rb2
-rw-r--r--app/models/like_signature.rb3
-rw-r--r--app/models/location.rb2
-rw-r--r--app/models/mention.rb10
-rw-r--r--app/models/message.rb12
-rw-r--r--app/models/notification.rb13
-rw-r--r--app/models/notification_actor.rb2
-rw-r--r--app/models/notifications/also_commented.rb8
-rw-r--r--app/models/notifications/comment_on_post.rb7
-rw-r--r--app/models/notifications/commented.rb15
-rw-r--r--app/models/notifications/mentioned.rb35
-rw-r--r--app/models/notifications/mentioned_in_comment.rb33
-rw-r--r--app/models/notifications/mentioned_in_post.rb22
-rw-r--r--app/models/o_embed_cache.rb2
-rw-r--r--app/models/open_graph_cache.rb2
-rw-r--r--app/models/participation.rb2
-rw-r--r--app/models/person.rb118
-rw-r--r--app/models/photo.rb4
-rw-r--r--app/models/pod.rb2
-rw-r--r--app/models/poll.rb2
-rw-r--r--app/models/poll_answer.rb2
-rw-r--r--app/models/poll_participation.rb4
-rw-r--r--app/models/poll_participation_signature.rb3
-rw-r--r--app/models/post.rb23
-rw-r--r--app/models/profile.rb11
-rw-r--r--app/models/report.rb6
-rw-r--r--app/models/reshare.rb2
-rw-r--r--app/models/role.rb3
-rw-r--r--app/models/service.rb2
-rw-r--r--app/models/share_visibility.rb4
-rw-r--r--app/models/signature_order.rb2
-rw-r--r--app/models/status_message.rb52
-rw-r--r--app/models/tag_following.rb2
-rw-r--r--app/models/user.rb46
-rw-r--r--app/models/user/connecting.rb2
-rw-r--r--app/models/user_preference.rb17
-rw-r--r--app/presenters/comment_presenter.rb11
-rw-r--r--app/presenters/extreme_post_presenter.rb14
-rw-r--r--app/presenters/person_presenter.rb4
-rw-r--r--app/presenters/post_presenter.rb14
-rw-r--r--app/presenters/statistics_presenter.rb49
-rw-r--r--app/serializers/export/comment_serializer.rb11
-rw-r--r--app/serializers/export/contact_serializer.rb28
-rw-r--r--app/serializers/export/others_data_serializer.rb34
-rw-r--r--app/serializers/export/own_post_serializer.rb33
-rw-r--r--app/serializers/export/own_relayables_serializer.rb13
-rw-r--r--app/serializers/export/person_metadata_serializer.rb17
-rw-r--r--app/serializers/export/post_serializer.rb13
-rw-r--r--app/serializers/export/profile_serializer.rb14
-rw-r--r--app/serializers/export/user_serializer.rb43
-rw-r--r--app/serializers/federation_entity_serializer.rb16
-rw-r--r--app/serializers/serializer_post_processing.rb20
-rw-r--r--app/services/notification_service.rb4
-rw-r--r--app/services/post_service.rb29
-rw-r--r--app/services/status_message_creation_service.rb15
-rw-r--r--app/uploaders/exported_user.rb6
-rw-r--r--app/uploaders/processed_image.rb4
-rw-r--r--app/uploaders/unprocessed_image.rb8
-rw-r--r--app/views/application/_head.haml4
-rw-r--r--app/views/comments/_comment.mobile.haml2
-rw-r--r--app/views/comments/_new_comment.mobile.haml2
-rw-r--r--app/views/comments/_post_stats.mobile.haml15
-rw-r--r--app/views/layouts/_header.html.haml17
-rw-r--r--app/views/layouts/_header.mobile.haml2
-rw-r--r--app/views/layouts/_header_not_connected.haml3
-rw-r--r--app/views/layouts/application.html.haml5
-rw-r--r--app/views/layouts/application.mobile.haml3
-rw-r--r--app/views/notifications/_notification.haml4
-rw-r--r--app/views/notifications/_notification.mobile.haml3
-rw-r--r--app/views/notifications/index.html.haml2
-rw-r--r--app/views/notifier/invite.markerb7
-rw-r--r--app/views/notifier/mentioned.markerb2
-rw-r--r--app/views/notifier/mentioned_in_comment.markerb9
-rw-r--r--app/views/publisher/_publisher.html.haml25
-rw-r--r--app/views/users/_edit.haml5
-rw-r--r--app/views/users/privacy_settings.mobile.haml4
-rw-r--r--app/workers/deferred_dispatch.rb2
-rw-r--r--app/workers/deferred_retraction.rb6
-rw-r--r--app/workers/delete_post_from_service.rb2
-rw-r--r--app/workers/mail/also_commented.rb9
-rw-r--r--app/workers/mail/comment_on_post.rb7
-rw-r--r--app/workers/mail/confirm_email.rb7
-rw-r--r--app/workers/mail/csrf_token_fail.rb7
-rw-r--r--app/workers/mail/liked.rb8
-rw-r--r--app/workers/mail/mentioned.rb7
-rw-r--r--app/workers/mail/mentioned_in_comment.rb6
-rw-r--r--app/workers/mail/notifier_base.rb11
-rw-r--r--app/workers/mail/private_message.rb7
-rw-r--r--app/workers/mail/reshared.rb7
-rw-r--r--app/workers/mail/started_sharing.rb7
-rw-r--r--app/workers/receive_base.rb2
-rwxr-xr-xbin/rails6
-rw-r--r--config/application.rb28
-rw-r--r--config/boot.rb9
-rw-r--r--config/color_themes.yml12
-rw-r--r--config/defaults.yml4
-rw-r--r--config/diaspora.yml.example6
-rw-r--r--config/environment.rb6
-rw-r--r--config/environments/development.rb52
-rw-r--r--config/environments/production.rb87
-rw-r--r--config/environments/test.rb42
-rw-r--r--config/initializers/application_controller_renderer.rb6
-rw-r--r--config/initializers/assets.rb29
-rw-r--r--config/initializers/backtrace_silencers.rb7
-rw-r--r--config/initializers/color_themes.rb8
-rw-r--r--config/initializers/cookies_serializer.rb5
-rw-r--r--config/initializers/cors.rb10
-rw-r--r--config/initializers/diaspora_federation.rb26
-rw-r--r--config/initializers/filter_parameter_logging.rb2
-rw-r--r--config/initializers/inflections.rb16
-rw-r--r--config/initializers/mime_types.rb4
-rw-r--r--config/initializers/secure_headers.rb6
-rw-r--r--config/initializers/wrap_parameters.rb4
-rw-r--r--config/locale_settings.yml5
-rw-r--r--config/locales/devise/devise.oc.yml12
-rw-r--r--config/locales/diaspora/br.yml8
-rw-r--r--config/locales/diaspora/bs.yml5
-rw-r--r--config/locales/diaspora/cs.yml27
-rw-r--r--config/locales/diaspora/da.yml74
-rw-r--r--config/locales/diaspora/de-CH.yml39
-rw-r--r--config/locales/diaspora/de.yml75
-rw-r--r--config/locales/diaspora/de_formal.yml61
-rw-r--r--config/locales/diaspora/el.yml3
-rw-r--r--config/locales/diaspora/en.yml80
-rw-r--r--config/locales/diaspora/en_valspeak.yml23
-rw-r--r--config/locales/diaspora/es-AR.yml41
-rw-r--r--config/locales/diaspora/es-CL.yml23
-rw-r--r--config/locales/diaspora/es-MX.yml23
-rw-r--r--config/locales/diaspora/es.yml97
-rw-r--r--config/locales/diaspora/fi.yml23
-rw-r--r--config/locales/diaspora/fr.yml52
-rw-r--r--config/locales/diaspora/he.yml1
-rw-r--r--config/locales/diaspora/hu.yml40
-rw-r--r--config/locales/diaspora/hy.yml32
-rw-r--r--config/locales/diaspora/ia.yml34
-rw-r--r--config/locales/diaspora/is.yml2
-rw-r--r--config/locales/diaspora/it.yml23
-rw-r--r--config/locales/diaspora/ja.yml58
-rw-r--r--config/locales/diaspora/ko.yml2
-rw-r--r--config/locales/diaspora/ml.yml18
-rw-r--r--config/locales/diaspora/nb.yml23
-rw-r--r--config/locales/diaspora/nds.yml20
-rw-r--r--config/locales/diaspora/nl.yml23
-rw-r--r--config/locales/diaspora/oc.yml217
-rw-r--r--config/locales/diaspora/pl.yml190
-rw-r--r--config/locales/diaspora/pt-BR.yml59
-rw-r--r--config/locales/diaspora/pt-PT.yml19
-rw-r--r--config/locales/diaspora/ru.yml23
-rw-r--r--config/locales/diaspora/sc.yml598
-rw-r--r--config/locales/diaspora/sk.yml11
-rw-r--r--config/locales/diaspora/sv.yml23
-rw-r--r--config/locales/diaspora/te.yml16
-rw-r--r--config/locales/diaspora/tr.yml21
-rw-r--r--config/locales/diaspora/uk.yml57
-rw-r--r--config/locales/diaspora/zh-TW.yml82
-rw-r--r--config/locales/javascript/javascript.da.yml1
-rw-r--r--config/locales/javascript/javascript.de.yml4
-rw-r--r--config/locales/javascript/javascript.de_formal.yml3
-rw-r--r--config/locales/javascript/javascript.en.yml1
-rw-r--r--config/locales/javascript/javascript.es.yml11
-rw-r--r--config/locales/javascript/javascript.fr.yml7
-rw-r--r--config/locales/javascript/javascript.hu.yml1
-rw-r--r--config/locales/javascript/javascript.ja.yml1
-rw-r--r--config/locales/javascript/javascript.oc.yml21
-rw-r--r--config/locales/javascript/javascript.pl.yml20
-rw-r--r--config/locales/javascript/javascript.pt-BR.yml1
-rw-r--r--config/locales/javascript/javascript.sc.yml3
-rw-r--r--config/locales/javascript/javascript.uk.yml3
-rw-r--r--config/locales/javascript/javascript.zh-TW.yml1
-rw-r--r--config/logging.rb8
-rw-r--r--config/routes.rb6
-rw-r--r--config/spring.rb6
-rw-r--r--db/migrate/0000_create_schema.rb978
-rw-r--r--db/migrate/20130207231310_add_facebook_id_to_post.rb2
-rw-r--r--db/migrate/20130404211624_fix_default_image_url_from_profile.rb2
-rw-r--r--db/migrate/20130429073928_add_tweet_id_to_post.rb2
-rw-r--r--db/migrate/20130608171134_add_open_graph_cache.rb2
-rw-r--r--db/migrate/20130613203350_remove_limit_from_root_guid_in_posts.rb2
-rw-r--r--db/migrate/20130717104359_migrate_activity_stream_to_status_message.rb4
-rw-r--r--db/migrate/20130801063213_add_tumblr_post_ids_to_posts.rb2
-rw-r--r--db/migrate/20131017093025_create_post_reports.rb2
-rw-r--r--db/migrate/20131213171804_create_simple_captcha_data.rb2
-rw-r--r--db/migrate/20140121132816_add_post_type_to_post_report.rb2
-rw-r--r--db/migrate/20140214104217_rename_post_report_to_report.rb2
-rw-r--r--db/migrate/20140222162826_devise_add_lastseenable_user.rb2
-rw-r--r--db/migrate/20140308154022_create_polls.rb2
-rw-r--r--db/migrate/20140422134050_rename_post_columns_to_item.rb2
-rw-r--r--db/migrate/20140422134627_change_user_id_type_to_integer.rb2
-rw-r--r--db/migrate/20140601102543_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb2
-rw-r--r--db/migrate/20140801101230_create_chat_contacts.rb2
-rw-r--r--db/migrate/20140801101352_create_chat_fragments.rb2
-rw-r--r--db/migrate/20140824230505_add_completed_at_to_account_deletions.rb2
-rw-r--r--db/migrate/20140826165533_increase_simple_captcha_limit.rb2
-rw-r--r--db/migrate/20140906192846_fix_open_graph_data.rb2
-rw-r--r--db/migrate/20141001162851_add_remove_after_to_users.rb2
-rw-r--r--db/migrate/20141007003922_add_chat_enabled_to_aspects.rb2
-rw-r--r--db/migrate/20141024170120_create_chat_offline_messages.rb2
-rw-r--r--db/migrate/20141209041241_drop_open_graph_caches_with_invalid_urls.rb2
-rw-r--r--db/migrate/20141216213423_purge_orphan_conversations.rb2
-rw-r--r--db/migrate/20141227120907_add_export_to_user.rb2
-rw-r--r--db/migrate/20141230214830_user_pref_strip_exif.rb2
-rw-r--r--db/migrate/20150106050733_set_mysql_to_unicode_mb4.rb113
-rw-r--r--db/migrate/20150209230946_disable_mail_for_closed_account.rb2
-rw-r--r--db/migrate/20150220001357_add_photos_export_to_user.rb2
-rw-r--r--db/migrate/20150403192408_remove_deleted_aspects_from_auto_follow_back.rb2
-rw-r--r--db/migrate/20150403212139_fix_wrong_only_sharing.rb2
-rw-r--r--db/migrate/20150523004437_enable_color_themes.rb2
-rw-r--r--db/migrate/20150531005120_cleanup_default_avatars.rb2
-rw-r--r--db/migrate/20150607143809_fix_photo_public_flag.rb2
-rw-r--r--db/migrate/20150613202109_create_o_auth_applications.rb2
-rw-r--r--db/migrate/20150630221004_add_public_to_profiles.rb2
-rw-r--r--db/migrate/20150708153926_create_authorizations.rb2
-rw-r--r--db/migrate/20150708153928_create_o_auth_access_tokens.rb2
-rw-r--r--db/migrate/20150714055110_create_id_tokens.rb2
-rw-r--r--db/migrate/20150724152052_remove_favorites_from_posts.rb2
-rw-r--r--db/migrate/20150731123113_create_pairwise_pseudonymous_identifiers.rb2
-rw-r--r--db/migrate/20150731123114_add_status_to_pods.rb2
-rw-r--r--db/migrate/20150828132451_remove_duplicate_and_empty_pods.rb2
-rw-r--r--db/migrate/20151003142048_update_report_item_types.rb2
-rw-r--r--db/migrate/20151210213023_remove_signatures_from_relayables.rb2
-rw-r--r--db/migrate/20160124234712_extend_pods.rb10
-rw-r--r--db/migrate/20160225232049_link_share_visibilities_with_user.rb10
-rw-r--r--db/migrate/20160302025129_cleanup_aspect_visibility.rb12
-rw-r--r--db/migrate/20160307142216_cleanup_handles.rb2
-rw-r--r--db/migrate/20160327103605_add_author_id_index_to_participations.rb2
-rw-r--r--db/migrate/20160509232726_cleanup_duplicates_and_add_unique_indexes.rb2
-rw-r--r--db/migrate/20160531170531_remove_duplicate_aspect_visibilities.rb2
-rw-r--r--db/migrate/20160618033455_cleanup_participations.rb6
-rw-r--r--db/migrate/20160720212620_create_signature_tables.rb4
-rw-r--r--db/migrate/20160802212635_cleanup_posts_table.rb2
-rw-r--r--db/migrate/20160807212443_participation_counter.rb12
-rw-r--r--db/migrate/20160810230114_cleanup_invitation_columns_from_users.rb12
-rw-r--r--db/migrate/20160813115514_remove_id_tokens.rb2
-rw-r--r--db/migrate/20160822212739_remove_started_sharing_notifications_without_contact.rb7
-rw-r--r--db/migrate/20160829170244_add_post_default_to_aspects.rb2
-rw-r--r--db/migrate/20160901072443_add_video_url_to_open_graph_cache.rb2
-rw-r--r--db/migrate/20160902180630_remove_invalid_unconfirmed_emails.rb4
-rw-r--r--db/migrate/20160906225138_fix_photos_share_visibilities.rb6
-rw-r--r--db/migrate/20161015174300_remove_empty_pod.rb4
-rw-r--r--db/migrate/20161024231443_add_scheduled_check_to_pod.rb2
-rw-r--r--db/migrate/20161107100840_polymorphic_mentions.rb39
-rw-r--r--db/migrate/20170430022507_remove_message_signature.rb5
-rw-r--r--db/migrate/20170730154117_create_account_migrations.rb14
-rw-r--r--db/migrate/20170813141631_cleanup_account_deletions_and_add_unique_index.rb19
-rw-r--r--db/migrate/20170813153048_add_missing_indexes.rb7
-rw-r--r--db/migrate/20170813160104_cleanup_aspects_and_add_unique_index.rb21
-rw-r--r--db/migrate/20170813164435_add_missing_unique_indexes.rb41
-rw-r--r--db/migrate/20170813222333_reset_export_states.rb12
-rw-r--r--db/schema.rb675
-rw-r--r--features/desktop/change_settings.feature9
-rw-r--r--features/desktop/connects_users.feature2
-rw-r--r--features/desktop/follows_tags.feature2
-rw-r--r--features/desktop/invitations.feature4
-rw-r--r--features/desktop/mentions.feature31
-rw-r--r--features/desktop/notifications.feature21
-rw-r--r--features/desktop/post_preview.feature16
-rw-r--r--features/desktop/post_with_a_poll.feature16
-rw-r--r--features/desktop/signs_up.feature1
-rw-r--r--features/mobile/activity_stream.feature3
-rw-r--r--features/mobile/drawer.feature2
-rw-r--r--features/mobile/posts_from_main_page.feature4
-rw-r--r--features/step_definitions/aspects_steps.rb7
-rw-r--r--features/step_definitions/comment_steps.rb14
-rw-r--r--features/step_definitions/custom_web_steps.rb3
-rw-r--r--features/step_definitions/keyboard_navigation_steps.rb2
-rw-r--r--features/step_definitions/notifications_steps.rb6
-rw-r--r--features/step_definitions/oidc_common_steps.rb2
-rw-r--r--features/step_definitions/posts_steps.rb8
-rw-r--r--features/step_definitions/user_steps.rb8
-rw-r--r--features/step_definitions/web_steps.rb8
-rw-r--r--features/support/env.rb4
-rw-r--r--features/support/publishing_cuke_helpers.rb28
-rw-r--r--features/support/user_cuke_helpers.rb8
-rw-r--r--lib/account_deleter.rb39
-rw-r--r--lib/api/openid_connect/token_endpoint.rb2
-rw-r--r--lib/bookmarklet_renderer.rb26
-rw-r--r--lib/diaspora/exporter.rb11
-rw-r--r--lib/diaspora/exporter/non_contact_authors.rb36
-rw-r--r--lib/diaspora/exporter/others_relayables.rb42
-rw-r--r--lib/diaspora/exporter/posts_with_activity.rb59
-rw-r--r--lib/diaspora/federated.rb1
-rw-r--r--lib/diaspora/federated/contact_retraction.rb18
-rw-r--r--lib/diaspora/federated/retraction.rb36
-rw-r--r--lib/diaspora/federation/dispatcher.rb10
-rw-r--r--lib/diaspora/federation/dispatcher/private.rb15
-rw-r--r--lib/diaspora/federation/dispatcher/public.rb11
-rw-r--r--lib/diaspora/federation/entities.rb79
-rw-r--r--lib/diaspora/federation/mappings.rb125
-rw-r--r--lib/diaspora/federation/receive.rb41
-rw-r--r--lib/diaspora/fetcher/public.rb13
-rw-r--r--lib/diaspora/fields/target.rb1
-rw-r--r--lib/diaspora/mentionable.rb98
-rw-r--r--lib/diaspora/mentions_container.rb43
-rw-r--r--lib/diaspora/message_renderer.rb4
-rw-r--r--lib/diaspora/relayable.rb2
-rw-r--r--lib/diaspora/shareable.rb8
-rw-r--r--lib/evil_query.rb2
-rw-r--r--lib/schemas/archive-format.json255
-rw-r--r--lib/share_visibility_converter.rb12
-rw-r--r--lib/tasks/assets.rake13
-rw-r--r--lib/tasks/tests.rake9
-rwxr-xr-xscript/server2
-rw-r--r--spec/controllers/admin/pods_controller_spec.rb4
-rw-r--r--spec/controllers/admin/users_controller_spec.rb2
-rw-r--r--spec/controllers/admins_controller_spec.rb16
-rw-r--r--spec/controllers/api/openid_connect/authorizations_controller_spec.rb128
-rw-r--r--spec/controllers/api/openid_connect/clients_controller_spec.rb20
-rw-r--r--spec/controllers/api/openid_connect/discovery_controller_spec.rb16
-rw-r--r--spec/controllers/api/openid_connect/token_endpoint_controller_spec.rb15
-rw-r--r--spec/controllers/aspect_memberships_controller_spec.rb34
-rw-r--r--spec/controllers/aspects_controller_spec.rb38
-rw-r--r--spec/controllers/blocks_controller_spec.rb41
-rw-r--r--spec/controllers/comments_controller_spec.rb30
-rw-r--r--spec/controllers/contacts_controller_spec.rb28
-rw-r--r--spec/controllers/conversation_visibilities_controller_spec.rb10
-rw-r--r--spec/controllers/conversations_controller_spec.rb237
-rw-r--r--spec/controllers/help_controller_spec.rb2
-rw-r--r--spec/controllers/home_controller_spec.rb2
-rw-r--r--spec/controllers/invitation_codes_controller_spec.rb6
-rw-r--r--spec/controllers/invitations_controller_spec.rb30
-rw-r--r--spec/controllers/jasmine_fixtures/aspects_spec.rb6
-rw-r--r--spec/controllers/jasmine_fixtures/contacts_spec.rb4
-rw-r--r--spec/controllers/jasmine_fixtures/conversations_spec.rb4
-rw-r--r--spec/controllers/jasmine_fixtures/people_spec.rb2
-rw-r--r--spec/controllers/jasmine_fixtures/photos_spec.rb2
-rw-r--r--spec/controllers/jasmine_fixtures/posts_spec.rb11
-rw-r--r--spec/controllers/jasmine_fixtures/status_messages_spec.rb2
-rw-r--r--spec/controllers/jasmine_fixtures/streams_spec.rb1
-rw-r--r--spec/controllers/likes_controller_spec.rb23
-rw-r--r--spec/controllers/messages_controller_spec.rb29
-rw-r--r--spec/controllers/node_info_controller_spec.rb18
-rw-r--r--spec/controllers/notifications_controller_spec.rb101
-rw-r--r--spec/controllers/participations_controller_spec.rb8
-rw-r--r--spec/controllers/passwords_controller_spec.rb8
-rw-r--r--spec/controllers/people_controller_spec.rb146
-rw-r--r--spec/controllers/photos_controller_spec.rb67
-rw-r--r--spec/controllers/posts_controller_spec.rb87
-rw-r--r--spec/controllers/profiles_controller_spec.rb53
-rw-r--r--spec/controllers/registrations_controller_spec.rb40
-rw-r--r--spec/controllers/report_controller_spec.rb28
-rw-r--r--spec/controllers/reshares_controller_spec.rb10
-rw-r--r--spec/controllers/search_controller_spec.rb8
-rw-r--r--spec/controllers/services_controller_spec.rb22
-rw-r--r--spec/controllers/sessions_controller_spec.rb4
-rw-r--r--spec/controllers/share_visibilities_controller_spec.rb8
-rw-r--r--spec/controllers/status_messages_controller_spec.rb80
-rw-r--r--spec/controllers/tags_controller_spec.rb28
-rw-r--r--spec/controllers/users_controller_spec.rb98
-rw-r--r--spec/factories.rb113
-rw-r--r--spec/federation_callbacks_spec.rb31
-rw-r--r--spec/helper_methods.rb30
-rw-r--r--spec/helpers/application_helper_spec.rb4
-rw-r--r--spec/helpers/notifications_helper_spec.rb31
-rw-r--r--spec/integration/account_deletion_spec.rb135
-rw-r--r--spec/integration/account_migration_spec.rb204
-rw-r--r--spec/integration/api/user_info_controller_spec.rb2
-rw-r--r--spec/integration/application_spec.rb10
-rw-r--r--spec/integration/exporter_spec.rb444
-rw-r--r--spec/integration/federation/attack_vectors_spec.rb27
-rw-r--r--spec/integration/federation/federation_helper.rb93
-rw-r--r--spec/integration/federation/receive_federation_messages_spec.rb182
-rw-r--r--spec/integration/federation/shared_receive_relayable.rb10
-rw-r--r--spec/integration/federation/shared_receive_retraction.rb26
-rw-r--r--spec/integration/federation/shared_receive_stream_items.rb117
-rw-r--r--spec/integration/mentioning_spec.rb381
-rw-r--r--spec/integration/mobile_posts_spec.rb6
-rw-r--r--spec/integration/tag_people_spec.rb4
-rw-r--r--spec/javascripts/app/app_spec.js14
-rw-r--r--spec/javascripts/app/models/stream_spec.js32
-rw-r--r--spec/javascripts/app/pages/single-post-viewer_spec.js3
-rw-r--r--spec/javascripts/app/router_spec.js7
-rw-r--r--spec/javascripts/app/views/bookmarklet_view_spec.js7
-rw-r--r--spec/javascripts/app/views/comment_mention_view_spec.js10
-rw-r--r--spec/javascripts/app/views/comment_stream_view_spec.js171
-rw-r--r--spec/javascripts/app/views/content_view_spec.js8
-rw-r--r--spec/javascripts/app/views/conversations_form_view_spec.js43
-rw-r--r--spec/javascripts/app/views/conversations_inbox_view_spec.js13
-rw-r--r--spec/javascripts/app/views/header_view_spec.js5
-rw-r--r--spec/javascripts/app/views/help_view_spec.js15
-rw-r--r--spec/javascripts/app/views/notifications_view_spec.js11
-rw-r--r--spec/javascripts/app/views/preview_post_view_spec.js14
-rw-r--r--spec/javascripts/app/views/publisher_mention_view_spec.js145
-rw-r--r--spec/javascripts/app/views/publisher_view_spec.js71
-rw-r--r--spec/javascripts/app/views/single-post-view/single_post_comment_stream_spec.js8
-rw-r--r--spec/javascripts/app/views/single-post-view/single_post_interaction_counts_spec.js148
-rw-r--r--spec/javascripts/helpers/markdown_editor_spec.js60
-rw-r--r--spec/javascripts/jasmine_helpers/SpecHelper.js19
-rw-r--r--spec/javascripts/jasmine_helpers/factory.js28
-rw-r--r--spec/javascripts/mobile/mobile_comments_spec.js24
-rw-r--r--spec/javascripts/mobile/mobile_post_actions_spec.js15
-rw-r--r--spec/lib/account_deleter_spec.rb53
-rw-r--r--spec/lib/api/openid_connect/protected_resource_endpoint_spec.rb8
-rw-r--r--spec/lib/api/openid_connect/token_endpoint_spec.rb80
-rw-r--r--spec/lib/diaspora/exporter/non_contact_authors_spec.rb25
-rw-r--r--spec/lib/diaspora/exporter/others_relayables_spec.rb35
-rw-r--r--spec/lib/diaspora/exporter/posts_with_activity_spec.rb24
-rw-r--r--spec/lib/diaspora/exporter_spec.rb93
-rw-r--r--spec/lib/diaspora/federated/contact_retraction_spec.rb66
-rw-r--r--spec/lib/diaspora/federated/retraction_spec.rb113
-rw-r--r--spec/lib/diaspora/federation/dispatcher/private_spec.rb51
-rw-r--r--spec/lib/diaspora/federation/dispatcher/public_spec.rb29
-rw-r--r--spec/lib/diaspora/federation/entities_spec.rb153
-rw-r--r--spec/lib/diaspora/federation/receive_spec.rb143
-rw-r--r--spec/lib/diaspora/mentionable_spec.rb202
-rw-r--r--spec/lib/diaspora/message_renderer_spec.rb17
-rw-r--r--spec/lib/evil_query_spec.rb12
-rw-r--r--spec/lib/publisher_spec.rb2
-rw-r--r--spec/lib/stream/person_spec.rb2
-rw-r--r--spec/mailers/notifier_spec.rb130
-rw-r--r--spec/mailers/report_spec.rb6
-rw-r--r--spec/models/account_deletion_spec.rb2
-rw-r--r--spec/models/account_migration_spec.rb148
-rw-r--r--spec/models/api/openid_connect/id_token_spec.rb14
-rw-r--r--spec/models/comment_spec.rb32
-rw-r--r--spec/models/contact_spec.rb5
-rw-r--r--spec/models/location_spec.rb14
-rw-r--r--spec/models/mention_spec.rb4
-rw-r--r--spec/models/message_spec.rb5
-rw-r--r--spec/models/notifications/mentioned_in_post_spec.rb72
-rw-r--r--spec/models/notifications/mentioned_spec.rb95
-rw-r--r--spec/models/notifications/private_message_spec.rb2
-rw-r--r--spec/models/person_spec.rb122
-rw-r--r--spec/models/photo_spec.rb8
-rw-r--r--spec/models/pod_spec.rb19
-rw-r--r--spec/models/poll_participation_spec.rb18
-rw-r--r--spec/models/poll_spec.rb31
-rw-r--r--spec/models/post_spec.rb50
-rw-r--r--spec/models/profile_spec.rb42
-rw-r--r--spec/models/role_spec.rb7
-rw-r--r--spec/models/status_message_spec.rb80
-rw-r--r--spec/models/user/connecting_spec.rb13
-rw-r--r--spec/models/user/posting_spec.rb9
-rw-r--r--spec/models/user/querying_spec.rb2
-rw-r--r--spec/models/user_spec.rb63
-rw-r--r--spec/presenters/avatar_presenter_spec.rb9
-rw-r--r--spec/presenters/o_embed_presenter_spec.rb4
-rw-r--r--spec/presenters/post_interaction_presenter_spec.rb (renamed from spec/presenters/post_ineraction_presenter_spec.rb)0
-rw-r--r--spec/presenters/post_presenter_spec.rb101
-rw-r--r--spec/presenters/statistics_presenter_spec.rb110
-rw-r--r--spec/serializers/comment_serializer_spec.rb8
-rw-r--r--spec/serializers/export/aspect_serializer_spec.rb12
-rw-r--r--spec/serializers/export/contact_serializer_spec.rb25
-rw-r--r--spec/serializers/export/others_data_serializer_spec.rb43
-rw-r--r--spec/serializers/export/own_post_serializer_spec.rb48
-rw-r--r--spec/serializers/export/own_relayables_serializer_spec.rb9
-rw-r--r--spec/serializers/export/person_metadata_serializer_spec.rb12
-rw-r--r--spec/serializers/export/user_serializer_spec.rb79
-rw-r--r--spec/serializers/federation_entity_serializer_spec.rb17
-rw-r--r--spec/serializers/notification_serializer_spec.rb2
-rw-r--r--spec/serializers/post_serializer_spec.rb15
-rw-r--r--spec/serializers/serializer_post_processing_spec.rb33
-rw-r--r--spec/services/notification_service_spec.rb74
-rw-r--r--spec/services/post_service_spec.rb232
-rw-r--r--spec/services/status_message_creation_service_spec.rb48
-rw-r--r--spec/shared_behaviors/account_deletion.rb79
-rw-r--r--spec/shared_behaviors/account_migration.rb187
-rw-r--r--spec/shared_behaviors/dispatcher.rb4
-rw-r--r--spec/shared_behaviors/federation_entity_serializer.rb14
-rw-r--r--spec/shared_behaviors/mentions_container.rb61
-rw-r--r--spec/shared_behaviors/shareable.rb18
-rw-r--r--spec/shared_behaviors/taggable.rb2
-rw-r--r--spec/spec/data_generator_spec.rb58
-rw-r--r--spec/spec/misc_spec.rb (renamed from spec/misc_spec.rb)30
-rw-r--r--spec/spec_helper.rb13
-rw-r--r--spec/support/account_matchers.rb43
-rw-r--r--spec/support/data_generator.rb189
-rw-r--r--spec/support/serializer_matchers.rb79
-rw-r--r--spec/support/user_methods.rb19
-rw-r--r--spec/workers/mail/csrf_token_fail_spec.rb4
-rw-r--r--spec/workers/mail/liked_spec.rb9
-rw-r--r--spec/workers/mail/mentioned_spec.rb9
-rw-r--r--spec/workers/mail/private_message_spec.rb9
-rw-r--r--spec/workers/mail/reshared_spec.rb7
-rw-r--r--spec/workers/send_private_spec.rb2
-rw-r--r--spec/workers/send_public_spec.rb2
605 files changed, 11154 insertions, 7089 deletions
diff --git a/.gitignore b/.gitignore
index 072691512..fea147b0e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,27 +10,15 @@ app/assets/images/custom/
# Configuration files
config/diaspora.yml
-config/heroku.yml
config/initializers/secret_token.rb
-config/redis.conf
-config/deploy_config.yml
-config/schedule.rb
.bundle
vendor/bundle/
vendor/cache/
config/database.yml
-.rvmrc_custom
-.rvmrc.local
config/oidc_key.pem
-# Mailing list stuff
-config/email_offset
-config/mailing_list.csv
-
# Generated files
log/
-public/stylesheets/*.css
-public/diaspora
spec/fixtures/*.y*ml
spec/fixtures/*.fixture.*
coverage/
@@ -39,6 +27,12 @@ public/404.html
public/422.html
public/500.html
+# the db/schema.rb. Although this is contrary to rails best-practises, we
+# cannot provide a schema.rb that works for both MySQL and PostgreSQL, so we
+# have no choice. Our migrations are maintained, so it should always be
+# possible to get back to a "clean" database schema anyway.
+db/schema.rb
+
# Sprites
app/assets/images/branding-*.png
app/assets/images/branding/logos-*.png
@@ -53,17 +47,13 @@ doc/
public/uploads/
public/assets/
public/source.tar*
-public/.well-known
-tmp/**/
tmp/
-*.sqlite3
# Temporary files of every sort
.sass-cache/
.DS_Store
.idea
.redcar
-.rvmrc
.stgit*
*.swap
*.swo
@@ -76,7 +66,6 @@ tmp/
nbproject
patches-*
capybara-*.html
-dump.rdb
# Rubinius's JIT
*.rbc
diff --git a/.rubocop.yml b/.rubocop.yml
index 2ebb26cff..91f28fdb1 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -40,7 +40,7 @@ Metrics/BlockLength:
# No space makes the method definition shorter and differentiates
# from a regular assignment.
-Style/SpaceAroundEqualsInParameterDefault:
+Layout/SpaceAroundEqualsInParameterDefault:
EnforcedStyle: no_space
# Single quotes being faster is hardly measurable and only affects parse time.
@@ -55,7 +55,7 @@ Style/SymbolArray:
Enabled: true
# Most readable form.
-Style/AlignHash:
+Layout/AlignHash:
EnforcedHashRocketStyle: table
EnforcedColonStyle: table
@@ -92,7 +92,7 @@ Style/RaiseArgs:
# Indenting the chained dots beneath each other is not supported by this cop,
# see https://github.com/bbatsov/rubocop/issues/1633
-Style/MultilineOperationIndentation:
+Layout/MultilineOperationIndentation:
Enabled: false
# Fail is an alias of raise. Avoid aliases, it's more cognitive load for no gain.
@@ -107,7 +107,7 @@ Style/SignalException:
Lint/HandleExceptions:
Enabled: false
-Style/SpaceInsideBlockBraces:
+Layout/SpaceInsideBlockBraces:
# The space here provides no real gain in readability while consuming
# horizontal space that could be used for a better parameter name.
# Also {| differentiates better from a hash than { | does.
@@ -115,7 +115,7 @@ Style/SpaceInsideBlockBraces:
# No trailing space differentiates better from the block:
# foo} means hash, foo } means block.
-Style/SpaceInsideHashLiteralBraces:
+Layout/SpaceInsideHashLiteralBraces:
EnforcedStyle: no_space
# { ... } for multi-line blocks is okay, follow Weirichs rule instead:
@@ -165,7 +165,7 @@ Style/NumericPredicate:
EnforcedStyle: comparison
# Reset some HoundCI changes back to Rubocop defaults
-Style/DotPosition:
+Layout/DotPosition:
EnforcedStyle: leading
### backward compatibility
diff --git a/.ruby-version b/.ruby-version
index bb576dbde..6b4950e3d 100644
--- a/.ruby-version
+++ b/.ruby-version
@@ -1 +1 @@
-2.3
+2.4
diff --git a/.travis.yml b/.travis.yml
index 1bcd8421a..e4b310171 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,8 +1,8 @@
language: ruby
rvm:
- - 2.3.1
- - 2.1
+ - 2.4.1
+ - 2.3.4
env:
- DB=postgresql BUILD_TYPE=cucumber
@@ -15,6 +15,7 @@ cache:
bundler: true
directories:
- app/assets/images
+ - tmp/cache/assets
branches:
only:
@@ -29,7 +30,7 @@ before_install:
- tar -xvf $PWD/travis-phantomjs/phantomjs-2.1.1-linux-x86_64.tar.bz2 -C $PWD/travis-phantomjs
- export PATH=$PWD/travis-phantomjs/phantomjs-2.1.1-linux-x86_64/bin:$PATH
-bundler_args: "--deployment --without development production --with mysql postgresql --jobs 3 --retry 3"
+bundler_args: "--deployment --without development --with mysql postgresql --jobs 3 --retry 3"
script: "./script/ci/build.sh"
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 000000000..797e62775
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,42 @@
+# Contributing to diaspora\*
+
+First of all: thank you very much for helping us out!
+
+## Things you need to know before contributing
+
+If you want to get in touch with other diaspora\* developers, [check our wiki][how-we-communicate] for information on how we communicate. Feel free to ask if you have any questions!
+
+Everyone interacting with our code, issue trackers, chat rooms, mailing lists, the wiki, and the discourse forum is expected to follow the [diaspora\* code of conduct][code-of-conduct].
+
+## Report a security issue
+
+Found a security issue? Please disclose it responsibly. We have a team of developers listening to [security@diasporafoundation.org][sec-mail]. The PGP fingerprint is [AB0D AB02 0FC5 D398 03AB 3CE1 6F70 243F 27AD 886A][pgp].
+
+## Contributing to translations
+
+We use [WebTranslateIt][webtranslateit] to manage translations of the app interface. Please read [our wiki page][translation-wiki] to find out more about this. If your language is featured on WebTranslateIt, please do **not** open a pull request to update translations. If it is not already featured on WebTranslateIt, please read the wiki article above to find out how to proceed.
+
+## Contributing to the code
+
+**Before opening a pull request** please read [how to contribute][contribute]. Doing things the right way from the start will save us time and mean that your contribution can be integrated quicker!
+- Follow our [git workflow][git-workflow] method. In particular, *do not* open a pull request from the `master` or the `develop` branch.
+- Follow our [styleguide][styleguide] and run pronto, our syntax analyzer, **locally before opening a pull request**. See [our wiki][pronto] for information on how to do this.
+- [Write tests][testing-workflow].
+- Use meaningful commit-messages and split larger tasks, e.g. refactoring, into separate commits. This makes the review process much easier.
+
+## Other ways to contribute
+
+You don’t know code? No worries, there are plenty other ways to help the diaspora* project! Please find out how you can help [on our wiki][other-ways].
+
+[code-of-conduct]: https://github.com/diaspora/diaspora/blob/develop/CODE_OF_CONDUCT.md
+[how-we-communicate]: https://wiki.diasporafoundation.org/How_we_communicate
+[pgp]: https://pgp.mit.edu/pks/lookup?op=get&search=0x6F70243F27AD886A
+[sec-mail]: mailto:security@diasporafoundation.org
+[webtranslateit]: https://webtranslateit.com/en/projects/3020-Diaspora
+[translation-wiki]: https://wiki.diasporafoundation.org/Contribute_translations
+[contribute]: https://wiki.diasporafoundation.org/Getting_started_with_contributing
+[git-workflow]: https://wiki.diasporafoundation.org/Git_Workflow
+[styleguide]: https://wiki.diasporafoundation.org/Styleguide
+[pronto]: https://wiki.diasporafoundation.org/Styleguide#Automatic_local_review
+[testing-workflow]: https://wiki.diasporafoundation.org/Testing_Workflow
+[other-ways]: https://wiki.diasporafoundation.org/Other_ways_to_contribute
diff --git a/Changelog.md b/Changelog.md
index dad01e1dd..879ca4e86 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -1,3 +1,63 @@
+# 0.7.0.0
+
+## Supported Ruby versions
+
+This release recommends using Ruby 2.4, while retaining Ruby 2.3 as an officially supported version.
+Ruby 2.1 is no longer officially supported.
+
+## Delete public/.well-known/
+
+Before upgrading, please check if your `public/` folder contains a hidden `.well-known/` folder.
+If so, please delete it since it will prevent the federation from working properly.
+
+## Refactor
+
+* Make the mention syntax more flexible [#7305](https://github.com/diaspora/diaspora/pull/7305)
+* Display @ before mentions [#7324](https://github.com/diaspora/diaspora/pull/7324)
+* Simplify mentions in the publisher [#7302](https://github.com/diaspora/diaspora/pull/7302)
+* Remove chartbeat and mixpanel support [#7280](https://github.com/diaspora/diaspora/pull/7280)
+* Upgrade to jQuery 3 [#7303](https://github.com/diaspora/diaspora/pull/7303)
+* Add i18n for color themes [#7369](https://github.com/diaspora/diaspora/pull/7369)
+* Remove deprecated statistics.json [#7399](https://github.com/diaspora/diaspora/pull/7399)
+* Always link comment count text on mobile [#7483](https://github.com/diaspora/diaspora/pull/7483)
+* Switch to new federation protocol [#7436](https://github.com/diaspora/diaspora/pull/7436)
+* Send public profiles publicly [#7501](https://github.com/diaspora/diaspora/pull/7501)
+* Change sender for mails [#7495](https://github.com/diaspora/diaspora/pull/7495)
+* Move back to top to the right to avoid misclicks [#7516](https://github.com/diaspora/diaspora/pull/7516)
+* Include count in mobile post action link [#7520](https://github.com/diaspora/diaspora/pull/7520)
+* Update the user data export archive format [#6726](https://github.com/diaspora/diaspora/pull/6726)
+* Use id as fallback when sorting posts [#7523](https://github.com/diaspora/diaspora/pull/7523)
+* Remove no-posts-info when adding posts to the stream [#7523](https://github.com/diaspora/diaspora/pull/7523)
+* Upgrade to rails 5.1 [#7514](https://github.com/diaspora/diaspora/pull/7514)
+* Refactoring single post view interactions [#7182](https://github.com/diaspora/diaspora/pull/7182)
+* Update help pages [#7528](https://github.com/diaspora/diaspora/pull/7528)
+* Disable rendering logging in production [#7529](https://github.com/diaspora/diaspora/pull/7529)
+* Add some missing indexes and cleanup the database if needed [#7533](https://github.com/diaspora/diaspora/pull/7533)
+* Remove avatar, name, timestamp and interactions from publisher preview [#7536](https://github.com/diaspora/diaspora/pull/7536)
+
+## Bug fixes
+
+* Fix height too high on mobile SPV [#7480](https://github.com/diaspora/diaspora/pull/7480)
+* Improve stream when ignoring a person who posts a lot of tagged posts [#7503](https://github.com/diaspora/diaspora/pull/7503)
+* Fix order of comments across pods [#7436](https://github.com/diaspora/diaspora/pull/7436)
+* Prevent publisher from closing in preview mode [#7518](https://github.com/diaspora/diaspora/pull/7518)
+* Increase reshare counter after reshare on mobile [#7520](https://github.com/diaspora/diaspora/pull/7520)
+* Reset stuck exports and handle errors [#7535](https://github.com/diaspora/diaspora/pull/7535)
+
+## Features
+* Add support for mentions in comments to the backend [#6818](https://github.com/diaspora/diaspora/pull/6818)
+* Add support for new mention syntax [#7300](https://github.com/diaspora/diaspora/pull/7300) [#7394](https://github.com/diaspora/diaspora/pull/7394)
+* Render mentions as links in comments [#7327](https://github.com/diaspora/diaspora/pull/7327)
+* Add support for mentions in comments to the front-end [#7386](https://github.com/diaspora/diaspora/pull/7386)
+* Support direct links to comments on mobile [#7508](https://github.com/diaspora/diaspora/pull/7508)
+* Add inviter first and last name in the invitation e-mail [#7484](https://github.com/diaspora/diaspora/pull/7484)
+* Add markdown editor for comments and conversations [#7482](https://github.com/diaspora/diaspora/pull/7482)
+* Improve responsive header in desktop version [#7509](https://github.com/diaspora/diaspora/pull/7509)
+* Support cmd+enter to submit posts, comments and conversations [#7524](https://github.com/diaspora/diaspora/pull/7524)
+* Add markdown editor for posts, comments and conversations on mobile [#7235](https://github.com/diaspora/diaspora/pull/7235)
+* Mark as "Mobile Web App Capable" on Android [#7534](https://github.com/diaspora/diaspora/pull/7534)
+* Add support for receiving account migrations [#6750](https://github.com/diaspora/diaspora/pull/6750)
+
# 0.6.7.0
## Refactor
diff --git a/Gemfile b/Gemfile
index a8e4f3e5b..532d4dd9e 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,29 +1,30 @@
source "https://rubygems.org"
-gem "rails", "4.2.8"
+gem "rails", "5.1.3"
# Legacy Rails features, remove me!
# responders (class level)
-gem "responders", "2.3.0"
+gem "responders", "2.4.0"
# Appserver
-gem "unicorn", "5.2.0", require: false
+gem "unicorn", "5.3.0", require: false
gem "unicorn-worker-killer", "0.4.4"
# Federation
-gem "diaspora_federation-rails", "0.1.9"
+gem "diaspora_federation-json_schema", "0.2.1"
+gem "diaspora_federation-rails", "0.2.1"
# API and JSON
-gem "acts_as_api", "1.0.0"
-gem "json", "1.8.6"
+gem "acts_as_api", "1.0.1"
+gem "json", "2.1.0"
gem "json-schema", "2.8.0"
# Authentication
-gem "devise", "4.2.0"
+gem "devise", "4.3.0"
gem "devise_lastseenable", "0.0.6"
# Captcha
@@ -32,15 +33,15 @@ gem "simple_captcha2", "0.4.3", require: "simple_captcha"
# Background processing
-gem "sidekiq", "4.2.9"
+gem "sidekiq", "5.0.4"
# Scheduled processing
-gem "sidekiq-cron", "0.4.5"
+gem "sidekiq-cron", "0.6.3"
# Compression
-gem "uglifier", "3.1.2"
+gem "uglifier", "3.2.0"
# Configuration
@@ -48,33 +49,34 @@ gem "configurate", "0.3.1"
# Cross-origin resource sharing
-gem "rack-cors", "0.4.1", require: "rack/cors"
+gem "rack-cors", "1.0.1", require: "rack/cors"
# CSS
-gem "autoprefixer-rails", "6.7.6"
+gem "autoprefixer-rails", "7.1.2.4"
gem "bootstrap-sass", "3.3.7"
gem "bootstrap-switch-rails", "3.3.3"
-gem "compass-rails", "2.0.5"
+gem "compass-rails", "3.0.2"
gem "sass-rails", "5.0.6"
+gem "sprockets-rails", "3.2.0"
# Database
group :mysql, optional: true do
- gem "mysql2", "0.4.5"
+ gem "mysql2", "0.4.9"
end
group :postgresql, optional: true do
- gem "pg", "0.19.0"
+ gem "pg", "0.21.0"
end
-gem "activerecord-import", "0.17.1"
+gem "activerecord-import", "0.19.1"
# File uploading
-gem "fog-aws", "1.2.1"
-gem "carrierwave", "0.11.2"
-gem "mini_magick", "4.6.1"
+gem "carrierwave", "1.1.0"
+gem "fog-aws", "1.4.0"
+gem "mini_magick", "4.8.0"
# GUID generation
gem "uuid", "2.3.8"
@@ -85,19 +87,19 @@ gem "entypo-rails", "3.0.0"
# JavaScript
-gem "handlebars_assets", "0.23.1"
-gem "jquery-rails", "4.2.1"
-gem "jquery-ui-rails", "5.0.5"
+gem "handlebars_assets", "0.23.2"
+gem "jquery-rails", "4.3.1"
gem "js-routes", "1.3.3"
-gem "js_image_paths", "0.1.0"
+gem "js_image_paths", "0.1.1"
source "https://rails-assets.org" do
- gem "rails-assets-jquery", "2.2.4" # Should be kept in sync with jquery-rails
+ gem "rails-assets-jquery", "3.2.1" # Should be kept in sync with jquery-rails
+ gem "rails-assets-jquery.ui", "1.11.4"
- gem "rails-assets-highlightjs", "9.9.0"
- gem "rails-assets-markdown-it", "8.3.0"
+ gem "rails-assets-highlightjs", "9.12.0"
+ gem "rails-assets-markdown-it", "8.3.2"
gem "rails-assets-markdown-it-hashtag", "0.4.0"
- gem "rails-assets-markdown-it-diaspora-mention", "1.1.1"
+ gem "rails-assets-markdown-it-diaspora-mention", "1.2.0"
gem "rails-assets-markdown-it-sanitizer", "0.4.3"
gem "rails-assets-markdown-it--markdown-it-for-inline", "0.1.1"
gem "rails-assets-markdown-it-sub", "1.0.0"
@@ -110,8 +112,8 @@ source "https://rails-assets.org" do
# jQuery plugins
- gem "rails-assets-autosize", "3.0.20"
- gem "rails-assets-blueimp-gallery", "2.25.0"
+ gem "rails-assets-autosize", "4.0.0"
+ gem "rails-assets-blueimp-gallery", "2.25.2"
gem "rails-assets-jquery.are-you-sure", "1.9.0"
gem "rails-assets-jquery-placeholder", "2.3.1"
gem "rails-assets-jquery-textchange", "0.2.3"
@@ -120,24 +122,24 @@ end
# Localization
-gem "http_accept_language", "2.1.0"
+gem "http_accept_language", "2.1.1"
gem "i18n-inflector-rails", "1.0.7"
-gem "rails-i18n", "4.0.8"
+gem "rails-i18n", "5.0.4"
# Mail
gem "markerb", "1.1.0"
# Map
-gem "leaflet-rails", "0.7.7"
+gem "leaflet-rails", "1.1.0"
# Parsing
-gem "nokogiri", "1.7.2"
+gem "nokogiri", "1.8.0"
gem "open_graph_reader", "0.6.2" # also update User-Agent in features/support/webmock.rb
gem "redcarpet", "3.4.0"
-gem "ruby-oembed", "0.10.1"
-gem "twitter-text", "1.14.5"
+gem "ruby-oembed", "0.12.0"
+gem "twitter-text", "1.14.7"
# RTL support
@@ -145,11 +147,11 @@ gem "string-direction", "1.2.0"
# Security Headers
-gem "secure_headers", "3.6.1"
+gem "secure_headers", "3.6.7"
# Services
-gem "omniauth", "1.4.2"
+gem "omniauth", "1.6.1"
gem "omniauth-facebook", "4.0.0"
gem "omniauth-tumblr", "1.2"
gem "omniauth-twitter", "1.4.0"
@@ -157,11 +159,11 @@ gem "twitter", "6.1.0"
gem "omniauth-wordpress", "0.2.2"
# OpenID Connect
-gem "openid_connect", "0.12.0"
+gem "openid_connect", "1.1.3"
# Serializers
-gem "active_model_serializers", "0.9.5"
+gem "active_model_serializers", "0.9.7"
# XMPP chat dependencies
gem "diaspora-prosody-config", "0.0.7"
@@ -169,11 +171,11 @@ gem "rails-assets-diaspora_jsxc", "0.1.5.develop.7", source: "https://rails-asse
# Tags
-gem "acts-as-taggable-on", "3.5.0"
+gem "acts-as-taggable-on", "5.0.0"
# URIs and HTTP
-gem "addressable", "2.5.0", require: "addressable/uri"
+gem "addressable", "2.5.1", require: "addressable/uri"
gem "faraday", "0.11.0" # also update User-Agent in OpenID specs
gem "faraday_middleware", "0.11.0.1"
gem "faraday-cookie_jar", "0.0.6"
@@ -182,14 +184,14 @@ gem "typhoeus", "1.1.2"
# Views
gem "gon", "6.1.0"
-gem "hamlit", "2.8.0"
-gem "mobile-fu", "1.3.1"
+gem "hamlit", "2.8.4"
+gem "mobile_fu", "1.4.0", require: "mobile-fu"
gem "rails-timeago", "2.16.0"
-gem "will_paginate", "3.1.5"
+gem "will_paginate", "3.1.6"
# Logging
-gem "logging-rails", "0.5.0", require: "logging/rails"
+gem "logging-rails", "0.6.0", require: "logging/rails"
# Reading and writing zip files
@@ -202,13 +204,7 @@ gem "rubyzip", "1.2.1", require: "zip"
# https://github.com/discourse/discourse/pull/238
gem "minitest"
-gem "versionist", "1.5.0"
-
-# Prevent accidental upgrades of thor
-# TODO: remove this when either all gems depending on thor have fixed the warnings
-# or thor released a version where they are clearly marked as warnings
-# see: https://github.com/erikhuda/thor/issues/538
-gem "thor", "0.19.1"
+gem "versionist", "1.6.0"
# Windows and OSX have an execjs compatible runtime built-in, Linux users should
# install Node.js or use "therubyracer".
@@ -225,7 +221,7 @@ group :production do # we don"t install these on travis to speed up test runs
# Process management
- gem "eye", "0.9.1"
+ gem "eye", "0.9.2"
# Redirects
@@ -234,7 +230,7 @@ group :production do # we don"t install these on travis to speed up test runs
# Third party asset hosting
- gem "asset_sync", "2.0.0", require: false
+ gem "asset_sync", "2.2.0", require: false
end
group :development do
@@ -242,22 +238,22 @@ group :development do
gem "guard", "2.14.1", require: false
gem "guard-cucumber", "2.1.2", require: false
gem "guard-rspec", "4.7.3", require: false
- gem "guard-rubocop", "1.2.0", require: false
- gem "rb-fsevent", "0.9.8", require: false
- gem "rb-inotify", "0.9.8", require: false
+ gem "guard-rubocop", "1.3.0", require: false
+ gem "rb-fsevent", "0.10.2", require: false
+ gem "rb-inotify", "0.9.10", require: false
# Linters
- gem "haml_lint", "0.24.0", require: false
- gem "pronto", "0.9.3", require: false
+ gem "haml_lint", "0.26.0", require: false
+ gem "pronto", "0.9.4", require: false
gem "pronto-eslint", "0.9.1", require: false
gem "pronto-haml", "0.9.0", require: false
gem "pronto-rubocop", "0.9.0", require: false
gem "pronto-scss", "0.9.1", require: false
- gem "rubocop", "0.48.1", require: false
+ gem "rubocop", "0.49.1", require: false
# Preloading environment
- gem "spring", "2.0.1"
+ gem "spring", "2.0.2"
gem "spring-commands-rspec", "1.0.4"
gem "spring-commands-cucumber", "1.0.1"
@@ -266,7 +262,7 @@ group :development do
gem "pry-byebug"
# test coverage
- gem "simplecov", "0.12.0", require: false
+ gem "simplecov", "0.14.1", require: false
gem "turbo_dev_assets", "0.0.2"
end
@@ -274,44 +270,45 @@ end
group :test do
# RSpec (unit tests, some integration tests)
- gem "fixture_builder", "0.4.1"
+ gem "fixture_builder", "0.5.0"
gem "fuubar", "2.2.0"
- gem "test_after_commit", "1.1.0"
+ gem "json-schema-rspec", "0.0.4"
+ gem "rspec-json_expectations", "~> 2.1"
# Cucumber (integration tests)
- gem "capybara", "2.12.1"
- gem "database_cleaner", "1.5.3"
- gem "poltergeist", "1.13.0"
+ gem "capybara", "2.15.1"
+ gem "database_cleaner", "1.6.1"
+ gem "poltergeist", "1.16.0"
gem "cucumber-api-steps", "0.13", require: false
# General helpers
gem "factory_girl_rails", "4.8.0"
- gem "timecop", "0.8.1"
- gem "webmock", "2.3.2", require: false
- gem "shoulda-matchers", "3.1.1"
+ gem "shoulda-matchers", "3.1.2"
+ gem "timecop", "0.9.1"
+ gem "webmock", "3.0.1", require: false
- gem "diaspora_federation-test", "0.1.9"
+ gem "diaspora_federation-test", "0.2.1"
# Coverage
- gem 'coveralls', require: false
+ gem "coveralls", "0.8.21", require: false
end
group :development, :test do
# RSpec (unit tests, some integration tests)
- gem "rspec-rails", "3.5.2"
+ gem "rspec-rails", "3.6.1"
# Cucumber (integration tests)
- gem "cucumber-rails", "1.4.5", require: false
+ gem "cucumber-rails", "1.5.0", require: false
# Jasmine (client side application tests (JS))
- gem "jasmine", "2.5.2"
+ gem "jasmine", "2.7.0"
gem "jasmine-jquery-rails", "2.0.3"
gem "rails-assets-jasmine-ajax", "3.3.1", source: "https://rails-assets.org"
gem "sinon-rails", "1.15.0"
- # silence assets
- gem "quiet_assets", "1.1.0"
+ # For `assigns` in controller specs
+ gem "rails-controller-testing", "1.0.2"
end
diff --git a/Gemfile.lock b/Gemfile.lock
index 2012458cb..5bc4f2ec5 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -2,64 +2,68 @@ GEM
remote: https://rubygems.org/
remote: https://rails-assets.org/
specs:
- actionmailer (4.2.8)
- actionpack (= 4.2.8)
- actionview (= 4.2.8)
- activejob (= 4.2.8)
+ actioncable (5.1.3)
+ actionpack (= 5.1.3)
+ nio4r (~> 2.0)
+ websocket-driver (~> 0.6.1)
+ actionmailer (5.1.3)
+ actionpack (= 5.1.3)
+ actionview (= 5.1.3)
+ activejob (= 5.1.3)
mail (~> 2.5, >= 2.5.4)
- rails-dom-testing (~> 1.0, >= 1.0.5)
- actionpack (4.2.8)
- actionview (= 4.2.8)
- activesupport (= 4.2.8)
- rack (~> 1.6)
- rack-test (~> 0.6.2)
- rails-dom-testing (~> 1.0, >= 1.0.5)
+ rails-dom-testing (~> 2.0)
+ actionpack (5.1.3)
+ actionview (= 5.1.3)
+ activesupport (= 5.1.3)
+ rack (~> 2.0)
+ rack-test (~> 0.6.3)
+ rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.2)
- actionview (4.2.8)
- activesupport (= 4.2.8)
+ actionview (5.1.3)
+ activesupport (= 5.1.3)
builder (~> 3.1)
- erubis (~> 2.7.0)
- rails-dom-testing (~> 1.0, >= 1.0.5)
+ erubi (~> 1.4)
+ rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.3)
- active_model_serializers (0.9.5)
+ active_model_serializers (0.9.7)
activemodel (>= 3.2)
- activejob (4.2.8)
- activesupport (= 4.2.8)
- globalid (>= 0.3.0)
- activemodel (4.2.8)
- activesupport (= 4.2.8)
- builder (~> 3.1)
- activerecord (4.2.8)
- activemodel (= 4.2.8)
- activesupport (= 4.2.8)
- arel (~> 6.0)
- activerecord-import (0.17.1)
+ concurrent-ruby (~> 1.0)
+ activejob (5.1.3)
+ activesupport (= 5.1.3)
+ globalid (>= 0.3.6)
+ activemodel (5.1.3)
+ activesupport (= 5.1.3)
+ activerecord (5.1.3)
+ activemodel (= 5.1.3)
+ activesupport (= 5.1.3)
+ arel (~> 8.0)
+ activerecord-import (0.19.1)
activerecord (>= 3.2)
- activesupport (4.2.8)
+ activesupport (5.1.3)
+ concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (~> 0.7)
minitest (~> 5.1)
- thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1)
- acts-as-taggable-on (3.5.0)
- activerecord (>= 3.2, < 5)
- acts_as_api (1.0.0)
+ acts-as-taggable-on (5.0.0)
+ activerecord (>= 4.2.8)
+ acts_as_api (1.0.1)
activemodel (>= 3.0.0)
activesupport (>= 3.0.0)
rack (>= 1.1.0)
- addressable (2.5.0)
+ addressable (2.5.1)
public_suffix (~> 2.0, >= 2.0.2)
- arel (6.0.4)
- asset_sync (2.0.0)
- activemodel
+ arel (8.0.0)
+ asset_sync (2.2.0)
+ activemodel (>= 4.1.0)
fog-core
- mime-types
+ mime-types (>= 2.99)
unf
ast (2.3.0)
attr_required (1.0.1)
- autoprefixer-rails (6.7.6)
+ autoprefixer-rails (7.1.2.4)
execjs
bcrypt (3.1.11)
- bindata (2.3.5)
+ bindata (2.4.0)
bootstrap-sass (3.3.7)
autoprefixer-rails (>= 5.2.1)
sass (>= 3.3.4)
@@ -67,19 +71,17 @@ GEM
buftok (0.2.0)
builder (3.2.3)
byebug (9.0.6)
- capybara (2.12.1)
+ capybara (2.15.1)
addressable
- mime-types (>= 1.16)
+ mini_mime (>= 0.1.3)
nokogiri (>= 1.3.3)
rack (>= 1.0.0)
rack-test (>= 0.5.4)
xpath (~> 2.0)
- carrierwave (0.11.2)
- activemodel (>= 3.2.0)
- activesupport (>= 3.2.0)
- json (>= 1.7)
+ carrierwave (1.1.0)
+ activemodel (>= 4.0.0)
+ activesupport (>= 4.0.0)
mime-types (>= 1.16)
- mimemagic (>= 0.3.0)
celluloid (0.17.3)
celluloid-essentials
celluloid-extras
@@ -116,18 +118,18 @@ GEM
sass (>= 3.3.0, < 3.5)
compass-import-once (1.0.5)
sass (>= 3.2, < 3.5)
- compass-rails (2.0.5)
+ compass-rails (3.0.2)
compass (~> 1.0.0)
sass-rails (< 5.1)
- sprockets (< 2.13)
+ sprockets (< 4.0)
concurrent-ruby (1.0.5)
configurate (0.3.1)
connection_pool (2.2.1)
- coveralls (0.8.19)
+ coveralls (0.8.21)
json (>= 1.8, < 3)
- simplecov (~> 0.12.0)
+ simplecov (~> 0.14.1)
term-ansicolor (~> 1.3)
- thor (~> 0.19.1)
+ thor (~> 0.19.4)
tins (~> 1.6)
crack (0.4.3)
safe_yaml (~> 1.0.0)
@@ -145,59 +147,63 @@ GEM
rspec (>= 2.12.0)
cucumber-core (1.5.0)
gherkin (~> 4.0)
- cucumber-rails (1.4.5)
+ cucumber-rails (1.5.0)
capybara (>= 1.1.2, < 3)
cucumber (>= 1.3.8, < 4)
- mime-types (>= 1.16, < 4)
+ mime-types (>= 1.17, < 4)
nokogiri (~> 1.5)
- railties (>= 3, < 5.1)
+ railties (>= 4, < 5.2)
cucumber-wire (0.0.1)
- database_cleaner (1.5.3)
- devise (4.2.0)
+ database_cleaner (1.6.1)
+ devise (4.3.0)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
- railties (>= 4.1.0, < 5.1)
+ railties (>= 4.1.0, < 5.2)
responders
warden (~> 1.2.3)
devise_lastseenable (0.0.6)
devise
rails (>= 3.0.4)
diaspora-prosody-config (0.0.7)
- diaspora_federation (0.1.9)
- faraday (>= 0.9.0, < 0.12.0)
- faraday_middleware (>= 0.10.0, < 0.12.0)
+ diaspora_federation (0.2.1)
+ faraday (>= 0.9.0, < 0.13.0)
+ faraday_middleware (>= 0.10.0, < 0.13.0)
nokogiri (~> 1.6, >= 1.6.8)
typhoeus (~> 1.0)
valid (~> 1.0)
- diaspora_federation-rails (0.1.9)
- diaspora_federation (= 0.1.9)
- rails (>= 4.2, < 6)
- diaspora_federation-test (0.1.9)
- diaspora_federation (= 0.1.9)
- factory_girl (~> 4.7)
+ diaspora_federation-json_schema (0.2.1)
+ diaspora_federation-rails (0.2.1)
+ actionpack (>= 4.2, < 6)
+ diaspora_federation (= 0.2.1)
+ diaspora_federation-test (0.2.1)
+ diaspora_federation (= 0.2.1)
+ fabrication (~> 2.16.0)
uuid (~> 2.3.8)
diff-lcs (1.3)
docile (1.1.5)
- domain_name (0.5.20170223)
+ domain_name (0.5.20170404)
unf (>= 0.0.5, < 1.0.0)
entypo-rails (3.0.0)
railties (>= 4.1, < 6)
equalizer (0.0.11)
- erubis (2.7.0)
+ erubi (1.6.1)
eslintrb (2.1.0)
execjs
multi_json (>= 1.3)
rake
+ et-orbi (1.0.5)
+ tzinfo
ethon (0.10.1)
ffi (>= 1.3.0)
- excon (0.55.0)
+ excon (0.58.0)
execjs (2.7.0)
- eye (0.9.1)
+ eye (0.9.2)
celluloid (~> 0.17.3)
celluloid-io (~> 0.17.0)
sigar (~> 0.7.3)
state_machines
thor
+ fabrication (2.16.2)
factory_girl (4.8.0)
activesupport (>= 3.0.0)
factory_girl_rails (4.8.0)
@@ -211,35 +217,35 @@ GEM
faraday_middleware (0.11.0.1)
faraday (>= 0.7.4, < 1.0)
ffi (1.9.18)
- fixture_builder (0.4.1)
+ fixture_builder (0.5.0)
activerecord (>= 2)
activesupport (>= 2)
- fog-aws (1.2.1)
+ fog-aws (1.4.0)
fog-core (~> 1.38)
fog-json (~> 1.0)
fog-xml (~> 0.1)
ipaddress (~> 0.8)
- fog-core (1.43.0)
+ fog-core (1.45.0)
builder
- excon (~> 0.49)
+ excon (~> 0.58)
formatador (~> 0.2)
fog-json (1.0.2)
fog-core (~> 1.0)
multi_json (~> 1.10)
- fog-xml (0.1.2)
+ fog-xml (0.1.3)
fog-core
- nokogiri (~> 1.5, >= 1.5.11)
+ nokogiri (>= 1.5.11, < 2.0.0)
formatador (0.2.5)
fuubar (2.2.0)
rspec-core (~> 3.0)
ruby-progressbar (~> 1.4)
get_process_mem (0.2.1)
- gherkin (4.0.0)
- gitlab (4.0.0)
+ gherkin (4.1.3)
+ gitlab (4.2.0)
httparty
- terminal-table (= 1.7.1)
- globalid (0.3.7)
- activesupport (>= 4.1.0)
+ terminal-table
+ globalid (0.4.0)
+ activesupport (>= 4.2.0)
gon (6.1.0)
actionpack (>= 3.0)
json
@@ -263,44 +269,43 @@ GEM
guard (~> 2.1)
guard-compat (~> 1.1)
rspec (>= 2.99.0, < 4.0)
- guard-rubocop (1.2.0)
+ guard-rubocop (1.3.0)
guard (~> 2.0)
rubocop (~> 0.20)
- haml (4.0.7)
+ haml (5.0.2)
+ temple (>= 0.8.0)
tilt
- haml_lint (0.24.0)
+ haml_lint (0.26.0)
haml (>= 4.0, < 5.1)
rainbow
rake (>= 10, < 13)
- rubocop (>= 0.47.0)
+ rubocop (>= 0.49.0)
sysexits (~> 1.1)
- hamlit (2.8.0)
+ hamlit (2.8.4)
temple (>= 0.8.0)
thor
tilt
- handlebars_assets (0.23.1)
+ handlebars_assets (0.23.2)
execjs (~> 2.0)
- multi_json (~> 1.0)
sprockets (>= 2.0.0)
tilt (>= 1.2)
- hashdiff (0.3.2)
- hashie (3.5.5)
- hike (1.2.3)
- hitimes (1.2.4)
- http (2.2.1)
+ hashdiff (0.3.5)
+ hashie (3.5.6)
+ hitimes (1.2.6)
+ http (2.2.2)
addressable (~> 2.3)
http-cookie (~> 1.0)
http-form_data (~> 1.0.1)
http_parser.rb (~> 0.6.0)
http-cookie (1.0.3)
domain_name (~> 0.5)
- http-form_data (1.0.1)
- http_accept_language (2.1.0)
+ http-form_data (1.0.3)
+ http_accept_language (2.1.1)
http_parser.rb (0.6.0)
httparty (0.14.0)
multi_xml (>= 0.5.2)
httpclient (2.8.3)
- i18n (0.8.1)
+ i18n (0.8.6)
i18n-inflector (2.6.7)
i18n (>= 0.4.1)
i18n-inflector-rails (1.0.7)
@@ -308,26 +313,25 @@ GEM
i18n-inflector (~> 2.6)
railties (>= 3.0.0)
ipaddress (0.8.3)
- jasmine (2.5.2)
- jasmine-core (>= 2.5.1, < 3.0.0)
+ jasmine (2.7.0)
+ jasmine-core (>= 2.7.0, < 3.0.0)
phantomjs
rack (>= 1.2.1)
rake
- jasmine-core (2.5.2)
+ jasmine-core (2.7.0)
jasmine-jquery-rails (2.0.3)
- jquery-rails (4.2.1)
+ jquery-rails (4.3.1)
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
- jquery-ui-rails (5.0.5)
- railties (>= 3.2.16)
js-routes (1.3.3)
railties (>= 3.2)
sprockets-rails
- js_image_paths (0.1.0)
- rails (~> 4.0)
- json (1.8.6)
- json-jwt (1.7.1)
+ js_image_paths (0.1.1)
+ rails (>= 4.0, < 6.0)
+ sprockets (>= 3.0.0)
+ json (2.1.0)
+ json-jwt (1.7.2)
activesupport
bindata
multi_json (>= 1.3)
@@ -335,27 +339,31 @@ GEM
url_safe_base64
json-schema (2.8.0)
addressable (>= 2.4)
- jsonpath (0.5.8)
+ json-schema-rspec (0.0.4)
+ json-schema (~> 2.5)
+ rspec
+ jsonpath (0.8.7)
multi_json
jwt (1.5.6)
kgio (2.11.0)
- leaflet-rails (0.7.7)
+ leaflet-rails (1.1.0)
+ rails (>= 4.2.0)
listen (3.1.5)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
ruby_dep (~> 1.2)
little-plugger (1.1.4)
- logging (2.1.0)
+ logging (2.2.2)
little-plugger (~> 1.1)
multi_json (~> 1.10)
- logging-rails (0.5.0)
+ logging-rails (0.6.0)
logging (>= 1.8)
loofah (2.0.3)
nokogiri (>= 1.5.9)
- lumberjack (1.0.11)
+ lumberjack (1.0.12)
macaddr (1.7.1)
systemu (~> 2.6.2)
- mail (2.6.4)
+ mail (2.6.6)
mime-types (>= 1.16, < 4)
markerb (1.1.0)
memoizable (0.4.2)
@@ -364,38 +372,38 @@ GEM
mime-types (3.1)
mime-types-data (~> 3.2015)
mime-types-data (3.2016.0521)
- mimemagic (0.3.2)
- mini_magick (4.6.1)
- mini_portile2 (2.1.0)
- minitest (5.10.1)
- mobile-fu (1.3.1)
+ mini_magick (4.8.0)
+ mini_mime (0.1.4)
+ mini_portile2 (2.2.0)
+ minitest (5.10.3)
+ mobile_fu (1.4.0)
rack-mobile-detect
rails
multi_json (1.12.1)
multi_test (0.1.2)
multi_xml (0.6.0)
multipart-post (2.0.0)
- mysql2 (0.4.5)
+ mysql2 (0.4.9)
naught (1.1.0)
nenv (0.3.0)
- nio4r (2.0.0)
- nokogiri (1.7.2)
- mini_portile2 (~> 2.1.0)
+ nio4r (2.1.0)
+ nokogiri (1.8.0)
+ mini_portile2 (~> 2.2.0)
notiffany (0.1.1)
nenv (~> 0.1)
shellany (~> 0.0)
- oauth (0.5.1)
- oauth2 (1.3.1)
- faraday (>= 0.8, < 0.12)
+ oauth (0.5.3)
+ oauth2 (1.4.0)
+ faraday (>= 0.8, < 0.13)
jwt (~> 1.0)
multi_json (~> 1.3)
multi_xml (~> 0.5)
rack (>= 1.2, < 3)
octokit (4.7.0)
sawyer (~> 0.8.0, >= 0.5.3)
- omniauth (1.4.2)
- hashie (>= 1.2, < 4)
- rack (>= 1.0, < 3)
+ omniauth (1.6.1)
+ hashie (>= 3.4.6, < 3.6.0)
+ rack (>= 1.6.2, < 3)
omniauth-facebook (4.0.0)
omniauth-oauth2 (~> 1.2)
omniauth-oauth (1.1.0)
@@ -415,28 +423,29 @@ GEM
open_graph_reader (0.6.2)
faraday (>= 0.9.0)
nokogiri (~> 1.6)
- openid_connect (0.12.0)
+ openid_connect (1.1.3)
activemodel
attr_required (>= 1.0.0)
json (>= 1.4.3)
json-jwt (>= 1.5.0)
- rack-oauth2 (>= 1.3.1)
+ rack-oauth2 (>= 1.6.1)
swd (>= 1.0.0)
tzinfo
validate_email
validate_url
webfinger (>= 1.0.1)
orm_adapter (0.5.0)
+ parallel (1.12.0)
parser (2.4.0.0)
ast (~> 2.2)
- pg (0.19.0)
+ pg (0.21.0)
phantomjs (2.1.1.0)
- poltergeist (1.13.0)
+ poltergeist (1.16.0)
capybara (~> 2.1)
cliver (~> 0.3.1)
websocket-driver (>= 0.2.0)
powerpack (0.1.1)
- pronto (0.9.3)
+ pronto (0.9.4)
gitlab (~> 4.0, >= 4.0.0)
httparty (>= 0.13.7, < 0.15)
octokit (~> 4.7, >= 4.7.0)
@@ -463,44 +472,43 @@ GEM
byebug (~> 9.0)
pry (~> 0.10)
public_suffix (2.0.5)
- quiet_assets (1.1.0)
- railties (>= 3.1, < 5.0)
- rack (1.6.5)
- rack-cors (0.4.1)
+ rack (2.0.3)
+ rack-cors (1.0.1)
rack-google-analytics (1.2.0)
actionpack
activesupport
rack-mobile-detect (0.4.0)
rack
- rack-oauth2 (1.5.1)
+ rack-oauth2 (1.6.2)
activesupport (>= 2.3)
attr_required (>= 0.0.5)
httpclient (>= 2.4)
multi_json (>= 1.3.6)
rack (>= 1.1)
rack-piwik (0.3.0)
- rack-protection (1.5.3)
+ rack-protection (2.0.0)
rack
rack-rewrite (1.5.1)
rack-ssl (1.4.1)
rack
rack-test (0.6.3)
rack (>= 1.0)
- rails (4.2.8)
- actionmailer (= 4.2.8)
- actionpack (= 4.2.8)
- actionview (= 4.2.8)
- activejob (= 4.2.8)
- activemodel (= 4.2.8)
- activerecord (= 4.2.8)
- activesupport (= 4.2.8)
- bundler (>= 1.3.0, < 2.0)
- railties (= 4.2.8)
- sprockets-rails
- rails-assets-autosize (3.0.20)
+ rails (5.1.3)
+ actioncable (= 5.1.3)
+ actionmailer (= 5.1.3)
+ actionpack (= 5.1.3)
+ actionview (= 5.1.3)
+ activejob (= 5.1.3)
+ activemodel (= 5.1.3)
+ activerecord (= 5.1.3)
+ activesupport (= 5.1.3)
+ bundler (>= 1.3.0)
+ railties (= 5.1.3)
+ sprockets-rails (>= 2.0.0)
+ rails-assets-autosize (4.0.0)
rails-assets-backbone (1.3.3)
rails-assets-underscore (>= 1.8.3)
- rails-assets-blueimp-gallery (2.25.0)
+ rails-assets-blueimp-gallery (2.25.2)
rails-assets-bootstrap (3.3.7)
rails-assets-jquery (>= 1.9.1, < 4)
rails-assets-bootstrap-markdown (2.10.0)
@@ -517,11 +525,11 @@ GEM
rails-assets-emojione (2.0.1)
rails-assets-favico.js (0.3.10)
rails-assets-fine-uploader (5.13.0)
- rails-assets-highlightjs (9.9.0)
- rails-assets-jasmine (2.5.2)
+ rails-assets-highlightjs (9.12.0)
+ rails-assets-jasmine (2.7.0)
rails-assets-jasmine-ajax (3.3.1)
rails-assets-jasmine (~> 2)
- rails-assets-jquery (2.2.4)
+ rails-assets-jquery (3.2.1)
rails-assets-jquery-colorbox (1.6.4)
rails-assets-jquery (>= 1.3.2)
rails-assets-jquery-fullscreen-plugin (0.5.0)
@@ -535,83 +543,86 @@ GEM
rails-assets-jquery.ui (1.11.4)
rails-assets-jquery (>= 1.6)
rails-assets-markdown-it--markdown-it-for-inline (0.1.1)
- rails-assets-markdown-it (8.3.0)
- rails-assets-markdown-it-diaspora-mention (1.1.1)
+ rails-assets-markdown-it (8.3.2)
+ rails-assets-markdown-it-diaspora-mention (1.2.0)
rails-assets-markdown-it-hashtag (0.4.0)
rails-assets-markdown-it-sanitizer (0.4.3)
rails-assets-markdown-it-sub (1.0.0)
rails-assets-markdown-it-sup (1.0.0)
rails-assets-perfect-scrollbar (0.6.16)
rails-assets-underscore (1.8.3)
- rails-deprecated_sanitizer (1.0.3)
- activesupport (>= 4.2.0.alpha)
- rails-dom-testing (1.0.8)
- activesupport (>= 4.2.0.beta, < 5.0)
- nokogiri (~> 1.6)
- rails-deprecated_sanitizer (>= 1.0.1)
+ rails-controller-testing (1.0.2)
+ actionpack (~> 5.x, >= 5.0.1)
+ actionview (~> 5.x, >= 5.0.1)
+ activesupport (~> 5.x)
+ rails-dom-testing (2.0.3)
+ activesupport (>= 4.2.0)
+ nokogiri (>= 1.6)
rails-html-sanitizer (1.0.3)
loofah (~> 2.0)
- rails-i18n (4.0.8)
+ rails-i18n (5.0.4)
i18n (~> 0.7)
- railties (~> 4.0)
+ railties (~> 5.0)
rails-timeago (2.16.0)
actionpack (>= 3.1)
activesupport (>= 3.1)
- railties (4.2.8)
- actionpack (= 4.2.8)
- activesupport (= 4.2.8)
+ railties (5.1.3)
+ actionpack (= 5.1.3)
+ activesupport (= 5.1.3)
+ method_source
rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0)
rainbow (2.2.2)
rake
- raindrops (0.17.0)
+ raindrops (0.19.0)
rake (12.0.0)
- rb-fsevent (0.9.8)
- rb-inotify (0.9.8)
- ffi (>= 0.5.0)
+ rb-fsevent (0.10.2)
+ rb-inotify (0.9.10)
+ ffi (>= 0.5.0, < 2)
redcarpet (3.4.0)
redis (3.3.3)
- redis-namespace (1.5.3)
- redis (~> 3.0, >= 3.0.4)
request_store (1.3.2)
- responders (2.3.0)
- railties (>= 4.2.0, < 5.1)
- rspec (3.5.0)
- rspec-core (~> 3.5.0)
- rspec-expectations (~> 3.5.0)
- rspec-mocks (~> 3.5.0)
- rspec-core (3.5.4)
- rspec-support (~> 3.5.0)
- rspec-expectations (3.5.0)
+ responders (2.4.0)
+ actionpack (>= 4.2.0, < 5.3)
+ railties (>= 4.2.0, < 5.3)
+ rspec (3.6.0)
+ rspec-core (~> 3.6.0)
+ rspec-expectations (~> 3.6.0)
+ rspec-mocks (~> 3.6.0)
+ rspec-core (3.6.0)
+ rspec-support (~> 3.6.0)
+ rspec-expectations (3.6.0)
diff-lcs (>= 1.2.0, < 2.0)
- rspec-support (~> 3.5.0)
- rspec-mocks (3.5.0)
+ rspec-support (~> 3.6.0)
+ rspec-json_expectations (2.1.0)
+ rspec-mocks (3.6.0)
diff-lcs (>= 1.2.0, < 2.0)
- rspec-support (~> 3.5.0)
- rspec-rails (3.5.2)
+ rspec-support (~> 3.6.0)
+ rspec-rails (3.6.1)
actionpack (>= 3.0)
activesupport (>= 3.0)
railties (>= 3.0)
- rspec-core (~> 3.5.0)
- rspec-expectations (~> 3.5.0)
- rspec-mocks (~> 3.5.0)
- rspec-support (~> 3.5.0)
- rspec-support (3.5.0)
- rubocop (0.48.1)
+ rspec-core (~> 3.6.0)
+ rspec-expectations (~> 3.6.0)
+ rspec-mocks (~> 3.6.0)
+ rspec-support (~> 3.6.0)
+ rspec-support (3.6.0)
+ rubocop (0.49.1)
+ parallel (~> 1.10)
parser (>= 2.3.3.1, < 3.0)
powerpack (~> 0.1)
rainbow (>= 1.99.1, < 3.0)
ruby-progressbar (~> 1.7)
unicode-display_width (~> 1.0, >= 1.0.1)
- ruby-oembed (0.10.1)
+ ruby-oembed (0.12.0)
ruby-progressbar (1.8.1)
ruby_dep (1.5.0)
rubyzip (1.2.1)
- rufus-scheduler (3.3.4)
- tzinfo
- rugged (0.25.1.1)
+ rufus-scheduler (3.4.2)
+ et-orbi (~> 1.0)
+ rugged (0.26.0)
safe_yaml (1.0.4)
- sass (3.4.23)
+ sass (3.4.25)
sass-rails (5.0.6)
railties (>= 4.0.0, < 6)
sass (~> 3.1)
@@ -621,52 +632,49 @@ GEM
sawyer (0.8.1)
addressable (>= 2.3.5, < 2.6)
faraday (~> 0.8, < 1.0)
- scss_lint (0.53.0)
+ scss_lint (0.54.0)
rake (>= 0.9, < 13)
sass (~> 3.4.20)
- secure_headers (3.6.1)
+ secure_headers (3.6.7)
useragent
securecompare (1.0.0)
shellany (0.0.1)
- shoulda-matchers (3.1.1)
+ shoulda-matchers (3.1.2)
activesupport (>= 4.0.0)
- sidekiq (4.2.9)
+ sidekiq (5.0.4)
concurrent-ruby (~> 1.0)
connection_pool (~> 2.2, >= 2.2.0)
rack-protection (>= 1.5.0)
- redis (~> 3.2, >= 3.2.1)
- sidekiq-cron (0.4.5)
- redis-namespace (>= 1.5.2)
- rufus-scheduler (>= 2.0.24)
+ redis (~> 3.3, >= 3.3.3)
+ sidekiq-cron (0.6.3)
+ rufus-scheduler (>= 3.3.0)
sidekiq (>= 4.2.1)
sigar (0.7.3)
simple_captcha2 (0.4.3)
rails (>= 4.1)
simple_oauth (0.3.1)
- simplecov (0.12.0)
+ simplecov (0.14.1)
docile (~> 1.1.0)
json (>= 1.8, < 3)
simplecov-html (~> 0.10.0)
- simplecov-html (0.10.0)
+ simplecov-html (0.10.1)
sinon-rails (1.15.0)
railties (>= 3.1)
slop (3.6.0)
- spring (2.0.1)
+ spring (2.0.2)
activesupport (>= 4.2)
spring-commands-cucumber (1.0.1)
spring (>= 0.9.1)
spring-commands-rspec (1.0.4)
spring (>= 0.9.1)
- sprockets (2.12.4)
- hike (~> 1.2)
- multi_json (~> 1.0)
- rack (~> 1.0)
- tilt (~> 1.1, != 1.3.0)
- sprockets-rails (2.3.3)
- actionpack (>= 3.0)
- activesupport (>= 3.0)
- sprockets (>= 2.8, < 4.0)
- state_machines (0.4.0)
+ sprockets (3.7.1)
+ concurrent-ruby (~> 1.0)
+ rack (> 1, < 3)
+ sprockets-rails (3.2.0)
+ actionpack (>= 4.0)
+ activesupport (>= 4.0)
+ sprockets (>= 3.0.0)
+ state_machines (0.5.0)
string-direction (1.2.0)
yard (~> 0.8)
swd (1.0.1)
@@ -678,19 +686,17 @@ GEM
sysexits (1.2.0)
systemu (2.6.5)
temple (0.8.0)
- term-ansicolor (1.4.0)
+ term-ansicolor (1.6.0)
tins (~> 1.0)
- terminal-table (1.7.1)
- unicode-display_width (~> 1.1.1)
- test_after_commit (1.1.0)
- activerecord (>= 3.2)
- thor (0.19.1)
+ terminal-table (1.8.0)
+ unicode-display_width (~> 1.1, >= 1.1.1)
+ thor (0.19.4)
thread_safe (0.3.6)
- tilt (1.4.1)
- timecop (0.8.1)
+ tilt (2.0.8)
+ timecop (0.9.1)
timers (4.1.2)
hitimes
- tins (1.13.2)
+ tins (1.15.0)
turbo_dev_assets (0.0.2)
twitter (6.1.0)
addressable (~> 2.5)
@@ -702,19 +708,19 @@ GEM
memoizable (~> 0.4.2)
naught (~> 1.1)
simple_oauth (~> 0.3.1)
- twitter-text (1.14.5)
+ twitter-text (1.14.7)
unf (~> 0.1.0)
typhoeus (1.1.2)
ethon (>= 0.9.0)
tzinfo (1.2.3)
thread_safe (~> 0.1)
- uglifier (3.1.2)
+ uglifier (3.2.0)
execjs (>= 0.3.0, < 3)
unf (0.1.4)
unf_ext
- unf_ext (0.0.7.2)
- unicode-display_width (1.1.3)
- unicorn (5.2.0)
+ unf_ext (0.0.7.4)
+ unicode-display_width (1.3.0)
+ unicorn (5.3.0)
kgio (~> 2.6)
raindrops (~> 0.7)
unicorn-worker-killer (0.4.4)
@@ -731,7 +737,7 @@ GEM
validate_url (1.0.2)
activemodel (>= 3.0.0)
addressable
- versionist (1.5.0)
+ versionist (1.6.0)
activesupport (>= 3)
railties (>= 3)
yard (~> 0.7)
@@ -741,159 +747,161 @@ GEM
activesupport
httpclient (>= 2.4)
multi_json
- webmock (2.3.2)
+ webmock (3.0.1)
addressable (>= 2.3.6)
crack (>= 0.3.2)
hashdiff
websocket-driver (0.6.5)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.2)
- will_paginate (3.1.5)
- xpath (2.0.0)
+ will_paginate (3.1.6)
+ xpath (2.1.0)
nokogiri (~> 1.3)
- yard (0.9.8)
+ yard (0.9.9)
PLATFORMS
ruby
DEPENDENCIES
- active_model_serializers (= 0.9.5)
- activerecord-import (= 0.17.1)
- acts-as-taggable-on (= 3.5.0)
- acts_as_api (= 1.0.0)
- addressable (= 2.5.0)
- asset_sync (= 2.0.0)
- autoprefixer-rails (= 6.7.6)
+ active_model_serializers (= 0.9.7)
+ activerecord-import (= 0.19.1)
+ acts-as-taggable-on (= 5.0.0)
+ acts_as_api (= 1.0.1)
+ addressable (= 2.5.1)
+ asset_sync (= 2.2.0)
+ autoprefixer-rails (= 7.1.2.4)
bootstrap-sass (= 3.3.7)
bootstrap-switch-rails (= 3.3.3)
- capybara (= 2.12.1)
- carrierwave (= 0.11.2)
- compass-rails (= 2.0.5)
+ capybara (= 2.15.1)
+ carrierwave (= 1.1.0)
+ compass-rails (= 3.0.2)
configurate (= 0.3.1)
- coveralls
+ coveralls (= 0.8.21)
cucumber-api-steps (= 0.13)
- cucumber-rails (= 1.4.5)
- database_cleaner (= 1.5.3)
- devise (= 4.2.0)
+ cucumber-rails (= 1.5.0)
+ database_cleaner (= 1.6.1)
+ devise (= 4.3.0)
devise_lastseenable (= 0.0.6)
diaspora-prosody-config (= 0.0.7)
- diaspora_federation-rails (= 0.1.9)
- diaspora_federation-test (= 0.1.9)
+ diaspora_federation-json_schema (= 0.2.1)
+ diaspora_federation-rails (= 0.2.1)
+ diaspora_federation-test (= 0.2.1)
entypo-rails (= 3.0.0)
- eye (= 0.9.1)
+ eye (= 0.9.2)
factory_girl_rails (= 4.8.0)
faraday (= 0.11.0)
faraday-cookie_jar (= 0.0.6)
faraday_middleware (= 0.11.0.1)
- fixture_builder (= 0.4.1)
- fog-aws (= 1.2.1)
+ fixture_builder (= 0.5.0)
+ fog-aws (= 1.4.0)
fuubar (= 2.2.0)
gon (= 6.1.0)
guard (= 2.14.1)
guard-cucumber (= 2.1.2)
guard-rspec (= 4.7.3)
- guard-rubocop (= 1.2.0)
- haml_lint (= 0.24.0)
- hamlit (= 2.8.0)
- handlebars_assets (= 0.23.1)
- http_accept_language (= 2.1.0)
+ guard-rubocop (= 1.3.0)
+ haml_lint (= 0.26.0)
+ hamlit (= 2.8.4)
+ handlebars_assets (= 0.23.2)
+ http_accept_language (= 2.1.1)
i18n-inflector-rails (= 1.0.7)
- jasmine (= 2.5.2)
+ jasmine (= 2.7.0)
jasmine-jquery-rails (= 2.0.3)
- jquery-rails (= 4.2.1)
- jquery-ui-rails (= 5.0.5)
+ jquery-rails (= 4.3.1)
js-routes (= 1.3.3)
- js_image_paths (= 0.1.0)
- json (= 1.8.6)
+ js_image_paths (= 0.1.1)
+ json (= 2.1.0)
json-schema (= 2.8.0)
- leaflet-rails (= 0.7.7)
- logging-rails (= 0.5.0)
+ json-schema-rspec (= 0.0.4)
+ leaflet-rails (= 1.1.0)
+ logging-rails (= 0.6.0)
markerb (= 1.1.0)
- mini_magick (= 4.6.1)
+ mini_magick (= 4.8.0)
minitest
- mobile-fu (= 1.3.1)
- mysql2 (= 0.4.5)
- nokogiri (= 1.7.2)
- omniauth (= 1.4.2)
+ mobile_fu (= 1.4.0)
+ mysql2 (= 0.4.9)
+ nokogiri (= 1.8.0)
+ omniauth (= 1.6.1)
omniauth-facebook (= 4.0.0)
omniauth-tumblr (= 1.2)
omniauth-twitter (= 1.4.0)
omniauth-wordpress (= 0.2.2)
open_graph_reader (= 0.6.2)
- openid_connect (= 0.12.0)
- pg (= 0.19.0)
- poltergeist (= 1.13.0)
- pronto (= 0.9.3)
+ openid_connect (= 1.1.3)
+ pg (= 0.21.0)
+ poltergeist (= 1.16.0)
+ pronto (= 0.9.4)
pronto-eslint (= 0.9.1)
pronto-haml (= 0.9.0)
pronto-rubocop (= 0.9.0)
pronto-scss (= 0.9.1)
pry
pry-byebug
- quiet_assets (= 1.1.0)
- rack-cors (= 0.4.1)
+ rack-cors (= 1.0.1)
rack-google-analytics (= 1.2.0)
rack-piwik (= 0.3.0)
rack-rewrite (= 1.5.1)
rack-ssl (= 1.4.1)
- rails (= 4.2.8)
- rails-assets-autosize (= 3.0.20)!
+ rails (= 5.1.3)
+ rails-assets-autosize (= 4.0.0)!
rails-assets-backbone (= 1.3.3)!
- rails-assets-blueimp-gallery (= 2.25.0)!
+ rails-assets-blueimp-gallery (= 2.25.2)!
rails-assets-bootstrap-markdown (= 2.10.0)!
rails-assets-corejs-typeahead (= 1.1.1)!
rails-assets-diaspora_jsxc (= 0.1.5.develop.7)!
rails-assets-fine-uploader (= 5.13.0)!
- rails-assets-highlightjs (= 9.9.0)!
+ rails-assets-highlightjs (= 9.12.0)!
rails-assets-jasmine-ajax (= 3.3.1)!
- rails-assets-jquery (= 2.2.4)!
+ rails-assets-jquery (= 3.2.1)!
rails-assets-jquery-placeholder (= 2.3.1)!
rails-assets-jquery-textchange (= 0.2.3)!
rails-assets-jquery.are-you-sure (= 1.9.0)!
- rails-assets-markdown-it (= 8.3.0)!
+ rails-assets-jquery.ui (= 1.11.4)!
+ rails-assets-markdown-it (= 8.3.2)!
rails-assets-markdown-it--markdown-it-for-inline (= 0.1.1)!
- rails-assets-markdown-it-diaspora-mention (= 1.1.1)!
+ rails-assets-markdown-it-diaspora-mention (= 1.2.0)!
rails-assets-markdown-it-hashtag (= 0.4.0)!
rails-assets-markdown-it-sanitizer (= 0.4.3)!
rails-assets-markdown-it-sub (= 1.0.0)!
rails-assets-markdown-it-sup (= 1.0.0)!
rails-assets-perfect-scrollbar (= 0.6.16)!
- rails-i18n (= 4.0.8)
+ rails-controller-testing (= 1.0.2)
+ rails-i18n (= 5.0.4)
rails-timeago (= 2.16.0)
- rb-fsevent (= 0.9.8)
- rb-inotify (= 0.9.8)
+ rb-fsevent (= 0.10.2)
+ rb-inotify (= 0.9.10)
redcarpet (= 3.4.0)
- responders (= 2.3.0)
- rspec-rails (= 3.5.2)
- rubocop (= 0.48.1)
- ruby-oembed (= 0.10.1)
+ responders (= 2.4.0)
+ rspec-json_expectations (~> 2.1)
+ rspec-rails (= 3.6.1)
+ rubocop (= 0.49.1)
+ ruby-oembed (= 0.12.0)
rubyzip (= 1.2.1)
sass-rails (= 5.0.6)
- secure_headers (= 3.6.1)
- shoulda-matchers (= 3.1.1)
- sidekiq (= 4.2.9)
- sidekiq-cron (= 0.4.5)
+ secure_headers (= 3.6.7)
+ shoulda-matchers (= 3.1.2)
+ sidekiq (= 5.0.4)
+ sidekiq-cron (= 0.6.3)
simple_captcha2 (= 0.4.3)
- simplecov (= 0.12.0)
+ simplecov (= 0.14.1)
sinon-rails (= 1.15.0)
- spring (= 2.0.1)
+ spring (= 2.0.2)
spring-commands-cucumber (= 1.0.1)
spring-commands-rspec (= 1.0.4)
+ sprockets-rails (= 3.2.0)
string-direction (= 1.2.0)
- test_after_commit (= 1.1.0)
- thor (= 0.19.1)
- timecop (= 0.8.1)
+ timecop (= 0.9.1)
turbo_dev_assets (= 0.0.2)
twitter (= 6.1.0)
- twitter-text (= 1.14.5)
+ twitter-text (= 1.14.7)
typhoeus (= 1.1.2)
- uglifier (= 3.1.2)
- unicorn (= 5.2.0)
+ uglifier (= 3.2.0)
+ unicorn (= 5.3.0)
unicorn-worker-killer (= 0.4.4)
uuid (= 2.3.8)
- versionist (= 1.5.0)
- webmock (= 2.3.2)
- will_paginate (= 3.1.5)
+ versionist (= 1.6.0)
+ webmock (= 3.0.1)
+ will_paginate (= 3.1.6)
BUNDLED WITH
- 1.14.5
+ 1.15.3
diff --git a/app/assets/javascripts/app/app.js b/app/assets/javascripts/app/app.js
index 57066f68d..1360e952e 100644
--- a/app/assets/javascripts/app/app.js
+++ b/app/assets/javascripts/app/app.js
@@ -121,12 +121,6 @@ var app = {
app.flashMessages = new app.views.FlashMessages({el: $("#flash-container")});
},
- /* mixpanel wrapper function */
- instrument : function(type, name, object, callback) {
- if(!window.mixpanel) { return; }
- window.mixpanel[type](name, object, callback);
- },
-
setupDisabledLinks: function() {
$("a.disabled").click(function(event) {
event.preventDefault();
diff --git a/app/assets/javascripts/app/models/post.js b/app/assets/javascripts/app/models/post.js
index c351ee787..b693d7b2d 100644
--- a/app/assets/javascripts/app/models/post.js
+++ b/app/assets/javascripts/app/models/post.js
@@ -48,12 +48,6 @@ app.models.Post = Backbone.Model.extend(_.extend({}, app.models.formatDateMixin,
var body = this.get("text").trim()
, newlineIdx = body.indexOf("\n");
return (newlineIdx > 0 ) ? body.substr(newlineIdx+1, body.length) : "";
- },
-
- //returns a promise
- preloadOrFetch : function(){
- var action = app.hasPreload("post") ? this.set(app.parsePreload("post")) : this.fetch();
- return $.when(action);
}
}));
// @license-end
diff --git a/app/assets/javascripts/app/models/post/interactions.js b/app/assets/javascripts/app/models/post/interactions.js
index 3615387e2..5770b3291 100644
--- a/app/assets/javascripts/app/models/post/interactions.js
+++ b/app/assets/javascripts/app/models/post/interactions.js
@@ -3,10 +3,6 @@
//require ../post
app.models.Post.Interactions = Backbone.Model.extend({
- url : function(){
- return this.post.url() + "/interactions";
- },
-
initialize : function(options){
this.post = options.post;
this.comments = new app.collections.Comments(this.get("comments"), {post : this.post});
@@ -14,33 +10,16 @@ app.models.Post.Interactions = Backbone.Model.extend({
this.reshares = new app.collections.Reshares(this.get("reshares"), {post : this.post});
},
- parse : function(resp){
- this.comments.reset(resp.comments);
- this.likes.reset(resp.likes);
- this.reshares.reset(resp.reshares);
-
- var comments = this.comments
- , likes = this.likes
- , reshares = this.reshares;
-
- return {
- comments : comments,
- likes : likes,
- reshares : reshares,
- fetched : true
- };
- },
-
likesCount : function(){
- return this.get("fetched") ? this.likes.models.length : this.get("likes_count");
+ return this.get("likes_count");
},
resharesCount : function(){
- return this.get("fetched") ? this.reshares.models.length : this.get("reshares_count");
+ return this.get("reshares_count");
},
commentsCount : function(){
- return this.get("fetched") ? this.comments.models.length : this.get("comments_count");
+ return this.get("comments_count");
},
userLike : function(){
@@ -76,8 +55,6 @@ app.models.Post.Interactions = Backbone.Model.extend({
app.flashMessages.handleAjaxError(response);
}
});
-
- app.instrument("track", "Like");
},
unlike : function() {
@@ -87,8 +64,6 @@ app.models.Post.Interactions = Backbone.Model.extend({
self.set({"likes_count" : self.get("likes_count") - 1});
self.likes.trigger("change");
}});
-
- app.instrument("track", "Unlike");
},
comment: function(text, options) {
@@ -104,8 +79,6 @@ app.models.Post.Interactions = Backbone.Model.extend({
self.trigger('change'); //updates after sync
if (options.success) { options.success(); }
});
-
- app.instrument("track", "Comment");
},
reshare : function(){
@@ -126,8 +99,6 @@ app.models.Post.Interactions = Backbone.Model.extend({
.fail(function(response) {
app.flashMessages.handleAjaxError(response);
});
-
- app.instrument("track", "Reshare");
},
userCanReshare : function(){
diff --git a/app/assets/javascripts/app/models/stream.js b/app/assets/javascripts/app/models/stream.js
index f1978eb76..119107144 100644
--- a/app/assets/javascripts/app/models/stream.js
+++ b/app/assets/javascripts/app/models/stream.js
@@ -13,8 +13,16 @@ app.models.Stream = Backbone.Collection.extend({
},
collectionOptions :function(){
- var order = this.sortOrder();
- return { comparator : function(item) { return -item[order](); } };
+ var order = this.sortOrder();
+ return {
+ comparator: function(item1, item2) {
+ if (item1[order]() < item2[order]()) { return 1; }
+ if (item1[order]() > item2[order]()) { return -1; }
+ if (item1.id < item2.id) { return 1; }
+ if (item1.id > item2.id) { return -1; }
+ return 0;
+ }
+ };
},
url : function(){
diff --git a/app/assets/javascripts/app/pages/single-post-viewer.js b/app/assets/javascripts/app/pages/single-post-viewer.js
index c5a30f1c9..f12f45a33 100644
--- a/app/assets/javascripts/app/pages/single-post-viewer.js
+++ b/app/assets/javascripts/app/pages/single-post-viewer.js
@@ -9,9 +9,8 @@ app.pages.SinglePostViewer = app.views.Base.extend({
},
initialize : function() {
- this.model = new app.models.Post({ id : gon.post.id });
- this.model.preloadOrFetch().done(_.bind(this.initViews, this));
- this.model.interactions.fetch(); //async, yo, might want to throttle this later.
+ this.model = new app.models.Post(gon.post);
+ this.initViews();
},
initViews : function() {
diff --git a/app/assets/javascripts/app/router.js b/app/assets/javascripts/app/router.js
index b189cad86..ab9e11a69 100644
--- a/app/assets/javascripts/app/router.js
+++ b/app/assets/javascripts/app/router.js
@@ -9,7 +9,7 @@ app.Router = Backbone.Router.extend({
"commented(/)": "stream",
"community_spotlight(/)": "spotlight",
"contacts(/)": "contacts",
- "conversations(/)(:id)(/)": "conversations",
+ "conversations(/)(:id)(?conversation_id=:conversation_id)(/)": "conversations",
"followed_tags(/)": "followed_tags",
"getting_started(/)": "gettingStarted",
"help(/)": "help",
@@ -93,8 +93,8 @@ app.Router = Backbone.Router.extend({
app.page = new app.pages.Contacts({stream: stream});
},
- conversations: function(id) {
- app.conversations = app.conversations || new app.views.ConversationsInbox();
+ conversations: function(id, conversationId) {
+ app.conversations = app.conversations || new app.views.ConversationsInbox(conversationId);
if (parseInt("" + id, 10)) {
app.conversations.renderConversation(id);
}
@@ -182,7 +182,7 @@ app.Router = Backbone.Router.extend({
},
singlePost: function(id) {
- this.renderPage(function() { return new app.pages.SinglePostViewer({id: id}); });
+ this.renderPage(function() { return new app.pages.SinglePostViewer({id: id, el: $("#container")}); });
},
spotlight: function() {
diff --git a/app/assets/javascripts/app/views/comment_mention_view.js b/app/assets/javascripts/app/views/comment_mention_view.js
new file mode 100644
index 000000000..52b125774
--- /dev/null
+++ b/app/assets/javascripts/app/views/comment_mention_view.js
@@ -0,0 +1,10 @@
+// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later
+//= require ./publisher/mention_view
+
+app.views.CommentMention = app.views.PublisherMention.extend({
+ initialize: function(opts) {
+ opts.url = Routes.mentionablePost(opts.postId);
+ app.views.PublisherMention.prototype.initialize.call(this, opts);
+ }
+});
+// @license-end
diff --git a/app/assets/javascripts/app/views/comment_stream_view.js b/app/assets/javascripts/app/views/comment_stream_view.js
index 05ba192db..2a1b81612 100644
--- a/app/assets/javascripts/app/views/comment_stream_view.js
+++ b/app/assets/javascripts/app/views/comment_stream_view.js
@@ -9,8 +9,8 @@ app.views.CommentStream = app.views.Base.extend({
events: {
"keydown .comment_box": "keyDownOnCommentBox",
"submit form": "createComment",
- "focus .comment_box": "commentTextareaFocused",
- "click .toggle_post_comments": "expandComments"
+ "click .toggle_post_comments": "expandComments",
+ "click form": "openForm"
},
initialize: function() {
@@ -21,12 +21,22 @@ app.views.CommentStream = app.views.Base.extend({
setupBindings: function() {
this.model.comments.bind("add", this.appendComment, this);
this.model.comments.bind("remove", this.removeComment, this);
+ $(document.body).click(this.onFormBlur.bind(this));
},
postRenderTemplate : function() {
this.model.comments.each(this.appendComment, this);
this.commentBox = this.$(".comment_box");
this.commentSubmitButton = this.$("input[name='commit']");
+ this.mentions = new app.views.CommentMention({el: this.$el, postId: this.model.get("id")});
+
+ this.mdEditor = new Diaspora.MarkdownEditor(this.$(".comment_box"), {
+ onPreview: function($mdInstance) {
+ var renderedText = app.helpers.textFormatter($mdInstance.getContent(), this.mentions.getMentionedPeople());
+ return "<div class='preview-content'>" + renderedText + "</div>";
+ }.bind(this),
+ onFocus: this.openForm.bind(this)
+ });
},
presenter: function(){
@@ -52,11 +62,14 @@ app.views.CommentStream = app.views.Base.extend({
success: function() {
this.commentBox.val("");
this.enableCommentBox();
+ this.mdEditor.hidePreview();
+ this.closeForm();
autosize.update(this.commentBox);
}.bind(this),
error: function() {
this.enableCommentBox();
- this.commentBox.focus();
+ this.mdEditor.hidePreview();
+ this.openForm();
}.bind(this)
});
},
@@ -72,7 +85,7 @@ app.views.CommentStream = app.views.Base.extend({
},
keyDownOnCommentBox: function(evt) {
- if(evt.which === Keycodes.ENTER && evt.ctrlKey) {
+ if (evt.which === Keycodes.ENTER && (evt.metaKey || evt.ctrlKey)) {
this.$("form").submit();
return false;
}
@@ -105,7 +118,8 @@ app.views.CommentStream = app.views.Base.extend({
// on post ownership in the Comment view.
comment.set({parent : this.model.toJSON()});
- var commentHtml = new this.CommentView({model: comment}).render().el;
+ var commentView = new this.CommentView({model: comment});
+ var commentHtml = commentView.render().el;
var commentBlocks = this.$(".comments div.comment.media");
this._moveInsertPoint(comment.get("created_at"), commentBlocks);
if (this._insertPoint >= commentBlocks.length) {
@@ -115,16 +129,13 @@ app.views.CommentStream = app.views.Base.extend({
} else {
commentBlocks.eq(this._insertPoint).before(commentHtml);
}
+ commentView.renderPluginWidgets();
},
removeComment: function(comment) {
this.$("#" + comment.get("guid")).closest(".comment.media").remove();
},
- commentTextareaFocused: function(){
- this.$("form").removeClass('hidden').addClass("open");
- },
-
expandComments: function(evt){
this.$(".loading-comments").removeClass("hidden");
if(evt){ evt.preventDefault(); }
@@ -134,6 +145,37 @@ app.views.CommentStream = app.views.Base.extend({
this.$(".loading-comments").addClass("hidden");
}.bind(this)
});
+ },
+
+ openForm: function() {
+ this.$("form").addClass("open");
+ this.$(".md-editor").addClass("active");
+ },
+
+ closeForm: function() {
+ this.$("form").removeClass("open");
+ this.$(".md-editor").removeClass("active");
+ this.commentBox.blur();
+ autosize.update(this.commentBox);
+ },
+
+ isCloseAllowed: function() {
+ if (this.mdEditor === undefined) {
+ return true;
+ }
+ return !this.mdEditor.isPreviewMode() && this.mdEditor.userInputEmpty();
+ },
+
+ onFormBlur: function(evt) {
+ if (!this.isCloseAllowed()) {
+ return;
+ }
+
+ var $target = $(evt.target);
+ var isForm = $target.hasClass("new-comment") || $target.parents(".new-comment").length !== 0;
+ if (!isForm && !$target.hasClass("focus_comment_textarea")) {
+ this.closeForm();
+ }
}
});
// @license-end
diff --git a/app/assets/javascripts/app/views/comment_view.js b/app/assets/javascripts/app/views/comment_view.js
index 7f74d1146..788344478 100644
--- a/app/assets/javascripts/app/views/comment_view.js
+++ b/app/assets/javascripts/app/views/comment_view.js
@@ -4,6 +4,7 @@
app.views.Comment = app.views.Content.extend({
templateName: "comment",
className : "comment media",
+ tooltipSelector: "time",
events : function() {
return _.extend({}, app.views.Content.prototype.events, {
@@ -20,7 +21,7 @@ app.views.Comment = app.views.Content.extend({
presenter : function() {
return _.extend(this.defaultPresenter(), {
canRemove: this.canRemove(),
- text : app.helpers.textFormatter(this.model.get("text"))
+ text: app.helpers.textFormatter(this.model.get("text"), this.model.get("mentioned_people"))
});
},
diff --git a/app/assets/javascripts/app/views/content_view.js b/app/assets/javascripts/app/views/content_view.js
index 7027ea97c..5a5a9e9af 100644
--- a/app/assets/javascripts/app/views/content_view.js
+++ b/app/assets/javascripts/app/views/content_view.js
@@ -17,15 +17,14 @@ app.views.Content = app.views.Base.extend({
largePhoto : function() {
var photos = this.model.get("photos");
- if(!photos || photos.length === 0) { return }
+ if (!photos || photos.length === 0) { return false; }
return photos[0];
},
smallPhotos : function() {
var photos = this.model.get("photos");
- if(!photos || photos.length < 2) { return }
- photos.splice(0, 1); // remove first photo as it is already shown as largePhoto
- return photos;
+ if (!photos || photos.length < 2) { return false; }
+ return photos.slice(1); // remove first photo as it is already shown as largePhoto
},
expandPost: function(evt) {
diff --git a/app/assets/javascripts/app/views/conversations_form_view.js b/app/assets/javascripts/app/views/conversations_form_view.js
index e3b553b7a..a28b6d426 100644
--- a/app/assets/javascripts/app/views/conversations_form_view.js
+++ b/app/assets/javascripts/app/views/conversations_form_view.js
@@ -24,6 +24,8 @@ app.views.ConversationsForm = app.views.Base.extend({
remoteRoute: {url: "/contacts", extraParameters: "mutual=true"}
});
+ this.newConversationMdEditor = this.renderMarkdownEditor("#new-message-text");
+
this.bindTypeaheadEvents();
this.tagListElement.empty();
@@ -31,10 +33,16 @@ app.views.ConversationsForm = app.views.Base.extend({
this.prefill(opts.prefill);
}
- this.$("form#new-conversation").on("ajax:success", this.conversationCreateSuccess);
+ this.$("form#new-conversation").on("ajax:success", this.conversationCreateSuccess.bind(this));
this.$("form#new-conversation").on("ajax:error", this.conversationCreateError);
},
+ renderMarkdownEditor: function(element) {
+ return new Diaspora.MarkdownEditor($(element), {
+ onPreview: Diaspora.MarkdownEditor.simplePreview
+ });
+ },
+
addRecipient: function(person) {
this.conversationRecipients.push(person);
this.updateContactIdsListInput();
@@ -66,7 +74,7 @@ app.views.ConversationsForm = app.views.Base.extend({
},
keyDown: function(evt) {
- if (evt.which === Keycodes.ENTER && evt.ctrlKey) {
+ if (evt.which === Keycodes.ENTER && (evt.metaKey || evt.ctrlKey)) {
$(evt.target).parents("form").submit();
}
},
@@ -84,6 +92,7 @@ app.views.ConversationsForm = app.views.Base.extend({
},
conversationCreateSuccess: function(evt, data) {
+ this.newConversationMdEditor.hidePreview();
app._changeLocation(Routes.conversation(data.id));
},
diff --git a/app/assets/javascripts/app/views/conversations_inbox_view.js b/app/assets/javascripts/app/views/conversations_inbox_view.js
index 67292cc75..9dc556343 100644
--- a/app/assets/javascripts/app/views/conversations_inbox_view.js
+++ b/app/assets/javascripts/app/views/conversations_inbox_view.js
@@ -8,11 +8,21 @@ app.views.ConversationsInbox = app.views.Base.extend({
"click .new-conversation-btn": "displayNewConversation"
},
- initialize: function() {
- new app.views.ConversationsForm();
+ initialize: function(conversationId) {
+ this.conversationForm = new app.views.ConversationsForm();
+
+ // Creates markdown editor in case of displaying preloaded conversation
+ if (conversationId != null) {
+ this.renderMarkdownEditor();
+ }
+
this.setupConversation();
},
+ renderMarkdownEditor: function() {
+ this.conversationForm.renderMarkdownEditor("#conversation-show .conversation-message-text");
+ },
+
renderConversation: function(conversationId) {
var self = this;
$.ajax({
@@ -23,6 +33,8 @@ app.views.ConversationsInbox = app.views.Base.extend({
self.$el.find("#conversation-show").removeClass("hidden").html(data);
self.selectConversation(conversationId);
self.setupConversation();
+ self.renderMarkdownEditor();
+ autosize(self.$("#conversation-show textarea"));
}
});
},
diff --git a/app/assets/javascripts/app/views/help_view.js b/app/assets/javascripts/app/views/help_view.js
index 48731e55c..24052f09f 100644
--- a/app/assets/javascripts/app/views/help_view.js
+++ b/app/assets/javascripts/app/views/help_view.js
@@ -4,27 +4,29 @@ app.views.Help = app.views.StaticContentView.extend({
templateName : "help",
events : {
- "click .faq-link" : "sectionClicked",
- "click .faq-link-getting-help" : "gettingHelp",
- "click .faq-link-sharing" : "sharing",
- "click .faq-link-posts-and-posting" : "postsAndPosting",
+ "click .faq-link": "sectionClicked",
+ "click .faq-link-getting-help": "gettingHelp",
+ "click .faq-link-sharing": "sharing",
+ "click .faq-link-posts-and-posting": "postsAndPosting",
"click .faq-link-tags": "tags",
- "click .faq-link-keyboard-shortcuts" : "keyboardShortcuts",
- "click .faq-link-chat" : "chat"
+ "click .faq-link-keyboard-shortcuts": "keyboardShortcuts",
+ "click .faq-link-chat": "chat"
},
initialize : function() {
this.GETTING_HELP_SUBS = {
- getting_started_a: { tutorial_series: this.linkHtml("http://diasporafoundation.org/getting_started/sign_up", Diaspora.I18n.t( 'getting_started_tutorial' )) },
- get_support_a_website: { link: this.linkHtml("https://diasporafoundation.org/", Diaspora.I18n.t( 'foundation_website' ))},
- get_support_a_tutorials: { tutorials: this.linkHtml("https://diasporafoundation.org/tutorials", Diaspora.I18n.t( 'tutorials' ))},
- get_support_a_wiki: { link: this.linkHtml("https://wiki.diasporafoundation.org/Special:Search", Diaspora.I18n.t( 'wiki' ))},
- get_support_a_irc: { irc: this.linkHtml("https://wiki.diasporafoundation.org/How_We_Communicate#IRC", Diaspora.I18n.t( 'irc' ))},
- get_support_a_faq: { faq: this.linkHtml("https://wiki.diasporafoundation.org/FAQ_for_users", Diaspora.I18n.t( 'faq' ))},
- get_support_a_hashtag: { question: this.linkHtml("/tags/question", "#question")}
+ getting_started_a: {tutorial_series: this.linkHtml("http://diasporafoundation.org/getting_started/sign_up", Diaspora.I18n.t("getting_started_tutorial"))},
+ get_support_a_website: {link: this.linkHtml("https://diasporafoundation.org/", Diaspora.I18n.t("foundation_website"))},
+ get_support_a_tutorials: {tutorials: this.linkHtml("https://diasporafoundation.org/tutorials", Diaspora.I18n.t("tutorials"))},
+ get_support_a_wiki: {link: this.linkHtml("https://wiki.diasporafoundation.org/Special:Search", Diaspora.I18n.t("wiki"))},
+ get_support_a_irc: {irc: this.linkHtml("https://wiki.diasporafoundation.org/How_We_Communicate#IRC", Diaspora.I18n.t("irc"))},
+ get_support_a_faq: {faq: this.linkHtml("https://wiki.diasporafoundation.org/FAQ_for_users", Diaspora.I18n.t("faq"))},
+ get_support_a_hashtag: {question: this.linkHtml("/tags/question", "#question")},
+ get_support_a_discourse: {discourse: this.linkHtml("https://discourse.diasporafoundation.org/c/support", "discussions & support")}
};
this.POSTS_AND_POSTING_SUBS = {
+ post_report_a: {community_guidelines: this.linkHtml("https://diasporafoundation.org/community_guidelines", Diaspora.I18n.t("community_guidelines"))},
format_text_a: {
markdown: this.linkHtml("http://diasporafoundation.org/formatting", Diaspora.I18n.t( 'markdown' )),
here: this.linkHtml("http://daringfireball.net/projects/markdown/syntax", Diaspora.I18n.t( 'here' ))
@@ -53,10 +55,9 @@ app.views.Help = app.views.StaticContentView.extend({
title_pods: Diaspora.I18n.t( 'pods.title' ),
title_posts_and_posting: Diaspora.I18n.t( 'posts_and_posting.title' ),
title_private_posts: Diaspora.I18n.t( 'private_posts.title' ),
- title_private_profiles: Diaspora.I18n.t( 'private_profiles.title' ),
title_public_posts: Diaspora.I18n.t( 'public_posts.title' ),
- title_public_profiles: Diaspora.I18n.t( 'public_profiles.title' ),
title_resharing_posts: Diaspora.I18n.t( 'resharing_posts.title' ),
+ title_profile: Diaspora.I18n.t("profile.title"),
title_sharing: Diaspora.I18n.t( 'sharing.title' ),
title_tags: Diaspora.I18n.t( 'tags.title' ),
title_keyboard_shortcuts: Diaspora.I18n.t( 'keyboard_shortcuts.title' ),
diff --git a/app/assets/javascripts/app/views/infinite_stream_view.js b/app/assets/javascripts/app/views/infinite_stream_view.js
index d5783d559..0a800da42 100644
--- a/app/assets/javascripts/app/views/infinite_stream_view.js
+++ b/app/assets/javascripts/app/views/infinite_stream_view.js
@@ -51,6 +51,12 @@ app.views.InfScroll = app.views.Base.extend({
}
},
+ postRenderTemplate: function() {
+ if (this.postViews.length > 0) {
+ this.$(".no-posts-info").closest(".stream-element").remove();
+ }
+ },
+
showNoPostsInfo: function() {
if (this.postViews.length === 0) {
var noPostsInfo = new app.views.NoPostsInfo();
diff --git a/app/assets/javascripts/app/views/notification_dropdown_view.js b/app/assets/javascripts/app/views/notification_dropdown_view.js
index c33287787..1d14cac08 100644
--- a/app/assets/javascripts/app/views/notification_dropdown_view.js
+++ b/app/assets/javascripts/app/views/notification_dropdown_view.js
@@ -26,7 +26,6 @@ app.views.NotificationDropdown = app.views.Base.extend({
toggleDropdown: function(evt){
evt.stopPropagation();
- if (!$("#notifications-link .entypo-bell:visible").length) { return true; }
evt.preventDefault();
if(this.dropdownShowing()){ this.hideDropdown(evt); }
else{ this.showDropdown(); }
diff --git a/app/assets/javascripts/app/views/preview_post_view.js b/app/assets/javascripts/app/views/preview_post_view.js
index d3b975f65..41a793f7b 100644
--- a/app/assets/javascripts/app/views/preview_post_view.js
+++ b/app/assets/javascripts/app/views/preview_post_view.js
@@ -5,7 +5,6 @@ app.views.PreviewPost = app.views.Post.extend({
className: "stream-element loaded",
subviews: {
- ".feedback": "feedbackView",
".post-content": "postContentView",
".oembed": "oEmbedView",
".opengraph": "openGraphView",
@@ -13,12 +12,6 @@ app.views.PreviewPost = app.views.Post.extend({
".status-message-location": "postLocationStreamView"
},
- tooltipSelector: [
- ".timeago",
- ".delete",
- ".permalink"
- ].join(", "),
-
initialize: function() {
this.model.set("preview", true);
this.oEmbedView = new app.views.OEmbed({model: this.model});
@@ -26,10 +19,6 @@ app.views.PreviewPost = app.views.Post.extend({
this.pollView = new app.views.Poll({model: this.model});
},
- feedbackView: function() {
- return new app.views.Feedback({model: this.model});
- },
-
postContentView: function() {
return new app.views.StatusMessage({model: this.model});
},
diff --git a/app/assets/javascripts/app/views/publisher/mention_view.js b/app/assets/javascripts/app/views/publisher/mention_view.js
index 86b3b07aa..bf15dc85e 100644
--- a/app/assets/javascripts/app/views/publisher/mention_view.js
+++ b/app/assets/javascripts/app/views/publisher/mention_view.js
@@ -2,29 +2,20 @@
app.views.PublisherMention = app.views.SearchBase.extend({
triggerChar: "@",
- invisibleChar: "\u200B", // zero width space
mentionRegex: /@([^@\s]+)$/,
-
- templates: {
- mentionItemSyntax: _.template("@{<%= name %> ; <%= handle %>}"),
- mentionItemHighlight: _.template("<strong><span><%= name %></span></strong>")
- },
+ mentionSyntaxTemplate: function(person) { return "@{" + person.handle + "}"; },
events: {
- "keydown #status_message_fake_text": "onInputBoxKeyDown",
- "input #status_message_fake_text": "onInputBoxInput",
- "click #status_message_fake_text": "onInputBoxClick",
- "blur #status_message_fake_text": "onInputBoxBlur"
+ "keydown .mention-textarea": "onInputBoxKeyDown",
+ "input .mention-textarea": "updateTypeaheadInput",
+ "click .mention-textarea": "onInputBoxClick",
+ "blur .mention-textarea": "onInputBoxBlur"
},
- initialize: function() {
+ initialize: function(opts) {
this.mentionedPeople = [];
-
- // contains the 'fake text' displayed to the user
- // also has a data-messageText attribute with the original text
- this.inputBox = this.$("#status_message_fake_text");
- // contains the mentions displayed to the user
- this.mentionsBox = this.$(".mentions-box");
+ var url = (opts && opts.url) || "/contacts";
+ this.inputBox = this.$(".mention-textarea");
this.typeaheadInput = this.$(".typeahead-mention-box");
this.bindTypeaheadEvents();
@@ -32,7 +23,7 @@ app.views.PublisherMention = app.views.SearchBase.extend({
typeaheadInput: this.typeaheadInput,
customSearch: true,
autoselect: true,
- remoteRoute: {url: "/contacts"}
+ remoteRoute: {url: url}
});
},
@@ -55,8 +46,8 @@ app.views.PublisherMention = app.views.SearchBase.extend({
cleanMentionedPeople: function() {
var inputText = this.inputBox.val();
this.mentionedPeople = this.mentionedPeople.filter(function(person) {
- return person.name && inputText.indexOf(person.name) > -1;
- });
+ return person.handle && inputText.indexOf(this.mentionSyntaxTemplate(person)) > -1;
+ }.bind(this));
this.ignoreDiasporaIds = this.mentionedPeople.map(function(person) { return person.handle; });
},
@@ -70,41 +61,16 @@ app.views.PublisherMention = app.views.SearchBase.extend({
this.addPersonToMentions(person);
this.closeSuggestions();
- messageText = messageText.substring(0, triggerCharPosition) +
- this.invisibleChar + person.name + messageText.substring(caretPosition);
+ var mentionText = this.mentionSyntaxTemplate(person);
- this.inputBox.val(messageText);
- this.updateMessageTexts();
+ messageText = messageText.substring(0, triggerCharPosition) + mentionText + messageText.substring(caretPosition);
+ this.inputBox.val(messageText);
this.inputBox.focus();
- var newCaretPosition = triggerCharPosition + person.name.length + 1;
+ var newCaretPosition = triggerCharPosition + mentionText.length;
this.inputBox[0].setSelectionRange(newCaretPosition, newCaretPosition);
},
- /**
- * Replaces every combination of this.invisibleChar + mention.name by the
- * correct syntax for both hidden text and visible one.
- *
- * For instance, the text "Hello \u200Buser1" will be tranformed to
- * "Hello @{user1 ; user1@pod.tld}" in the hidden element and
- * "Hello <strong><span>user1</span></strong>" in the element visible to the user.
- */
- updateMessageTexts: function() {
- var fakeMessageText = this.inputBox.val(),
- mentionBoxText = _.escape(fakeMessageText),
- messageText = fakeMessageText;
-
- this.mentionedPeople.forEach(function(person) {
- var mentionName = this.invisibleChar + person.name;
- messageText = messageText.replace(mentionName, this.templates.mentionItemSyntax(person));
- var textHighlight = this.templates.mentionItemHighlight({name: _.escape(person.name)});
- mentionBoxText = mentionBoxText.replace(mentionName, textHighlight);
- }, this);
-
- this.inputBox.data("messageText", messageText);
- this.mentionsBox.find(".mentions").html(mentionBoxText);
- },
-
updateTypeaheadInput: function() {
var messageText = this.inputBox.val();
var caretPosition = this.inputBox[0].selectionStart;
@@ -115,6 +81,8 @@ app.views.PublisherMention = app.views.SearchBase.extend({
return;
}
+ this.cleanMentionedPeople();
+
// result[1] is the string between the last '@' and the current caret position
this.typeaheadInput.typeahead("val", result[1]);
this.typeaheadInput.typeahead("open");
@@ -128,12 +96,11 @@ app.views.PublisherMention = app.views.SearchBase.extend({
prefillMention: function(persons) {
persons.forEach(function(person) {
this.addPersonToMentions(person);
- var text = this.invisibleChar + person.name;
+ var text = this.mentionSyntaxTemplate(person);
if(this.inputBox.val().length !== 0) {
text = this.inputBox.val() + " " + text;
}
this.inputBox.val(text);
- this.updateMessageTexts();
}, this);
},
@@ -154,15 +121,6 @@ app.views.PublisherMention = app.views.SearchBase.extend({
this.typeaheadInput.trigger($.Event("keydown", {keyCode: e.keyCode, which: e.which}));
},
- /**
- * Listens for user input and opens results dropdown when input contains the trigger char
- */
- onInputBoxInput: function() {
- this.cleanMentionedPeople();
- this.updateMessageTexts();
- this.updateTypeaheadInput();
- },
-
onInputBoxKeyDown: function(e) {
// This also matches HOME/END on OSX which is CMD+LEFT, CMD+RIGHT
if(e.which === Keycodes.LEFT || e.which === Keycodes.RIGHT ||
@@ -205,7 +163,7 @@ app.views.PublisherMention = app.views.SearchBase.extend({
reset: function() {
this.inputBox.val("");
- this.onInputBoxInput();
+ this.updateTypeaheadInput();
},
closeSuggestions: function() {
@@ -217,7 +175,8 @@ app.views.PublisherMention = app.views.SearchBase.extend({
return this.$(".tt-menu").is(":visible");
},
- getTextForSubmit: function() {
- return this.mentionedPeople.length ? this.inputBox.data("messageText") : this.inputBox.val();
+ getMentionedPeople: function() {
+ this.cleanMentionedPeople();
+ return this.mentionedPeople;
}
});
diff --git a/app/assets/javascripts/app/views/publisher_view.js b/app/assets/javascripts/app/views/publisher_view.js
index a80ef3555..baffa26da 100644
--- a/app/assets/javascripts/app/views/publisher_view.js
+++ b/app/assets/javascripts/app/views/publisher_view.js
@@ -18,11 +18,11 @@ app.views.Publisher = Backbone.View.extend({
el : "#publisher",
events : {
- "keydown #status_message_fake_text" : "keyDown",
+ "keydown #status_message_text": "keyDown",
"focus textarea" : "open",
"submit form" : "createStatusMessage",
"click #submit" : "createStatusMessage",
- "textchange #status_message_fake_text": "handleTextchange",
+ "textchange #status_message_text": "checkSubmitAvailability",
"click #locator" : "showLocation",
"click #poll_creator" : "togglePollCreator",
"click #hide_location" : "destroyLocation",
@@ -35,8 +35,7 @@ app.views.Publisher = Backbone.View.extend({
this.disabled = false;
// init shortcut references to the various elements
- this.inputEl = this.$("#status_message_fake_text");
- this.hiddenInputEl = this.$("#status_message_text");
+ this.inputEl = this.$("#status_message_text");
this.wrapperEl = this.$("#publisher_textarea_wrapper");
this.submitEl = this.$("input[type=submit], button#submit");
this.photozoneEl = this.$("#photodropzone");
@@ -46,14 +45,6 @@ app.views.Publisher = Backbone.View.extend({
$(window).on("beforeunload", _.bind(this._beforeUnload, this));
$(window).on("unload", this.clear.bind(this));
- // sync textarea content
- if( this.hiddenInputEl.val() === "" ) {
- this.hiddenInputEl.val( this.inputEl.val() );
- }
- if( this.inputEl.val() === "" ) {
- this.inputEl.val( this.hiddenInputEl.val() );
- }
-
// hide close and preview buttons and manage services link
// in case publisher is standalone
// (e.g. bookmarklet, mentions popup)
@@ -163,7 +154,7 @@ app.views.Publisher = Backbone.View.extend({
this.viewPollCreator.render();
if (this.prefillMention) {
- this.handleTextchange();
+ this.checkSubmitAvailability();
}
},
@@ -175,12 +166,11 @@ app.views.Publisher = Backbone.View.extend({
// inject content into the publisher textarea
setText: function(txt) {
this.inputEl.val(txt);
- this.hiddenInputEl.val(txt);
this.prefillText = txt;
this.inputEl.trigger("input");
autosize.update(this.inputEl);
- this.handleTextchange();
+ this.checkSubmitAvailability();
},
// show the "getting started" popups around the publisher
@@ -202,9 +192,6 @@ app.views.Publisher = Backbone.View.extend({
// empty poll answer and failing validation.
this.viewPollCreator.removeLastAnswer();
- //add missing mentions at end of post:
- this.handleTextchange();
-
var serializedForm = $(evt.target).closest("form").serializeObject();
// disable input while posting, must be after the form is serialized
this.setInputEnabled(false);
@@ -255,7 +242,7 @@ app.views.Publisher = Backbone.View.extend({
self.setButtonsEnabled(true);
self.setInputEnabled(true);
self.wrapperEl.removeClass("submitting");
- self.handleTextchange();
+ self.checkSubmitAvailability();
autosize.update(self.inputEl);
}
});
@@ -330,13 +317,8 @@ app.views.Publisher = Backbone.View.extend({
},
createPostPreview: function() {
- //add missing mentions at end of post:
- this.handleTextchange();
-
var serializedForm = $("#new_status_message").serializeObject();
- var text = this.mention.getTextForSubmit();
var photos = this.getUploadedPhotos();
- var mentionedPeople = this.mention.mentionedPeople;
var poll = this.getPollData(serializedForm);
var locationCoords = serializedForm["location[coords]"];
if(!locationCoords || locationCoords === "") {
@@ -352,12 +334,12 @@ app.views.Publisher = Backbone.View.extend({
var previewMessage = {
"id": 0,
- "text": text,
+ "text": serializedForm["status_message[text]"],
"public": serializedForm["aspect_ids[]"] === "public",
"created_at": new Date().toISOString(),
"interacted_at": new Date().toISOString(),
"author": app.currentUser ? app.currentUser.attributes : {},
- "mentioned_people": mentionedPeople,
+ "mentioned_people": this.mention.getMentionedPeople(),
"photos": photos,
"title": serializedForm["status_message[text]"],
"location": location,
@@ -370,7 +352,7 @@ app.views.Publisher = Backbone.View.extend({
},
keyDown : function(evt) {
- if(evt.which === Keycodes.ENTER && evt.ctrlKey) {
+ if (evt.which === Keycodes.ENTER && (evt.metaKey || evt.ctrlKey)) {
this.$("form").submit();
this.open();
return false;
@@ -381,11 +363,10 @@ app.views.Publisher = Backbone.View.extend({
// remove mentions
this.mention.reset();
- // clear text(s)
+ // clear text
this.inputEl.val("");
- this.hiddenInputEl.val("");
this.inputEl.trigger("keyup")
- .trigger("keydown");
+ .trigger("keydown");
autosize.update(this.inputEl);
// remove photos
@@ -421,14 +402,13 @@ app.views.Publisher = Backbone.View.extend({
// force textchange plugin to update lastValue
this.inputEl.data("lastValue", "");
- this.hiddenInputEl.data("lastValue", "");
return this;
},
tryClose : function(){
- // if it is not submittable, close it.
- if( !this._submittable() ){
+ // if it is not submittable and not in preview mode, close it.
+ if (!this._submittable() && !this.markdownEditor.isPreviewMode()) {
this.close();
}
},
@@ -472,8 +452,7 @@ app.views.Publisher = Backbone.View.extend({
setEnabled: function(bool) {
this.setInputEnabled(bool);
this.disabled = !bool;
-
- this.handleTextchange();
+ this.checkSubmitAvailability();
},
setButtonsEnabled: function(bool) {
@@ -487,10 +466,8 @@ app.views.Publisher = Backbone.View.extend({
setInputEnabled: function(bool) {
if (bool) {
this.inputEl.removeAttr("disabled");
- this.hiddenInputEl.removeAttr("disabled");
} else {
this.inputEl.prop("disabled", true);
- this.hiddenInputEl.prop("disabled", true);
}
},
@@ -503,11 +480,6 @@ app.views.Publisher = Backbone.View.extend({
return (!onlyWhitespaces || isPhotoAttached) && isValidPoll && !this.disabled;
},
- handleTextchange: function() {
- this.checkSubmitAvailability();
- this.hiddenInputEl.val(this.mention.getTextForSubmit());
- },
-
_beforeUnload: function(e) {
if(this._submittable() && this.inputEl.val() !== this.prefillText){
var confirmationMessage = Diaspora.I18n.t("confirm_unload");
diff --git a/app/assets/javascripts/app/views/single-post-viewer/single_post_comment_stream.js b/app/assets/javascripts/app/views/single-post-viewer/single_post_comment_stream.js
index 49ddf11db..6981bdc3a 100644
--- a/app/assets/javascripts/app/views/single-post-viewer/single_post_comment_stream.js
+++ b/app/assets/javascripts/app/views/single-post-viewer/single_post_comment_stream.js
@@ -7,7 +7,9 @@ app.views.SinglePostCommentStream = app.views.CommentStream.extend({
this.CommentView = app.views.ExpandedComment;
$(window).on('hashchange',this.highlightPermalinkComment);
this.setupBindings();
- this.model.comments.on("reset", this.render, this);
+ this.model.comments.fetch({success: function() {
+ setTimeout(this.highlightPermalinkComment, 0);
+ }.bind(this)});
},
highlightPermalinkComment: function() {
@@ -17,14 +19,13 @@ app.views.SinglePostCommentStream = app.views.CommentStream.extend({
$(".highlighted").removeClass("highlighted");
element.addClass("highlighted");
var pos = element.offset().top - headerSize;
- window.scroll(0, pos);
+ $("html,body").animate({scrollTop: pos});
}
},
postRenderTemplate: function() {
app.views.CommentStream.prototype.postRenderTemplate.apply(this);
this.$(".new-comment-form-wrapper").removeClass("hidden");
- _.defer(this.highlightPermalinkComment);
},
presenter: function(){
diff --git a/app/assets/javascripts/app/views/single-post-viewer/single_post_interaction_counts.js b/app/assets/javascripts/app/views/single-post-viewer/single_post_interaction_counts.js
index 42348627c..abc4f5d9e 100644
--- a/app/assets/javascripts/app/views/single-post-viewer/single_post_interaction_counts.js
+++ b/app/assets/javascripts/app/views/single-post-viewer/single_post_interaction_counts.js
@@ -4,8 +4,15 @@ app.views.SinglePostInteractionCounts = app.views.Base.extend({
templateName: "single-post-viewer/single-post-interaction-counts",
tooltipSelector: ".avatar.micro",
+ events: {
+ "click #show-all-likes": "showAllLikes",
+ "click #show-all-reshares": "showAllReshares"
+ },
+
initialize: function() {
this.model.interactions.on("change", this.render, this);
+ this.model.interactions.likes.on("change", this.render, this);
+ this.model.interactions.reshares.on("change", this.render, this);
},
presenter: function() {
@@ -15,8 +22,28 @@ app.views.SinglePostInteractionCounts = app.views.Base.extend({
reshares: interactions.reshares.toJSON(),
commentsCount: interactions.commentsCount(),
likesCount: interactions.likesCount(),
- resharesCount: interactions.resharesCount()
+ resharesCount: interactions.resharesCount(),
+ showMoreLikes: interactions.likes.length < interactions.likesCount(),
+ showMoreReshares: interactions.reshares.length < interactions.resharesCount()
};
+ },
+
+ _showAll: function(interactionType, models) {
+ this.$("#show-all-" + interactionType).addClass("hidden");
+ this.$("#" + interactionType + " .loader").removeClass("hidden");
+ models.fetch({success: function() {
+ models.trigger("change");
+ }});
+ },
+
+ showAllLikes: function(evt) {
+ evt.preventDefault();
+ this._showAll("likes", this.model.interactions.likes);
+ },
+
+ showAllReshares: function(evt) {
+ evt.preventDefault();
+ this._showAll("reshares", this.model.interactions.reshares);
}
});
// @license-end
diff --git a/app/assets/javascripts/helpers/markdown_editor.js b/app/assets/javascripts/helpers/markdown_editor.js
index 5706888a1..5da96bbf0 100644
--- a/app/assets/javascripts/helpers/markdown_editor.js
+++ b/app/assets/javascripts/helpers/markdown_editor.js
@@ -9,7 +9,8 @@ Diaspora.MarkdownEditor.prototype = {
this.options = {
resize: "none",
onHidePreview: $.noop,
- onPostPreview: $.noop
+ onPostPreview: $.noop,
+ onChange: function(e) { autosize.update(e.$textarea); }
};
$.extend(this.options, opts);
@@ -130,6 +131,14 @@ Diaspora.MarkdownEditor.prototype = {
}
},
+ isPreviewMode: function() {
+ return this.instance !== undefined && this.instance.$editor.find(".md-preview").length > 0;
+ },
+
+ userInputEmpty: function() {
+ return this.instance === undefined || this.instance.getContent().length === 0;
+ },
+
localize: function() {
var locale = Diaspora.I18n.language;
@@ -160,3 +169,7 @@ Diaspora.MarkdownEditor.prototype = {
return locale;
}
};
+
+Diaspora.MarkdownEditor.simplePreview = function($mdInstance) {
+ return "<div class='preview-content'>" + app.helpers.textFormatter($mdInstance.getContent()) + "</div>";
+};
diff --git a/app/assets/javascripts/jasmine-load-all.js b/app/assets/javascripts/jasmine-load-all.js
index be83acdec..b465abdad 100644
--- a/app/assets/javascripts/jasmine-load-all.js
+++ b/app/assets/javascripts/jasmine-load-all.js
@@ -1,4 +1,4 @@
-//= require jquery2
+//= require jquery3
//= require handlebars.runtime
//= require templates
//= require main
diff --git a/app/assets/javascripts/jsxc.js b/app/assets/javascripts/jsxc.js
index 9e90634ca..66ed5d622 100644
--- a/app/assets/javascripts/jsxc.js
+++ b/app/assets/javascripts/jsxc.js
@@ -1,5 +1,5 @@
//= require emojione
-//= require favico.js
+//= require favico.js/favico
//= require jquery.ui/ui/resizable
//= require jquery.ui/ui/draggable
diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js
index dccddf014..a59460b96 100644
--- a/app/assets/javascripts/main.js
+++ b/app/assets/javascripts/main.js
@@ -10,10 +10,10 @@
//= require charcount
//= require jquery-placeholder
//= require jquery.timeago
-//= require jquery-ui/core
-//= require jquery-ui/widget
-//= require jquery-ui/mouse
-//= require jquery-ui/sortable
+//= require jquery.ui/ui/core
+//= require jquery.ui/ui/widget
+//= require jquery.ui/ui/mouse
+//= require jquery.ui/ui/sortable
//= require keycodes
//= require jquery.autoSuggest.custom
//= require fine-uploader/fine-uploader.core
diff --git a/app/assets/javascripts/mobile/mobile.js b/app/assets/javascripts/mobile/mobile.js
index f0fb64c39..0bb660573 100644
--- a/app/assets/javascripts/mobile/mobile.js
+++ b/app/assets/javascripts/mobile/mobile.js
@@ -1,9 +1,9 @@
-// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later
-
/* Copyright (c) 2010-2011, Diaspora Inc. This file is
* licensed under the Affero General Public License version 3 or later. See
* the COPYRIGHT file.
*/
+// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later
+
//= require jquery-textchange
//= require charcount
//= require js-routes
@@ -18,6 +18,8 @@
//= require helpers/i18n
//= require helpers/profile_photo_uploader
//= require helpers/tags_autocomplete
+//= require bootstrap-markdown/bootstrap-markdown
+//= require helpers/markdown_editor
//= require widgets/timeago
//= require mobile/mobile_application
//= require mobile/mobile_file_uploader
diff --git a/app/assets/javascripts/mobile/mobile_comments.js b/app/assets/javascripts/mobile/mobile_comments.js
index 49858bc1c..a10c60639 100644
--- a/app/assets/javascripts/mobile/mobile_comments.js
+++ b/app/assets/javascripts/mobile/mobile_comments.js
@@ -11,6 +11,8 @@
initialize: function() {
var self = this;
+ new Diaspora.MarkdownEditor(".comment_box");
+
this.stream().on("tap click", "a.show-comments", function(evt){
evt.preventDefault();
self.toggleComments($(this));
@@ -35,7 +37,7 @@
self.scrollToOffset(commentContainer);
});
- this.stream().on("submit", ".new_comment", this.submitComment);
+ this.stream().on("submit", ".new-comment", this.submitComment);
},
submitComment: function(evt){
diff --git a/app/assets/javascripts/mobile/mobile_conversations.js b/app/assets/javascripts/mobile/mobile_conversations.js
index bf88bb5ff..5d42b5813 100644
--- a/app/assets/javascripts/mobile/mobile_conversations.js
+++ b/app/assets/javascripts/mobile/mobile_conversations.js
@@ -1,6 +1,7 @@
(function() {
Diaspora.Mobile.Conversations = {
initialize: function() {
+ new Diaspora.MarkdownEditor(".conversation-message-text");
if (Diaspora.Page !== "ConversationsNew") { return; }
$(document).on("ajax:success", "form#new-conversation", this.conversationCreateSuccess);
$(document).on("ajax:error", "form#new-conversation", this.conversationCreateError);
diff --git a/app/assets/javascripts/mobile/mobile_file_uploader.js b/app/assets/javascripts/mobile/mobile_file_uploader.js
index 86c784818..3a33ef5ee 100644
--- a/app/assets/javascripts/mobile/mobile_file_uploader.js
+++ b/app/assets/javascripts/mobile/mobile_file_uploader.js
@@ -33,7 +33,6 @@ function createUploader(){
$("#fileInfo-publisher").text(fileName + " " + progress + "%");
},
onSubmit: function() {
- $("#file-upload-publisher").addClass("loading");
$("#publisher_textarea_wrapper").addClass("with_attachments");
$("#photodropzone").append(
"<li class='publisher_photo loading' style='position:relative;'>" +
diff --git a/app/assets/javascripts/mobile/mobile_post_actions.js b/app/assets/javascripts/mobile/mobile_post_actions.js
index 7df54d6a9..76f1126d5 100644
--- a/app/assets/javascripts/mobile/mobile_post_actions.js
+++ b/app/assets/javascripts/mobile/mobile_post_actions.js
@@ -75,7 +75,7 @@
onLike: function(evt){
evt.preventDefault();
- var link = $(evt.target),
+ var link = $(evt.target).closest(".like-action"),
likeCounter = $(evt.target).closest(".stream-element").find(".like-count");
if(!link.hasClass("loading") && link.hasClass("inactive")) {
@@ -89,7 +89,7 @@
onReshare: function(evt) {
evt.preventDefault();
- var link = $(this),
+ var link = $(this).closest(".reshare-action"),
href = link.attr("href"),
confirmText = link.attr("title");
@@ -103,6 +103,10 @@
},
success: function() {
Diaspora.Mobile.PostActions.toggleActive(link);
+ var reshareCounter = $(evt.target).closest(".stream-element").find(".reshare-count");
+ if (reshareCounter) {
+ reshareCounter.text(parseInt(reshareCounter.text(), 10) + 1);
+ }
},
error: function(response) {
Diaspora.Mobile.Alert.handleAjaxError(response);
diff --git a/app/assets/javascripts/mobile/publisher.js b/app/assets/javascripts/mobile/publisher.js
index 6954631cf..f50c6aa71 100644
--- a/app/assets/javascripts/mobile/publisher.js
+++ b/app/assets/javascripts/mobile/publisher.js
@@ -46,4 +46,6 @@ $(document).ready(function(){
evt.preventDefault();
$("#new_status_message").submit();
});
+
+ new Diaspora.MarkdownEditor("#status_message_text");
});
diff --git a/app/assets/stylesheets/_application.scss b/app/assets/stylesheets/_application.scss
index 8bd3810d0..169bf1e1c 100644
--- a/app/assets/stylesheets/_application.scss
+++ b/app/assets/stylesheets/_application.scss
@@ -9,7 +9,6 @@
@import 'media-box';
@import 'entypo';
@import 'icons';
-@import 'mentions';
@import 'animations';
@import 'flash_messages';
@import 'sprites';
diff --git a/app/assets/stylesheets/base.scss b/app/assets/stylesheets/base.scss
index 13293c941..4bc53b49a 100644
--- a/app/assets/stylesheets/base.scss
+++ b/app/assets/stylesheets/base.scss
@@ -71,7 +71,7 @@ pre { word-wrap: break-word; }
line-height: 50px;
opacity: 0;
position: fixed;
- right: 54px;
+ right: 20px;
transition: opacity ease 400ms;
width: 50px;
z-index: 49;
diff --git a/app/assets/stylesheets/bootstrap-complete.scss b/app/assets/stylesheets/bootstrap-complete.scss
index df03c6ad0..0e49df681 100644
--- a/app/assets/stylesheets/bootstrap-complete.scss
+++ b/app/assets/stylesheets/bootstrap-complete.scss
@@ -1,7 +1,7 @@
// Calling this file bootstrap would cause an infinite recursion during asset compilation.
@import "bootstrap-sprockets";
@import "bootstrap-variables"; //our overwrites of bootstrap variables
-@import "bootstrap";
+@import "_bootstrap";
// Plugins
diff --git a/app/assets/stylesheets/color_themes/_color_theme_override_dark.scss b/app/assets/stylesheets/color_themes/_color_theme_override_dark.scss
index 74c305068..ec5e4ef46 100644
--- a/app/assets/stylesheets/color_themes/_color_theme_override_dark.scss
+++ b/app/assets/stylesheets/color_themes/_color_theme_override_dark.scss
@@ -1,24 +1,20 @@
// Only overriding existing selectors here, so disable some lint rules
// scss-lint:disable IdSelector, SelectorFormat, NestingDepth, SelectorDepth, QualifyingElement
body {
- .navbar.navbar-fixed-top #user_menu .dropdown-menu > li > a {
- color: $text-color;
- &:hover { color: $white; }
- }
-
.publisher {
- .mentions-input-box { background-color: $gray; }
form {
#publisher_textarea_wrapper { background-color: $gray; }
.btn.btn-link.question_mark:hover .entypo-cog { color: $gray-light; }
}
-
- .write-preview-tabs > li.active * { color: $text-color; }
- .md-preview { background-color: $gray; }
- .md-cancel:hover .entypo-cross { color: $gray-light; }
.publisher-buttonbar .btn.btn-link:hover i { color: $gray-light; }
}
+ .write-preview-tabs > li.active * { color: $text-color; }
+ .md-cancel:hover .entypo-cross { color: $gray-light; }
+
+ .md-input,
+ .md-preview { background-color: $gray; }
+
.aspect_dropdown li a .text { color: $dropdown-link-color; }
.info .tag { background-color: $gray-light; }
@@ -96,6 +92,7 @@ body {
#welcome-to-diaspora { background: $orange; }
+ .md-editor,
.block-form fieldset .form-control:focus { border-color: $input-border; }
&.page-registrations.action-new,
diff --git a/app/assets/stylesheets/color_themes/dark/_style.scss b/app/assets/stylesheets/color_themes/dark/_style.scss
index 1078d86bc..62e74dee6 100644
--- a/app/assets/stylesheets/color_themes/dark/_style.scss
+++ b/app/assets/stylesheets/color_themes/dark/_style.scss
@@ -59,7 +59,8 @@ $dropdown-link-hover-color: $dropdown-link-color;
//== Navbar
$navbar-inverse-bg: $gray-darker;
-$navbar-inverse-link-hover-color: $text-color;
+$navbar-inverse-link-color: $gray-lighter;
+$navbar-inverse-link-hover-color: $white;
$navbar-inverse-brand-hover-color: $navbar-inverse-link-hover-color;
//== Tabs
diff --git a/app/assets/stylesheets/comments.scss b/app/assets/stylesheets/comments.scss
index 533c9cffb..1c111d57f 100644
--- a/app/assets/stylesheets/comments.scss
+++ b/app/assets/stylesheets/comments.scss
@@ -46,13 +46,12 @@
.comment.new-comment-form-wrapper { padding-bottom: 0; }
- .submit_button {
+ .submit-button {
margin-top: 10px;
input {
float: right;
}
padding-left: 12px;
- display: none;
}
.comment_box {
height: 35px;
@@ -60,8 +59,27 @@
}
textarea.comment_box:focus, textarea.comment_box:valid, textarea.comment_box:active {
border-color: $border-dark-grey;
- & + .submit_button { display: block; }
- min-height: 35px;
box-shadow: none;
}
+
+ .twitter-typeahead {
+ // typeahead sets this to `display: inline-block` which adds additional space between
+ // the comment textarea and the submit button.
+ // scss-lint:disable ImportantRule
+ display: block !important;
+ // scss-lint:enable ImportantRule
+ }
+}
+
+.new-comment {
+ &:not(.open) .submit-button,
+ &:not(.open) .md-header {
+ display: none;
+ }
+
+ // The rule for .md-preview is required until we switch to the newer release of bootstrap-markdown with
+ // the following commit in:
+ // https://github.com/toopay/bootstrap-markdown/commit/14a21c3837140144b27efc19c795d1a37fad70fb
+ .md-preview,
+ &.open .md-editor textarea { min-height: 70px; }
}
diff --git a/app/assets/stylesheets/conversations.scss b/app/assets/stylesheets/conversations.scss
index 7c0bf90c5..f627e8059 100644
--- a/app/assets/stylesheets/conversations.scss
+++ b/app/assets/stylesheets/conversations.scss
@@ -238,3 +238,9 @@
}
.new-conversation.form-horizontal .form-group:last-of-type { margin-bottom: 0; }
+
+// This rule is required until we switch to the newer release of bootstrap-markdown with
+// the following commit in: https://github.com/toopay/bootstrap-markdown/commit/14a21c3837140144b27efc19c795d1a37fad70fb
+.conversations-form-container .md-preview {
+ min-height: 105px;
+}
diff --git a/app/assets/stylesheets/header.scss b/app/assets/stylesheets/header.scss
index 4e883094e..9bd9df45a 100644
--- a/app/assets/stylesheets/header.scss
+++ b/app/assets/stylesheets/header.scss
@@ -1,68 +1,68 @@
+.not-connected-menu {
+ .navbar-left {
+ float: left;
+ }
+
+ .navbar-right,
+ .navbar-right li {
+ float: right;
+ }
+}
+
.navbar.navbar-fixed-top {
border-bottom: none;
box-shadow: 1px 0 2px $black;
- a:focus {outline: 0 none; }
+ a:focus { outline: 0 none; }
+
+ .in {
+ overflow-y: visible; // Avoid search result dropdown to be hidden
+ }
.navbar-brand {
font-weight: bold;
font-size: $font-size-h3;
+ margin-left: -15px;
}
- @media (max-width: $grid-float-breakpoint-max) {
- .navbar-header > .nav li { display: inline-block !important; }
- .nav-badge {
- color: $navbar-inverse-link-color;
- padding-left: 12px;
- padding-right: 12px;
- &:hover { color: $navbar-inverse-link-hover-color; }
- &:hover,
- &:focus {
- background-color: transparent;
- }
+ .header-title {
+ margin: (($navbar-height - 32px - 2 * $navbar-padding-vertical) / 2) 0;
+
+ img {
+ height: 32px;
+ opacity: .7;
}
- #navbar-collapse {
- .form-group, .twitter-typeahead {
- display: block !important;
- margin-bottom: 0;
- &, & input { width: 100% }
- }
+
+ img:hover {
+ opacity: 1;
}
}
- @media (min-width: $grid-float-breakpoint) {
- input[type="search"] {
- @include transition(width);
- margin-top: 2px;
- width: 200px;
- &:not(.active) {
- background-color: $navbar-inverse-bg;
- border-color: $gray-light;
- width: 150px;
- }
- }
- #user_menu {
- &.open .dropdown-toggle { background-color: darken($navbar-inverse-bg, 7%); }
- .dropdown-toggle {
- margin: 0 1px;
- min-width: 160px;
- }
- .dropdown-menu {
- background-color: darken($navbar-inverse-bg, 7%);
- border-top: none;
- width: 100%;
- & > li > a {
- color: $gray-light;
- padding-left: 55px;
- &:hover {
- background-color: $brand-primary;
- color: $gray-lighter;
- }
- }
- }
+
+ .navbar-header > ul,
+ .navbar-header > ul li {
+ float: left;
+ }
+
+ [class^="entypo-"],
+ [class*="entypo-"] {
+ color: inherit;
+ font-size: $font-size-h3;
+ vertical-align: middle;
+ }
+
+ .nav-badge {
+ padding: $navbar-padding-vertical 12px;
+
+ .badge {
+ position: absolute;
+ right: 10px;
+ top: 10px;
}
}
.navbar-nav:not(.nav-badges) > li > a { font-weight: bold; }
.nav-badges {
+ margin: 0;
+
li { height: $navbar-height; }
.dropdown-open {
background-color: $dropdown-bg;
@@ -118,31 +118,141 @@
}
}
}
- [class^="entypo-"], [class*="entypo-"] {
- color: inherit;
- font-size: $font-size-h3;
- vertical-align: middle;
- }
- .nav-badge {
- margin-bottom: -2px;
- .badge {
- position: absolute;
- right: 10px;
- top: 10px;
- }
+
+ .user-menu-dropdown {
+ padding: 0;
}
- #user_menu {
+ .user-avatar {
+ height: $navbar-height;
+ margin-bottom: -$navbar-padding-vertical;
+ margin-right: 10px;
+ margin-top: -$navbar-padding-vertical;
+ padding: ($navbar-height - 30px) / 2 0;
+
.avatar {
height: 30px;
width: 30px;
}
- .user-avatar {
- height: $navbar-height;
- padding: ($navbar-height - 30px)/2 0;
- margin-bottom: -$navbar-padding-vertical;
- margin-top: -$navbar-padding-vertical;
- margin-right: 10px;
+ }
+
+ .navbar-form .form-control { display: inline-block; }
+
+ @media (max-width: $grid-float-breakpoint-max) {
+
+ .navbar-nav.hidden-xs {
+ margin: 0;
+
+ a {
+ padding-bottom: $navbar-padding-vertical;
+ padding-top: $navbar-padding-vertical;
+ }
+ }
+
+ .nav-badge {
+ color: $navbar-inverse-link-color;
+ &:hover { color: $navbar-inverse-link-hover-color; }
+ &:hover,
+ &:focus {
+ background-color: transparent;
+ }
+ }
+
+ .form-group,
+ .twitter-typeahead {
+ margin-bottom: 0;
+
+ &,
+ input { width: 100%; }
+ }
+
+ .nav-badges .dropdown-menu {
+ width: 300px;
+ }
+
+ .navbar-collapse {
+ padding-top: $navbar-padding-vertical / 2;
+
+ .navbar-nav {
+ margin-bottom: 0;
+ margin-top: 0;
+ }
+ }
+
+ .user-menu-dropdown {
+ background-color: transparent;
+ border: 0;
+ box-shadow: none;
+ display: block;
+ padding: 0;
+ position: static;
+ width: 100%;
+
+ a {
+ color: $navbar-inverse-link-color;
+ font-weight: bold;
+ padding: $nav-link-padding;
+
+ &:hover {
+ background-color: $navbar-inverse-link-hover-bg;
+ color: $navbar-inverse-link-hover-color;
+ }
+ }
+ }
+ }
+
+ @media (min-width: $grid-float-breakpoint) {
+
+ .navbar-form { // set correct margin for small inputs
+ margin-bottom: ($navbar-height - $input-height-small) / 2;
+ margin-top: ($navbar-height - $input-height-small) / 2;
+ }
+
+ [type="search"] {
+ @include transition(width);
+ width: 200px;
+
+ &:not(.active) {
+ background-color: $navbar-inverse-bg;
+ border-color: $gray-light;
+ width: 150px;
+ }
+ }
+
+ .user-menu {
+ &.open .dropdown-toggle { background-color: darken($navbar-inverse-bg, 7%); }
+ .dropdown-toggle {
+ margin: 0 1px;
+ min-width: 160px;
+ }
+ }
+
+ .user-menu-dropdown {
+ background-color: darken($navbar-inverse-bg, 7%);
+ border-top: 0;
+ width: 100%;
+
+ a {
+ color: $navbar-inverse-link-color;
+ padding-left: 55px;
+
+ &:hover {
+ background-color: $list-group-hover-bg;
+ color: $list-group-link-hover-color;
+ }
+ }
+
+ li:last-child a {
+ padding-bottom: 6px;
+ }
+ }
+ }
+
+ @media (max-width: $screen-xs-max) {
+ .nav-badges .dropdown-menu {
+ position: fixed;
+ top: $navbar-height;
+ width: 100%;
}
}
}
diff --git a/app/assets/stylesheets/markdown-editor.scss b/app/assets/stylesheets/markdown-editor.scss
index b077a7b44..e5e3b5a77 100644
--- a/app/assets/stylesheets/markdown-editor.scss
+++ b/app/assets/stylesheets/markdown-editor.scss
@@ -1,3 +1,18 @@
+.md-editor {
+ border: 1px solid $border-grey;
+ border-radius: $border-radius-small;
+ overflow: hidden;
+
+ &.active { border: 1px solid $border-dark-grey; }
+
+ textarea,
+ textarea:focus {
+ border: 0;
+ box-shadow: none;
+ margin: 0;
+ }
+}
+
.md-footer,
.md-header {
background: $white;
@@ -27,6 +42,7 @@
.btn-group {
margin-bottom: 8px;
+ &:first-child { margin-left: 0; }
[class^="entypo-"],
[class*="entypo-"] {
@@ -77,13 +93,11 @@
.md-preview {
- background: $white;
color: $text-color;
// !important is needed to override the CSS rules dynamically added to the element
// scss-lint:disable ImportantRule
height: auto !important;
// scss-lint:enable ImportantRule
- min-height: 90px;
overflow: auto;
position: relative;
// !important is needed to override the CSS rules dynamically added to the element
@@ -91,6 +105,8 @@
width: 100% !important;
// scss-lint:enable ImportantRule
z-index: 10;
+
+ .preview-content { padding: 10px; }
}
.md-controls {
diff --git a/app/assets/stylesheets/mentions.scss b/app/assets/stylesheets/mentions.scss
deleted file mode 100644
index a6920e7b3..000000000
--- a/app/assets/stylesheets/mentions.scss
+++ /dev/null
@@ -1,91 +0,0 @@
-.mentions-input-box {
- border-radius: 3px;
-
- background: #fff;
- position: relative;
-
- textarea {
- display: block;
- background: transparent;
- border: 1px solid #dcdcdc;
- border-radius: 3px;
- outline: 0;
- overflow: hidden;
- position: relative;
- resize: none;
- width: 100%;
-
- -webkit-box-sizing: border-box;
- -moz-box-sizing: border-box;
- box-sizing: border-box;
- }
-
- .form-control[disabled] { background-color: transparent; }
-
- .mentions-autocomplete-list {
- background: white;
- display: none;
- left: 0;
- margin-left: -1px;
- position: absolute;
- right: 0;
- z-index: 10000;
-
- ul {
- border: 1px solid $border-dark-grey;
- margin: 0;
- padding: 0;
-
- border-radius: 0px 0px 5px 5px;
-
- li {
- color: #444;
- background: white;
- border-bottom: 1px solid #ccc;
- cursor: pointer;
- font-size: 15px;
- height: 26px;
- line-height: 26px;
- list-style: none;
- margin: 0;
- overflow: hidden;
- padding: 5px;
- white-space: nowrap;
-
- &:hover, &.active { background: $background-grey; }
- &:last-child { border-radius: 0px 0px 5px 5px; }
-
- img, div.icon {
- float: left;
- height: 25px;
- margin-right: 5px;
- width: 25px;
- }
- }
- }
- }
-
- .mentions-box {
- position: absolute;
- right: 0px;
- bottom: 0px;
- left: 0px;
- top: 0px;
- padding: $padding-base-vertical $padding-base-horizontal;
- }
-
- .mentions {
- color: transparent;
- font-size: $font-size-base;
- font-family: Arial, Helvetica, sans-serif;
- overflow: hidden;
- width: 100%;
- white-space: pre-wrap;
- word-wrap: break-word;
-
- > strong {
- background: $background-blue;
- font-weight: normal;
- }
- }
-}
diff --git a/app/assets/stylesheets/mobile/comments.scss b/app/assets/stylesheets/mobile/comments.scss
index 7588a47fe..62db27354 100644
--- a/app/assets/stylesheets/mobile/comments.scss
+++ b/app/assets/stylesheets/mobile/comments.scss
@@ -43,16 +43,15 @@
display: flex;
.count {
+ color: $text-color;
+ font-family: $font-family-base;
+ font-size: $font-size-base;
line-height: 22px;
margin-left: 5px;
+ vertical-align: top;
z-index: 2;
}
- .icon-count-group {
- display: flex;
- margin: 0 7px;
- }
-
[class^="entypo"] {
color: $text-grey;
font-size: 24px;
@@ -73,6 +72,9 @@
}
.post-action {
+ display: flex;
+ margin: 0 7px;
+
.disabled { color: $medium-gray; }
}
diff --git a/app/assets/stylesheets/mobile/header.scss b/app/assets/stylesheets/mobile/header.scss
index c1813042e..159e6a536 100644
--- a/app/assets/stylesheets/mobile/header.scss
+++ b/app/assets/stylesheets/mobile/header.scss
@@ -33,10 +33,15 @@ $mobile-navbar-height: 46px;
li { float: left; }
}
- #header-title {
+ .header-title {
padding: 7px 15px;
margin: 0 0 0 -15px;
height: $mobile-navbar-height;
+
+ img {
+ height: 30px;
+ width: 30px;
+ }
}
#nav-badges {
@@ -87,12 +92,6 @@ $mobile-navbar-height: 46px;
background-color: $red;
}
}
- #header-title{
- img {
- height: 30px;
- width: 30px;
- }
- }
}
#drawer {
diff --git a/app/assets/stylesheets/mobile/markdown_editor.scss b/app/assets/stylesheets/mobile/markdown_editor.scss
new file mode 100644
index 000000000..b39f5a0ba
--- /dev/null
+++ b/app/assets/stylesheets/mobile/markdown_editor.scss
@@ -0,0 +1,6 @@
+.md-editor {
+ border: 1px solid $light-grey;
+ border-radius: $btn-border-radius-base;
+
+ &.active { border-color: $text-grey; }
+}
diff --git a/app/assets/stylesheets/mobile/mobile.scss b/app/assets/stylesheets/mobile/mobile.scss
index e9d612991..dc9958164 100644
--- a/app/assets/stylesheets/mobile/mobile.scss
+++ b/app/assets/stylesheets/mobile/mobile.scss
@@ -16,6 +16,8 @@
@import "mobile/stream_element";
@import "mobile/comments";
@import 'mobile/openid_connect_error_page';
+@import 'markdown-editor';
+@import 'mobile/markdown_editor';
@import 'typography';
@@ -42,8 +44,6 @@ h3 { margin-top: 0; }
.clear { clear: both; }
#main { padding: 56px 10px 0 10px; }
-textarea { resize: vertical; }
-
.avatar {
border-radius: 4px;
}
@@ -55,7 +55,6 @@ textarea { resize: vertical; }
overflow: auto;
position: relative;
text-align: left;
- min-height: 34px;
padding: 10px 0 0 0;
list-style: none;
@@ -404,11 +403,6 @@ footer {
.counter {
font-size: 14px;
}
-
- textarea {
- min-width: 100%;
- max-width: 100%;
- }
}
select {
@@ -539,13 +533,6 @@ form#new_conversation.new_conversation {
}
}
-textarea#conversation_text {
- font-size: larger;
- width: 100%;
- min-width: 100%;
- max-width: 100%;
-}
-
.registrations_error,
.registrations_notice {
color: #DF0101;
@@ -714,33 +701,6 @@ select#aspect_ids_ {
position: relative;
padding-right: 10px;
- #hide_publisher {
- opacity: 0.3;
- z-index: 5;
- padding: 3px;
- position: absolute;
- right: 6px;
- top: 0;
-
- &:hover {
- opacity: 1;
- }
- }
-
- &.active {
- border: 1px solid $border-dark-grey;
- }
-
- textarea {
- z-index: 2;
- border: none;
-
- &:focus {
- outline: 0;
- background: transparent;
- }
- }
-
&.with_attachments {
padding-bottom: 55px;
border: 1px solid $border-medium-grey;
diff --git a/app/assets/stylesheets/publisher.scss b/app/assets/stylesheets/publisher.scss
index 0ce5b462c..93cd34d19 100644
--- a/app/assets/stylesheets/publisher.scss
+++ b/app/assets/stylesheets/publisher.scss
@@ -14,21 +14,11 @@
display: none !important;
}
- .mentions-box {
- margin-top: 0;
- }
-
#publisher_textarea_wrapper { border: 1px solid $border-grey !important; }
}
.container-fluid{ padding: 0; }
- .twitter-typeahead {
- width: calc(100% + 2px);
-
- .tt-menu { width: 100%; }
- }
-
form {
margin: 0;
#fileInfo { display: none !important; }
@@ -86,11 +76,10 @@
}
textarea {
+ background: transparent;
border: 0 solid $light-grey;
- margin: 0;
- box-shadow: none;
- resize: none;
height: 50px;
+ resize: none;
}
&.active textarea {
@@ -202,9 +191,27 @@
margin-bottom: 0;
}
}
+
+ .md-editor,
+ .md-editor.active {
+ border: 0;
+ }
+
+ .md-preview {
+ // This rule is required until we switch to the newer release of bootstrap-markdown with
+ // the following commit in:
+ // https://github.com/toopay/bootstrap-markdown/commit/14a21c3837140144b27efc19c795d1a37fad70fb
+ min-height: 90px;
+
+ .stream-element .post-content .markdown-content {
+ padding-top: 0;
+ }
+ }
}
.publisher-textarea-wrapper {
+ position: relative;
+
&:not(.with-location) .location-container,
&.markdown-preview .location-container,
&:not(.with-poll) .poll-creator-container,
@@ -248,20 +255,12 @@
.locator { display: none; }
}
- &.submitting .mentions-box { display: none; }
-
.twitter-typeahead {
- left: -1px;
// Override inline rule of Typeahead
// scss-lint:disable ImportantRule
position: absolute !important;
// scss-lint:enable ImportantRule
}
-
- .mentions-box {
- // Leave space for markdown editor header
- margin-top: 42px;
- }
}
.publisher-buttonbar {
diff --git a/app/assets/stylesheets/single-post-view.scss b/app/assets/stylesheets/single-post-view.scss
index 15fdbcbde..ceaabc4fa 100644
--- a/app/assets/stylesheets/single-post-view.scss
+++ b/app/assets/stylesheets/single-post-view.scss
@@ -152,5 +152,16 @@
.interaction-avatars {
overflow: hidden;
+
+ .author-name:focus,
+ .author-name:hover {
+ text-decoration: none;
+ }
+
+ .loader {
+ height: $line-height-computed;
+ vertical-align: text-bottom;
+ width: $line-height-computed;
+ }
}
}
diff --git a/app/assets/stylesheets/typeahead.scss b/app/assets/stylesheets/typeahead.scss
index af635352b..89e1ef8fd 100644
--- a/app/assets/stylesheets/typeahead.scss
+++ b/app/assets/stylesheets/typeahead.scss
@@ -43,3 +43,21 @@
}
}
}
+
+.typeahead-mention-box-wrap .twitter-typeahead {
+ left: -1px;
+ width: calc(100% + 2px);
+
+ .tt-menu {
+ // Override inline rule of Typeahead
+ // If this is not overridden (`position: absolute` by default in Typeahead) then
+ // the box is cut when opened because of the `overflow: hidden` from parent classes of comment form styles. By
+ // having `position: relative` here we make it visible by inserting it in the flow.
+ // This has a side effect of "Comment" button move down when box is open, but it feels like the least evil.
+ // scss-lint:disable ImportantRule
+ position: relative !important;
+ // scss-lint:enable ImportantRule
+
+ width: 100%;
+ }
+}
diff --git a/app/assets/templates/comment-stream_tpl.jst.hbs b/app/assets/templates/comment-stream_tpl.jst.hbs
index e7343507d..592cf408b 100644
--- a/app/assets/templates/comment-stream_tpl.jst.hbs
+++ b/app/assets/templates/comment-stream_tpl.jst.hbs
@@ -25,9 +25,16 @@
{{/with}}
<div class="bd">
- <form accept-charset="UTF-8" action="/posts/{{id}}/comments" class="new_comment" id="new_comment_on_{{id}}" method="post">
- <textarea class="comment_box form-control" id="comment_text_on_{{id}}" name="text" rows="1" required placeholder="{{t "stream.comment"}}" />
- <div class="submit_button">
+ <form accept-charset="UTF-8" action="/posts/{{id}}/comments"
+ class="new-comment" id="new-comment-on-{{id}}" method="post">
+
+ <textarea class="comment_box form-control mention-textarea"
+ id="comment_text_on_{{id}}" name="text" rows="1" required placeholder="{{t "stream.comment"}}" />
+ <div class="typeahead-mention-box-wrap">
+ <input class="typeahead-mention-box hidden" type="text">
+ </div>
+
+ <div class="submit-button">
<input class="btn btn-primary" id="comment_submit_{{id}}" name="commit" type="submit" value="{{t "stream.comment"}}" />
</div>
</form>
diff --git a/app/assets/templates/faq_getting_help_tpl.jst.hbs b/app/assets/templates/faq_getting_help_tpl.jst.hbs
index 1457d820d..37859b7d8 100644
--- a/app/assets/templates/faq_getting_help_tpl.jst.hbs
+++ b/app/assets/templates/faq_getting_help_tpl.jst.hbs
@@ -17,6 +17,7 @@
<li>{{{ get_support_a_irc }}}</li>
<li>{{{ get_support_a_faq }}}</li>
<li>{{{ get_support_a_hashtag }}}</li>
+ <li>{{{ get_support_a_discourse }}}</li>
</ul>
</div>
</div>
diff --git a/app/assets/templates/faq_posts_and_posting_tpl.jst.hbs b/app/assets/templates/faq_posts_and_posting_tpl.jst.hbs
index 10af52769..6fd047cc4 100644
--- a/app/assets/templates/faq_posts_and_posting_tpl.jst.hbs
+++ b/app/assets/templates/faq_posts_and_posting_tpl.jst.hbs
@@ -28,7 +28,7 @@
<a class='toggle' href='#'>
<h4>{{ post_report_q }}</h4>
</a>
- <div class='answer hideable'>{{ post_report_a }}</div>
+ <div class='answer hideable'>{{{ post_report_a }}}</div>
</div>
<div class='question opened collapsible'>
<a class='toggle' href='#'>
@@ -59,9 +59,7 @@
<h4>{{ insert_images_comments_q }}</h4>
</a>
<div class='answer hideable'>
- {{ insert_images_comments_a1 }}
- <pre>![{{ image_text }}]( {{ image_url }})</pre>
- {{ insert_images_comments_a2 }}
+ {{ insert_images_comments_a }}
</div>
</div>
<div class='question opened collapsible'>
diff --git a/app/assets/templates/feedback_tpl.jst.hbs b/app/assets/templates/feedback_tpl.jst.hbs
index cf824d367..b373b2a7e 100644
--- a/app/assets/templates/feedback_tpl.jst.hbs
+++ b/app/assets/templates/feedback_tpl.jst.hbs
@@ -13,29 +13,17 @@
</span>
-
-{{#if preview}}
- <span>{{t "stream.like"}}</span>
-{{else}}
- <a href="#" class="like" rel='nofollow'>
- {{~#if userLike~}}
- {{~t "stream.unlike"~}}
- {{~else~}}
- {{~t "stream.like"~}}
- {{~/if~}}
- </a>
-{{/if}}
+<a href="#" class="like" rel='nofollow'>
+ {{~#if userLike~}}
+ {{~t "stream.unlike"~}}
+ {{~else~}}
+ {{~t "stream.like"~}}
+ {{~/if~}}
+</a>
·
-{{#if preview}}
- <span>{{t "stream.reshare"}}</span>
- ·
-{{else if userCanReshare}}
+{{#if userCanReshare}}
<a href="#" class="reshare" rel='nofollow'>{{t "stream.reshare"}}</a>
·
{{/if}}
-{{#if preview}}
- <span>{{t "stream.comment"}}</span>
-{{else}}
- <a href="#" class="focus_comment_textarea" rel="nofollow">{{t "stream.comment"}}</a>
-{{/if}}
+<a href="#" class="focus_comment_textarea" rel="nofollow">{{t "stream.comment"}}</a>
diff --git a/app/assets/templates/header_tpl.jst.hbs b/app/assets/templates/header_tpl.jst.hbs
index ee9eb0fb7..9c3270e5b 100644
--- a/app/assets/templates/header_tpl.jst.hbs
+++ b/app/assets/templates/header_tpl.jst.hbs
@@ -10,46 +10,24 @@
<span class="icon-bar"></span>
</button>
<a href="/stream" class="navbar-brand" data-stream-title="{{t "my_stream"}}">
- {{ podname }}
+ <span class="hidden-xs">{{ podname }}</span>
+ <div class="visible-xs-block header-title">
+ <img src="{{imageUrl 'branding/logos/asterisk_white_mobile.png'}}" alt="{{ podname }}" />
+ </div>
</a>
- <ul class="nav nav-badges visible-sm">
- <li>
- <a href="/notifications" title="{{t "header.notifications"}}" class="notifications-link nav-badge">
- <i class="entypo-bell"></i>
- <span class="badge badge-important {{#unless current_user.notifications_count}} hidden {{/unless}}">
- {{current_user.notifications_count}}
- </span>
- </a>
- </li>
- <li>
- <a href="/conversations" title="{{t "header.conversations"}}" class="conversations-link nav-badge">
- <i class="entypo-mail"></i>
- <span class="badge badge-important {{#unless current_user.unread_messages_count}} hidden {{/unless}}">
- {{current_user.unread_messages_count}}
- </span>
- </a>
- </li>
- </ul>
- </div>
-
- <div class="collapse navbar-collapse" id="navbar-collapse">
- <ul class="nav navbar-nav navbar-left">
+ <ul class="nav navbar-nav hidden-xs">
<li><a href="/stream">{{t "my_stream"}}</a></li>
<li><a href="/activity">{{t "my_activity"}}</a></li>
- <li class="visible-xs"><a href="/notifications">{{t "header.notifications"}}</a></li>
- <li class="visible-xs"><a href="/conversations">{{t "header.conversations"}}</a></li>
- <li class="visible-sm visible-xs"><a href="/mobile/toggle">{{t "header.toggle_mobile"}}</a></li>
</ul>
-
- <ul class="nav navbar-nav navbar-left nav-badges hidden-sm hidden-xs">
+ <ul class="nav navbar-nav nav-badges">
<li class="dropdown" id="notification-dropdown">
- <a id="notifications-link" href="/notifications" title="{{t "header.notifications"}}" class="notifications-link nav-badge hidden-sm hidden-xs" role="button" data-toggle="dropdown" aria-expanded="false" data-target=" ">
+ <a id="notifications-link" href="/notifications" title="{{t "header.notifications"}}" class="notifications-link nav-badge"
+ role="button" data-toggle="dropdown" aria-expanded="false" data-target=" ">
<i class="entypo-bell"></i>
<span class="badge badge-important {{#unless current_user.notifications_count}} hidden {{/unless}}">
{{current_user.notifications_count}}
</span>
</a>
-
<ul class="dropdown-menu" role="menu">
<div class="header">
<div class="pull-right">
@@ -71,11 +49,9 @@
</a>
</div>
</ul>
-
</li>
-
<li>
- <a id="conversations-link" href="/conversations" title="{{t "header.conversations"}}" class="conversations-link nav-badge hidden-sm hidden-xs">
+ <a id="conversations-link" href="/conversations" title="{{t "header.conversations"}}" class="conversations-link nav-badge">
<i class="entypo-mail"></i>
<span class="badge badge-important {{#unless current_user.unread_messages_count}} hidden {{/unless}}">
{{current_user.unread_messages_count}}
@@ -83,10 +59,17 @@
</a>
</li>
</ul>
+ </div>
+ <div class="collapse navbar-collapse" id="navbar-collapse">
+ <ul class="nav navbar-nav navbar-left visible-sm-block visible-xs-block">
+ <li class="visible-xs-block"><a href="/stream">{{t "my_stream"}}</a></li>
+ <li class="visible-xs-block"><a href="/activity">{{t "my_activity"}}</a></li>
+ <li><a href="/mobile/toggle">{{t "header.toggle_mobile"}}</a></li>
+ </ul>
<ul class="nav navbar-nav navbar-right">
- <li class="dropdown" id="user_menu">
- <a href="{{urlTo "person" current_user.guid}}" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">
+ <li class="dropdown user-menu" id="user-menu">
+ <a href="{{urlTo "person" current_user.guid}}" class="dropdown-toggle hidden-xs hidden-sm" data-toggle="dropdown" role="button" aria-expanded="false">
<span class="user-avatar pull-left">
{{{personImage current_user "small"}}}
</span>
@@ -94,7 +77,7 @@
<span class="caret"></span>
</a>
- <ul class="dropdown-menu" role="menu">
+ <ul class="dropdown-menu user-menu-dropdown" role="menu">
<li><a href="/people/{{current_user.guid}}">{{t "header.profile"}}</a></li>
<li><a href="/contacts">{{t "header.contacts"}}</a></li>
<li><a href="/user/edit">{{t "header.settings"}}</a></li>
diff --git a/app/assets/templates/help_tpl.jst.hbs b/app/assets/templates/help_tpl.jst.hbs
index 9a1579b7e..7281a958d 100644
--- a/app/assets/templates/help_tpl.jst.hbs
+++ b/app/assets/templates/help_tpl.jst.hbs
@@ -37,22 +37,18 @@
<span class="section-selected">{{ title_private_posts }}</span>
</li>
<li>
- <a href="#" class="section-unselected faq-link" data-section="private_profiles" data-items="who_sees_profile whats_in_profile who_sees_updates">{{ title_private_profiles }}</a>
- <span class="section-selected">{{ title_private_profiles }}</span>
- </li>
- <li>
<a href="#" class="section-unselected faq-link" data-section="public_posts" data-items="who_sees_post find_public_post can_comment_reshare_like see_comment_reshare_like deselect_aspect_posting">{{ title_public_posts }}</a>
<span class="section-selected">{{ title_public_posts }}</span>
</li>
<li>
- <a href="#" class="section-unselected faq-link" data-section="public_profiles" data-items="who_sees_profile whats_in_profile who_sees_updates what_do_tags_do">{{ title_public_profiles }}</a>
- <span class="section-selected">{{ title_public_profiles }}</span>
- </li>
- <li>
<a href="#" class="section-unselected faq-link" data-section="resharing_posts" data-items="reshare_public_post_aspects reshare_private_post_aspects">{{ title_resharing_posts }}</a>
<span class="section-selected">{{ title_resharing_posts }}</span>
</li>
<li>
+ <a href="#" class="section-unselected faq-link" data-section="profile" data-items="whats_in_profile who_sees_profile what_do_tags_do">{{ title_profile }}</a>
+ <span class="section-selected">{{ title_profile }}</span>
+ </li>
+ <li>
<a href="#" class="section-unselected faq-link-sharing" data-section="sharing" data-items="">{{ title_sharing }}</a>
<span class="section-selected">{{ title_sharing }}</span>
</li>
diff --git a/app/assets/templates/single-post-viewer/single-post-interaction-counts_tpl.jst.hbs b/app/assets/templates/single-post-viewer/single-post-interaction-counts_tpl.jst.hbs
index 221274487..dcf8cdd31 100644
--- a/app/assets/templates/single-post-viewer/single-post-interaction-counts_tpl.jst.hbs
+++ b/app/assets/templates/single-post-viewer/single-post-interaction-counts_tpl.jst.hbs
@@ -10,6 +10,12 @@
{{{personImage this "small" "micro"}}}
{{/linkToAuthor}}
{{/each}}
+ {{#if showMoreReshares}}
+ <div class="loader hidden">
+ <div class="spinner"></div>
+ </div>
+ <div id="show-all-reshares" class="btn btn-sm btn-link">{{t "show_all"}}</div>
+ {{/if}}
</div>
</div>
{{/if}}
@@ -25,6 +31,12 @@
{{{personImage this "small" "micro"}}}
{{/linkToAuthor}}
{{/each}}
+ {{#if showMoreLikes}}
+ <div class="loader hidden">
+ <div class="spinner"></div>
+ </div>
+ <div id="show-all-likes" class="btn btn-sm btn-link">{{t "show_all"}}</div>
+ {{/if}}
</div>
</div>
{{/if}}
diff --git a/app/assets/templates/stream-element_tpl.jst.hbs b/app/assets/templates/stream-element_tpl.jst.hbs
index bfba508f7..ed6b8083c 100644
--- a/app/assets/templates/stream-element_tpl.jst.hbs
+++ b/app/assets/templates/stream-element_tpl.jst.hbs
@@ -1,25 +1,26 @@
<div class="media {{#if showPost}} {{#if nsfw}} shield-off {{/if}} {{else}} shield-active {{/if}}">
- {{#with author}}
- <a href="/people/{{guid}}" class="img {{{hovercardable this}}}">
- {{{personImage this}}}
- </a>
- {{/with}}
+
+ {{#unless preview}}
+ {{#with author}}
+ <a href="/people/{{guid}}" class="img {{{hovercardable this}}}">
+ {{{personImage this}}}
+ </a>
+ {{/with}}
+ {{/unless}}
<div class="bd">
- {{#if loggedIn}}
- <div class="post-controls"></div>
- {{/if}}
+ {{#unless preview}}
+ {{#if loggedIn}}
+ <div class="post-controls"></div>
+ {{/if}}
- <div>
- {{#linkToAuthor author}}
- {{~name~}}
- {{/linkToAuthor}}
+ <div>
+ {{#linkToAuthor author}}
+ {{~name~}}
+ {{/linkToAuthor}}
- <span class="details gray">
- -
- {{#if preview}}
- <time class="timeago" data-original-title="{{{localTime created_at}}}" datetime="{{created_at}}" />
- {{else}}
+ <span class="details gray">
+ -
<a href="/posts/{{id}}">
<time class="timeago" data-original-title="{{{localTime created_at}}}" datetime="{{created_at}}" />
</a>
@@ -27,16 +28,18 @@
<a href="/posts/{{guid}}" class="permalink" title="{{t "stream.permalink"}}">
<i class="entypo-link"></i>
</a>
- {{/if}}
- </span>
- </div>
+ </span>
+ </div>
+ {{/unless}}
<div class="post-content"> </div>
<div class="status-message-location nsfw-hidden"> </div>
- <div class="feedback nsfw-hidden"> </div>
- <div class="likes nsfw-hidden"> </div>
- <div class="reshares nsfw-hidden"> </div>
- <div class="comments nsfw-hidden"> </div>
+ {{#unless preview}}
+ <div class="feedback nsfw-hidden"> </div>
+ <div class="likes nsfw-hidden"> </div>
+ <div class="reshares nsfw-hidden"> </div>
+ <div class="comments nsfw-hidden"> </div>
+ {{/unless}}
</div>
</div>
diff --git a/app/controllers/admin/admin_controller.rb b/app/controllers/admin/admin_controller.rb
index 8e22795ef..24f08cdf0 100644
--- a/app/controllers/admin/admin_controller.rb
+++ b/app/controllers/admin/admin_controller.rb
@@ -1,8 +1,6 @@
module Admin
class AdminController < ApplicationController
-
- before_filter :authenticate_user!
- before_filter :redirect_unless_admin
-
+ before_action :authenticate_user!
+ before_action :redirect_unless_admin
end
end
diff --git a/app/controllers/api/openid_connect/authorizations_controller.rb b/app/controllers/api/openid_connect/authorizations_controller.rb
index cc2e6a0a6..94f268010 100644
--- a/app/controllers/api/openid_connect/authorizations_controller.rb
+++ b/app/controllers/api/openid_connect/authorizations_controller.rb
@@ -205,7 +205,7 @@ module Api
if prompt && prompt.include?("none")
handle_prompt_none
elsif prompt && prompt.include?("login")
- new_params = params.except("controller", "action").merge(prompt: prompt.remove("login"))
+ new_params = params.except("controller", "action").permit!.to_h.merge(prompt: prompt.remove("login"))
reauthenticate(new_params)
else
authenticate_user!
diff --git a/app/controllers/api/openid_connect/discovery_controller.rb b/app/controllers/api/openid_connect/discovery_controller.rb
index 19c9001b4..f648e3566 100644
--- a/app/controllers/api/openid_connect/discovery_controller.rb
+++ b/app/controllers/api/openid_connect/discovery_controller.rb
@@ -24,17 +24,6 @@
module Api
module OpenidConnect
class DiscoveryController < ApplicationController
- def webfinger
- jrd = {
- links: [{
- rel: OpenIDConnect::Discovery::Provider::Issuer::REL_VALUE,
- href: root_url
- }]
- }
- jrd[:subject] = params[:resource] if params[:resource].present?
- render json: jrd, content_type: "application/jrd+json"
- end
-
def configuration
render json: OpenIDConnect::Discovery::Provider::Config::Response.new(
issuer: root_url,
diff --git a/app/controllers/api/openid_connect/token_endpoint_controller.rb b/app/controllers/api/openid_connect/token_endpoint_controller.rb
index c8fd53c2d..378f0086b 100644
--- a/app/controllers/api/openid_connect/token_endpoint_controller.rb
+++ b/app/controllers/api/openid_connect/token_endpoint_controller.rb
@@ -8,7 +8,8 @@ module Api
if req["client_assertion_type"] == "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"
handle_jwt_bearer(req)
end
- self.status, response.headers, self.response_body = Api::OpenidConnect::TokenEndpoint.new.call(request.env)
+ self.status, headers, self.response_body = Api::OpenidConnect::TokenEndpoint.new.call(request.env)
+ headers.each {|name, value| response.headers[name] = value }
nil
end
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 50484821e..27e793c1b 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -5,7 +5,7 @@
class ApplicationController < ActionController::Base
before_action :force_tablet_html
has_mobile_fu
- protect_from_forgery except: :receive, with: :exception
+ protect_from_forgery except: :receive, with: :exception, prepend: true
rescue_from ActionController::InvalidAuthenticityToken do
if user_signed_in?
diff --git a/app/controllers/aspect_memberships_controller.rb b/app/controllers/aspect_memberships_controller.rb
index 68215bc37..2bfd0c933 100644
--- a/app/controllers/aspect_memberships_controller.rb
+++ b/app/controllers/aspect_memberships_controller.rb
@@ -6,7 +6,7 @@
class AspectMembershipsController < ApplicationController
before_action :authenticate_user!
- respond_to :html, :json
+ respond_to :json
def destroy
aspect = current_user.aspects.joins(:aspect_memberships).where(aspect_memberships: {id: params[:id]}).first
@@ -30,18 +30,9 @@ class AspectMembershipsController < ApplicationController
if success
render json: AspectMembershipPresenter.new(membership).base_hash
else
- render text: membership.errors.full_messages, status: 403
+ render plain: membership.errors.full_messages, status: 403
end
end
-
- format.all do
- if success
- flash.now[:notice] = I18n.t "aspect_memberships.destroy.success"
- else
- flash.now[:error] = I18n.t "aspect_memberships.destroy.failure"
- end
- redirect_to :back
- end
end
end
@@ -58,35 +49,25 @@ class AspectMembershipsController < ApplicationController
AspectMembership.where(contact_id: @contact.id, aspect_id: @aspect.id).first)
.base_hash
end
-
- format.all do
- flash.now[:notice] = I18n.t("aspects.add_to_aspect.success")
- redirect_to :back
- end
end
else
respond_to do |format|
format.json do
- render text: I18n.t("aspects.add_to_aspect.failure"), status: 409
- end
-
- format.all do
- flash.now[:error] = I18n.t("aspects.add_to_aspect.failure")
- render nothing: true, status: 409
+ render plain: I18n.t("aspects.add_to_aspect.failure"), status: 409
end
end
end
end
rescue_from ActiveRecord::StatementInvalid do
- render text: I18n.t("aspect_memberships.destroy.invalid_statement"), status: 400
+ render plain: I18n.t("aspect_memberships.destroy.invalid_statement"), status: 400
end
rescue_from ActiveRecord::RecordNotFound do
- render text: I18n.t("aspect_memberships.destroy.no_membership"), status: 404
+ render plain: I18n.t("aspect_memberships.destroy.no_membership"), status: 404
end
rescue_from Diaspora::NotMine do
- render text: I18n.t("aspect_memberships.destroy.forbidden"), status: 403
+ render plain: I18n.t("aspect_memberships.destroy.forbidden"), status: 403
end
end
diff --git a/app/controllers/aspects_controller.rb b/app/controllers/aspects_controller.rb
index ce21bd95d..73bdf8cd2 100644
--- a/app/controllers/aspects_controller.rb
+++ b/app/controllers/aspects_controller.rb
@@ -22,7 +22,7 @@ class AspectsController < ApplicationController
render json: result
else
- render nothing: true, status: 422
+ head :unprocessable_entity
end
end
@@ -71,7 +71,7 @@ class AspectsController < ApplicationController
params[:ordered_aspect_ids].each_with_index do |id, i|
current_user.aspects.find(id).update_attributes(order_id: i)
end
- render nothing: true
+ head :no_content
end
def toggle_chat_privilege
@@ -79,7 +79,7 @@ class AspectsController < ApplicationController
@aspect.chat_enabled = !@aspect.chat_enabled
@aspect.save
- render :nothing => true
+ head :no_content
end
def toggle_contact_visibility
@@ -91,7 +91,7 @@ class AspectsController < ApplicationController
@aspect.contacts_visible = true
end
@aspect.save
- render :nothing => true
+ head :no_content
end
private
diff --git a/app/controllers/blocks_controller.rb b/app/controllers/blocks_controller.rb
index dd5cb4ae9..7ad4f2e1c 100644
--- a/app/controllers/blocks_controller.rb
+++ b/app/controllers/blocks_controller.rb
@@ -1,34 +1,26 @@
class BlocksController < ApplicationController
before_action :authenticate_user!
- respond_to :html, :json
-
def create
block = current_user.blocks.new(block_params)
- if block.save
- disconnect_if_contact(block.person)
- notice = {:notice => t('blocks.create.success')}
- else
- notice = {:error => t('blocks.create.failure')}
- end
+ disconnect_if_contact(block.person) if block.save
- respond_with do |format|
- format.html{ redirect_to :back, notice }
- format.json{ render :nothing => true, :status => 204 }
+ respond_to do |format|
+ format.json { head :no_content }
end
end
def destroy
- if current_user.blocks.find(params[:id]).delete
- notice = {:notice => t('blocks.destroy.success')}
- else
- notice = {:error => t('blocks.destroy.failure')}
- end
-
- respond_with do |format|
- format.html{ redirect_to :back, notice }
- format.json{ render :nothing => true, :status => 204 }
+ notice = if current_user.blocks.find_by(id: params[:id])&.delete
+ {notice: t("blocks.destroy.success")}
+ else
+ {error: t("blocks.destroy.failure")}
+ end
+
+ respond_to do |format|
+ format.json { head :no_content }
+ format.any { redirect_back fallback_location: privacy_settings_path, flash: notice }
end
end
diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb
index bde3e2fbb..f9d4ad47d 100644
--- a/app/controllers/comments_controller.rb
+++ b/app/controllers/comments_controller.rb
@@ -8,21 +8,21 @@ class CommentsController < ApplicationController
respond_to :html, :mobile, :json
rescue_from ActiveRecord::RecordNotFound do
- render nothing: true, status: 404
+ head :not_found
end
def create
begin
comment = comment_service.create(params[:post_id], params[:text])
rescue ActiveRecord::RecordNotFound
- render text: I18n.t("comments.create.error"), status: 404
+ render plain: I18n.t("comments.create.error"), status: 404
return
end
if comment
respond_create_success(comment)
else
- render text: I18n.t("comments.create.error"), status: 422
+ render plain: I18n.t("comments.create.error"), status: 422
end
end
@@ -57,24 +57,24 @@ class CommentsController < ApplicationController
def respond_create_success(comment)
respond_to do |format|
format.json { render json: CommentPresenter.new(comment), status: 201 }
- format.html { render nothing: true, status: 201 }
+ format.html { head :created }
format.mobile { render partial: "comment", locals: {comment: comment} }
end
end
def respond_destroy_success
respond_to do |format|
- format.mobile { redirect_to :back }
- format.js { render nothing: true, status: 204 }
- format.json { render nothing: true, status: 204 }
+ format.mobile { redirect_back fallback_location: stream_path }
+ format.js { head :no_content }
+ format.json { head :no_content }
end
end
def respond_destroy_error
respond_to do |format|
- format.mobile { redirect_to :back }
- format.js { render nothing: true, status: 403 }
- format.json { render nothing: true, status: 403 }
+ format.mobile { redirect_back fallback_location: stream_path }
+ format.js { head :forbidden }
+ format.json { head :forbidden }
end
end
end
diff --git a/app/controllers/conversations_controller.rb b/app/controllers/conversations_controller.rb
index c69b6d7d8..3f1977655 100644
--- a/app/controllers/conversations_controller.rb
+++ b/app/controllers/conversations_controller.rb
@@ -39,7 +39,7 @@ class ConversationsController < ApplicationController
end
unless person_ids.present?
- render text: I18n.t("javascripts.conversation.create.no_recipient"), status: 422
+ render plain: I18n.t("javascripts.conversation.create.no_recipient"), status: 422
return
end
@@ -53,7 +53,7 @@ class ConversationsController < ApplicationController
flash[:notice] = I18n.t("conversations.create.sent")
render json: {id: @conversation.id}
else
- render text: I18n.t("conversations.create.fail"), status: 422
+ render plain: I18n.t("conversations.create.fail"), status: 422
end
end
@@ -82,7 +82,7 @@ class ConversationsController < ApplicationController
@conversation.set_read(current_user)
render partial: "conversations/show", locals: {conversation: @conversation}
else
- render nothing: true, status: 404
+ head :not_found
end
end
diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb
index 3c4a6b5ee..74c2b6532 100644
--- a/app/controllers/home_controller.rb
+++ b/app/controllers/home_controller.rb
@@ -33,7 +33,7 @@ class HomeController < ApplicationController
def toggle_mobile
session[:mobile_view] = session[:mobile_view].nil? ? true : !session[:mobile_view]
- redirect_to :back
+ redirect_back fallback_location: root_path
end
def force_mobile
diff --git a/app/controllers/invitations_controller.rb b/app/controllers/invitations_controller.rb
index 66653e83e..04927022c 100644
--- a/app/controllers/invitations_controller.rb
+++ b/app/controllers/invitations_controller.rb
@@ -42,7 +42,7 @@ class InvitationsController < ApplicationController
t("invitations.create.rejected", emails: invalid_emails.join(", "))
end
- redirect_to :back
+ redirect_back fallback_location: stream_path
end
private
@@ -55,7 +55,7 @@ class InvitationsController < ApplicationController
else
t("invitations.create.closed")
end
- redirect_to :back
+ redirect_back fallback_location: stream_path
end
def valid_email?(email)
@@ -71,6 +71,6 @@ class InvitationsController < ApplicationController
end
def inviter_params
- params.require(:email_inviter).permit(:message, :locale, :emails)
+ params.require(:email_inviter).permit(:message, :locale, :emails).to_h
end
end
diff --git a/app/controllers/likes_controller.rb b/app/controllers/likes_controller.rb
index 20fe1dd69..182760951 100644
--- a/app/controllers/likes_controller.rb
+++ b/app/controllers/likes_controller.rb
@@ -13,10 +13,10 @@ class LikesController < ApplicationController
def create
like = like_service.create(params[:post_id])
rescue ActiveRecord::RecordNotFound, ActiveRecord::RecordInvalid
- render text: I18n.t("likes.create.error"), status: 422
+ render plain: I18n.t("likes.create.error"), status: 422
else
respond_to do |format|
- format.html { render nothing: true, status: 201 }
+ format.html { head :created }
format.mobile { redirect_to post_path(like.post_id) }
format.json { render json: like.as_api_response(:backbone), status: 201 }
end
@@ -24,9 +24,9 @@ class LikesController < ApplicationController
def destroy
if like_service.destroy(params[:id])
- render nothing: true, status: 204
+ head :no_content
else
- render text: I18n.t("likes.destroy.error"), status: 404
+ render plain: I18n.t("likes.destroy.error"), status: 404
end
end
diff --git a/app/controllers/messages_controller.rb b/app/controllers/messages_controller.rb
index c5387799b..a217aab87 100644
--- a/app/controllers/messages_controller.rb
+++ b/app/controllers/messages_controller.rb
@@ -18,14 +18,6 @@ class MessagesController < ApplicationController
logger.info "event=create type=message user=#{current_user.diaspora_handle} status=success " \
"message=#{message.id} chars=#{params[:message][:text].length}"
Diaspora::Federation::Dispatcher.defer_dispatch(current_user, message)
-
- # TODO: can be removed when messages are not relayed anymore
- conversation_owner = conversation.author.owner
- if conversation_owner && conversation_owner != current_user
- remote_subs = conversation.participants.remote.ids
- opts = {subscriber_ids: remote_subs}
- Diaspora::Federation::Dispatcher.defer_dispatch(conversation_owner, message, opts) unless remote_subs.empty?
- end
else
flash[:error] = I18n.t('conversations.new_conversation.fail')
end
diff --git a/app/controllers/node_info_controller.rb b/app/controllers/node_info_controller.rb
index bb0aaa14f..aaf9b68d8 100644
--- a/app/controllers/node_info_controller.rb
+++ b/app/controllers/node_info_controller.rb
@@ -1,7 +1,4 @@
class NodeInfoController < ApplicationController
- respond_to :json
- respond_to :html, only: :statistics
-
def jrd
render json: NodeInfo.jrd(CGI.unescape(node_info_url("123.123").sub("123.123", "%{version}")))
end
@@ -17,7 +14,7 @@ class NodeInfoController < ApplicationController
def statistics
respond_to do |format|
- format.json { render json: StatisticsPresenter.new }
+ format.json { head :not_acceptable }
format.all { @statistics = NodeInfoPresenter.new("1.0") }
end
end
diff --git a/app/controllers/notifications_controller.rb b/app/controllers/notifications_controller.rb
index aae218b69..0d1714ea0 100644
--- a/app/controllers/notifications_controller.rb
+++ b/app/controllers/notifications_controller.rb
@@ -23,8 +23,8 @@ class NotificationsController < ApplicationController
def index
conditions = {:recipient_id => current_user.id}
- if params[:type] && Notification.types.has_key?(params[:type])
- conditions[:type] = Notification.types[params[:type]]
+ if params[:type] && types.has_key?(params[:type])
+ conditions[:type] = types[params[:type]]
end
if params[:show] == "unread" then conditions[:unread] = true end
page = params[:page] || 1
@@ -44,7 +44,7 @@ class NotificationsController < ApplicationController
@grouped_unread_notification_counts = {}
- Notification.types.each_with_object(current_user.unread_notifications.group_by(&:type)) {|(name, type), notifications|
+ types.each_with_object(current_user.unread_notifications.group_by(&:type)) {|(name, type), notifications|
@grouped_unread_notification_counts[name] = notifications.has_key?(type) ? notifications[type].count : 0
}
@@ -65,7 +65,7 @@ class NotificationsController < ApplicationController
end
def read_all
- current_type = Notification.types[params[:type]]
+ current_type = types[params[:type]]
notifications = Notification.where(recipient_id: current_user.id, unread: true)
notifications = notifications.where(type: current_type) if params[:type]
notifications.update_all(unread: false)
@@ -93,4 +93,17 @@ class NotificationsController < ApplicationController
}
}.as_json
end
+
+ def types
+ {
+ "also_commented" => "Notifications::AlsoCommented",
+ "comment_on_post" => "Notifications::CommentOnPost",
+ "liked" => "Notifications::Liked",
+ "mentioned" => "Notifications::MentionedInPost",
+ "mentioned_in_comment" => "Notifications::MentionedInComment",
+ "reshared" => "Notifications::Reshared",
+ "started_sharing" => "Notifications::StartedSharing"
+ }
+ end
+ helper_method :types
end
diff --git a/app/controllers/participations_controller.rb b/app/controllers/participations_controller.rb
index 95e8a2c03..1cb9b7b40 100644
--- a/app/controllers/participations_controller.rb
+++ b/app/controllers/participations_controller.rb
@@ -5,9 +5,9 @@ class ParticipationsController < ApplicationController
post = current_user.find_visible_shareable_by_id(Post, params[:post_id])
if post
current_user.participate! post
- render nothing: true, status: :created
+ head :created
else
- render nothing: true, status: :forbidden
+ head :forbidden
end
end
@@ -15,9 +15,9 @@ class ParticipationsController < ApplicationController
participation = current_user.participations.find_by target_id: params[:post_id]
if participation
participation.destroy
- render nothing: true, status: :ok
+ head :ok
else
- render nothing: true, status: :unprocessable_entity
+ head :unprocessable_entity
end
end
end
diff --git a/app/controllers/people_controller.rb b/app/controllers/people_controller.rb
index 930ed0b7c..f42a4d908 100644
--- a/app/controllers/people_controller.rb
+++ b/app/controllers/people_controller.rb
@@ -19,8 +19,8 @@ class PeopleController < ApplicationController
rescue_from Diaspora::AccountClosed do
respond_to do |format|
- format.any { redirect_to :back, :notice => t("people.show.closed_account") }
- format.json { render :nothing => true, :status => 410 } # 410 GONE
+ format.any { redirect_back fallback_location: root_path, notice: t("people.show.closed_account") }
+ format.json { head :gone }
end
end
@@ -115,15 +115,15 @@ class PeopleController < ApplicationController
def retrieve_remote
if params[:diaspora_handle]
Workers::FetchWebfinger.perform_async(params[:diaspora_handle])
- render :nothing => true
+ head :ok
else
- render :nothing => true, :status => 422
+ head :unprocessable_entity
end
end
def contacts
respond_to do |format|
- format.json { render nothing: true, status: 406 }
+ format.json { head :not_acceptable }
format.any do
@person = Person.find_by_guid(params[:person_id])
diff --git a/app/controllers/photos_controller.rb b/app/controllers/photos_controller.rb
index d8b59fb4a..a95fdb420 100644
--- a/app/controllers/photos_controller.rb
+++ b/app/controllers/photos_controller.rb
@@ -66,10 +66,10 @@ class PhotosController < ApplicationController
:status => 201}
end
else
- render :nothing => true, :status => 422
+ head :unprocessable_entity
end
else
- render :nothing => true, :status => 422
+ head :unprocessable_entity
end
end
@@ -80,7 +80,7 @@ class PhotosController < ApplicationController
current_user.retract(photo)
respond_to do |format|
- format.json{ render :nothing => true, :status => 204 }
+ format.json { head :no_content }
format.html do
flash[:notice] = I18n.t 'photos.destroy.notice'
if StatusMessage.find_by_guid(photo.status_message_guid)
@@ -125,27 +125,28 @@ class PhotosController < ApplicationController
end
def legacy_create
- if params[:photo][:aspect_ids] == "all"
- params[:photo][:aspect_ids] = current_user.aspects.collect { |x| x.id }
- elsif params[:photo][:aspect_ids].is_a?(Hash)
- params[:photo][:aspect_ids] = params[:photo][:aspect_ids].values
+ photo_params = params.require(:photo).permit(:pending, :set_profile_photo, aspect_ids: [])
+ if photo_params[:aspect_ids] == "all"
+ photo_params[:aspect_ids] = current_user.aspects.map(&:id)
+ elsif photo_params[:aspect_ids].is_a?(Hash)
+ photo_params[:aspect_ids] = params[:photo][:aspect_ids].values
end
- params[:photo][:user_file] = file_handler(params)
+ photo_params[:user_file] = file_handler(params)
- @photo = current_user.build_post(:photo, params[:photo])
+ @photo = current_user.build_post(:photo, photo_params)
if @photo.save
unless @photo.pending
unless @photo.public?
- aspects = current_user.aspects_from_ids(params[:photo][:aspect_ids])
+ aspects = current_user.aspects_from_ids(photo_params[:aspect_ids])
current_user.add_to_streams(@photo, aspects)
end
- current_user.dispatch_post(@photo, :to => params[:photo][:aspect_ids])
+ current_user.dispatch_post(@photo, to: photo_params[:aspect_ids])
end
- if params[:photo][:set_profile_photo]
+ if photo_params[:set_profile_photo]
profile_params = {:image_url => @photo.url(:thumb_large),
:image_url_medium => @photo.url(:thumb_medium),
:image_url_small => @photo.url(:thumb_small)}
diff --git a/app/controllers/poll_participations_controller.rb b/app/controllers/poll_participations_controller.rb
index 2fd07c76e..a8b874fca 100644
--- a/app/controllers/poll_participations_controller.rb
+++ b/app/controllers/poll_participations_controller.rb
@@ -1,20 +1,17 @@
class PollParticipationsController < ApplicationController
- include ApplicationHelper
- before_filter :authenticate_user!
+ before_action :authenticate_user!
def create
answer = PollAnswer.find(params[:poll_answer_id])
poll_participation = current_user.participate_in_poll!(target, answer) if target
respond_to do |format|
- format.html { redirect_to :back }
format.mobile { redirect_to stream_path }
format.json { render json: poll_participation, :status => 201 }
end
rescue ActiveRecord::RecordInvalid
respond_to do |format|
- format.html { redirect_to :back }
format.mobile { redirect_to stream_path }
- format.json { render :nothing => true, :status => 403 }
+ format.json { head :forbidden }
end
end
@@ -25,4 +22,4 @@ class PollParticipationsController < ApplicationController
current_user.find_visible_shareable_by_id(Post, params[:post_id]) || raise(ActiveRecord::RecordNotFound.new)
end
end
-end \ No newline at end of file
+end
diff --git a/app/controllers/posts_controller.rb b/app/controllers/posts_controller.rb
index e88af7a77..9d6b3258c 100644
--- a/app/controllers/posts_controller.rb
+++ b/app/controllers/posts_controller.rb
@@ -3,7 +3,7 @@
# the COPYRIGHT file.
class PostsController < ApplicationController
- before_action :authenticate_user!, only: :destroy
+ before_action :authenticate_user!, only: %i(destroy mentionable)
before_action :set_format_if_malformed_from_status_net, only: :show
respond_to :html, :mobile, :json, :xml
@@ -13,7 +13,7 @@ class PostsController < ApplicationController
end
rescue_from Diaspora::NotMine do
- render text: I18n.t("posts.show.forbidden"), status: 403
+ render plain: I18n.t("posts.show.forbidden"), status: 403
end
def show
@@ -22,12 +22,11 @@ class PostsController < ApplicationController
presenter = PostPresenter.new(post, current_user)
respond_to do |format|
format.html do
- gon.post = presenter
+ gon.post = presenter.with_initial_interactions
render locals: {post: presenter}
end
format.mobile { render locals: {post: post} }
- format.xml { render xml: DiasporaFederation::Salmon::XmlPayload.pack(Diaspora::Federation::Entities.post(post)) }
- format.json { render json: presenter }
+ format.json { render json: presenter.with_interactions }
end
end
@@ -37,23 +36,28 @@ class PostsController < ApplicationController
oembed = params.slice(:format, :maxheight, :minheight)
render json: OEmbedPresenter.new(post, oembed)
rescue
- render nothing: true, status: 404
+ head :not_found
end
- def interactions
+ def mentionable
respond_to do |format|
format.json {
- post = post_service.find!(params[:id])
- render json: PostInteractionPresenter.new(post, current_user)
+ if params[:id].present? && params[:q].present?
+ render json: post_service.mentionable_in_comment(params[:id], params[:q])
+ else
+ head :no_content
+ end
}
- format.any { render nothing: true, status: 406 }
+ format.any { head :not_acceptable }
end
+ rescue ActiveRecord::RecordNotFound
+ head :not_found
end
def destroy
post_service.destroy(params[:id])
respond_to do |format|
- format.json { render nothing: true, status: 204 }
+ format.json { head :no_content }
format.any { redirect_to stream_path }
end
end
diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb
index bb4d9b070..9daa4640d 100644
--- a/app/controllers/profiles_controller.rb
+++ b/app/controllers/profiles_controller.rb
@@ -48,7 +48,7 @@ class ProfilesController < ApplicationController
end
respond_to do |format|
- format.js { render :nothing => true, :status => 200 }
+ format.js { head :ok }
format.any {
if current_user.getting_started?
redirect_to getting_started_path
@@ -77,6 +77,6 @@ class ProfilesController < ApplicationController
def profile_params
params.require(:profile).permit(:first_name, :last_name, :gender, :bio,
:location, :searchable, :tag_string, :nsfw,
- :public_details, date: %i(year month day)) || {}
+ :public_details, date: %i[year month day]).to_h || {}
end
end
diff --git a/app/controllers/report_controller.rb b/app/controllers/report_controller.rb
index 8e0826c1f..f51d2d043 100644
--- a/app/controllers/report_controller.rb
+++ b/app/controllers/report_controller.rb
@@ -31,7 +31,7 @@ class ReportController < ApplicationController
if report.save
render json: true, status: 200
else
- render nothing: true, status: 409
+ head :conflict
end
end
diff --git a/app/controllers/reshares_controller.rb b/app/controllers/reshares_controller.rb
index 4add93174..d38f49f6a 100644
--- a/app/controllers/reshares_controller.rb
+++ b/app/controllers/reshares_controller.rb
@@ -5,9 +5,9 @@ class ResharesController < ApplicationController
def create
reshare = reshare_service.create(params[:root_guid])
rescue ActiveRecord::RecordNotFound, ActiveRecord::RecordInvalid
- render text: I18n.t("reshares.create.error"), status: 422
+ render plain: I18n.t("reshares.create.error"), status: 422
else
- render json: ExtremePostPresenter.new(reshare, current_user), status: 201
+ render json: PostPresenter.new(reshare, current_user).with_interactions, status: 201
end
def index
diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb
index f3a320615..e1f754a43 100644
--- a/app/controllers/search_controller.rb
+++ b/app/controllers/search_controller.rb
@@ -1,24 +1,24 @@
class SearchController < ApplicationController
before_action :authenticate_user!
-
+
def search
if search_query.starts_with?('#')
if search_query.length > 1
- respond_to do |format|
+ respond_to do |format|
format.json {redirect_to tags_path(:q => search_query.delete("#."))}
format.any {redirect_to tag_path(:name => search_query.delete("#."))}
end
else
flash[:error] = I18n.t('tags.show.none', :name => search_query)
- redirect_to :back
+ redirect_back fallback_location: stream_path
end
else
redirect_to people_path(:q => search_query)
- end
+ end
end
-
+
private
-
+
def search_query
@search_query ||= (params[:q] || params[:term] || '').strip
end
diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb
index 61f464209..74fd1f818 100644
--- a/app/controllers/sessions_controller.rb
+++ b/app/controllers/sessions_controller.rb
@@ -3,8 +3,8 @@
# the COPYRIGHT file.
class SessionsController < Devise::SessionsController
- after_filter :reset_authentication_token, :only => [:create]
- before_filter :reset_authentication_token, :only => [:destroy]
+ after_action :reset_authentication_token, only: [:create]
+ before_action :reset_authentication_token, only: [:destroy]
def reset_authentication_token
current_user.reset_authentication_token! unless current_user.nil?
diff --git a/app/controllers/status_messages_controller.rb b/app/controllers/status_messages_controller.rb
index e65e4b54a..58ae46536 100644
--- a/app/controllers/status_messages_controller.rb
+++ b/app/controllers/status_messages_controller.rb
@@ -47,14 +47,8 @@ class StatusMessagesController < ApplicationController
end
def create
- normalized_params = params.merge(
- services: normalize_services,
- aspect_ids: normalize_aspect_ids,
- public: normalize_public_flag
- )
- status_message = StatusMessageCreationService.new(current_user).create(normalized_params)
+ status_message = StatusMessageCreationService.new(current_user).create(normalize_params)
respond_to do |format|
- format.html { redirect_to :back }
format.mobile { redirect_to stream_path }
format.json { render json: PostPresenter.new(status_message, current_user), status: 201 }
end
@@ -71,9 +65,8 @@ class StatusMessagesController < ApplicationController
def handle_create_error(error)
logger.debug error
respond_to do |format|
- format.html { redirect_to :back }
format.mobile { redirect_to stream_path }
- format.json { render text: error.message, status: 403 }
+ format.json { render plain: error.message, status: 403 }
end
end
@@ -89,8 +82,19 @@ class StatusMessagesController < ApplicationController
request.env["HTTP_REFERER"].include?("/people/" + current_user.guid)
end
- def normalize_services
- [*params[:services]].compact
+ def normalize_params
+ params.permit(
+ :location_address,
+ :location_coords,
+ :poll_question,
+ status_message: %i[text provider_display_name],
+ poll_answers: []
+ ).to_h.merge(
+ services: [*params[:services]].compact,
+ aspect_ids: normalize_aspect_ids,
+ public: [*params[:aspect_ids]].first == "public",
+ photos: [*params[:photos]].compact
+ )
end
def normalize_aspect_ids
@@ -102,10 +106,6 @@ class StatusMessagesController < ApplicationController
end
end
- def normalize_public_flag
- [*params[:aspect_ids]].first == "public"
- end
-
def remove_getting_started
current_user.disable_getting_started
end
diff --git a/app/controllers/tag_followings_controller.rb b/app/controllers/tag_followings_controller.rb
index 72ca6fd24..a82d16dd9 100644
--- a/app/controllers/tag_followings_controller.rb
+++ b/app/controllers/tag_followings_controller.rb
@@ -15,7 +15,7 @@ class TagFollowingsController < ApplicationController
name_normalized = ActsAsTaggableOn::Tag.normalize(params['name'])
if name_normalized.nil? || name_normalized.empty?
- render :nothing => true, :status => 403
+ head :forbidden
else
@tag = ActsAsTaggableOn::Tag.find_or_create_by(name: name_normalized)
@tag_following = current_user.tag_followings.new(:tag_id => @tag.id)
@@ -23,7 +23,7 @@ class TagFollowingsController < ApplicationController
if @tag_following.save
render :json => @tag.to_json, :status => 201
else
- render :nothing => true, :status => 403
+ head :forbidden
end
end
end
@@ -35,11 +35,11 @@ class TagFollowingsController < ApplicationController
if tag_following && tag_following.destroy
respond_to do |format|
- format.any(:js, :json) { render :nothing => true, :status => 204 }
+ format.any(:js, :json) { head :no_content }
end
else
respond_to do |format|
- format.any(:js, :json) {render :nothing => true, :status => 403}
+ format.any(:js, :json) { head :forbidden }
end
end
end
diff --git a/app/controllers/tags_controller.rb b/app/controllers/tags_controller.rb
index 30ddfec00..d201fd905 100644
--- a/app/controllers/tags_controller.rb
+++ b/app/controllers/tags_controller.rb
@@ -24,8 +24,8 @@ class TagsController < ApplicationController
end
else
respond_to do |format|
- format.json{ render :nothing => true, :status => 422 }
- format.html{ redirect_to tag_path('partytimeexcellent') }
+ format.json { head :unprocessable_entity }
+ format.html { redirect_to tag_path("partytimeexcellent") }
end
end
end
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 262d0bb16..e6dbb3449 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -46,7 +46,7 @@ class UsersController < ApplicationController
flash[:error] = t("users.update.settings_not_updated")
end
- redirect_to :back
+ redirect_back fallback_location: privacy_settings_path
end
def destroy
@@ -60,7 +60,7 @@ class UsersController < ApplicationController
else
flash[:error] = t "users.destroy.no_password"
end
- redirect_to :back
+ redirect_back fallback_location: edit_user_path
end
end
@@ -150,16 +150,7 @@ class UsersController < ApplicationController
:auto_follow_back_aspect_id,
:getting_started,
:post_default_public,
- email_preferences: %i(
- someone_reported
- also_commented
- mentioned
- comment_on_post
- private_message
- started_sharing
- liked
- reshared
- )
+ email_preferences: UserPreference::VALID_EMAIL_TYPES.map(&:to_sym)
)
end
# rubocop:enable Metrics/MethodLength
diff --git a/app/helpers/analytics_helper.rb b/app/helpers/analytics_helper.rb
deleted file mode 100644
index df7f69c6e..000000000
--- a/app/helpers/analytics_helper.rb
+++ /dev/null
@@ -1,69 +0,0 @@
-# Copyright (c) 2010-2012, Diaspora Inc. This file is
-# licensed under the Affero General Public License version 3 or later. See
-# the COPYRIGHT file.
-
-module AnalyticsHelper
- def include_mixpanel
- include_analytics "mixpanel" do
- nonced_javascript_tag do
- <<-JS.html_safe
- (function(d,c){var a,b,g,e;a=d.createElement('script');a.type='text/javascript';a.async=!0;a.src=('https:'===d.location.protocol?'https:':'http:')+'//api.mixpanel.com/site_media/js/api/mixpanel.2.js';b=d.getElementsByTagName('script')[0];b.parentNode.insertBefore(a,b);c._i=[];c.init=function(a,d,f){var b=c;'undefined'!==typeof f?b=c[f]=[]:f='mixpanel';g='disable track track_pageview track_links track_forms register register_once unregister identify name_tag set_config'.split(' ');
- for(e=0;e<g.length;e++)(function(a){b[a]=function(){b.push([a].concat(Array.prototype.slice.call(arguments,0)))}})(g[e]);c._i.push([a,d,f])};window.mixpanel=c})(document,[]);
- mixpanel.init("#{AppConfig.privacy.mixpanel_uid}");
- JS
- end
- end
- end
-
- def include_mixpanel_guid
- return unless current_user
- include_analytics "mixpanel" do
- nonced_javascript_tag do
- <<-JS.html_safe
- mixpanel.name_tag("#{current_user.guid}");
- JS
- end
- end
- end
-
- def chartbeat_head_block
- return unless configured?("chartbeat")
- nonced_javascript_tag("var _sf_startpt=(new Date()).getTime()")
- end
-
- def include_chartbeat
- include_analytics "chartbeat" do
- nonced_javascript_tag do
- <<-JS.html_safe
- var _sf_async_config = { uid: #{AppConfig.privacy.chartbeat_uid}, domain: "#{AppConfig.pod_uri.host}" };
- (function() {
- function loadChartbeat() {
- window._sf_endpt = (new Date()).getTime();
- var e = document.createElement('script');
- e.setAttribute('language', 'javascript');
- e.setAttribute('type', 'text/javascript');
- e.setAttribute('src',
- (('https:' == document.location.protocol) ? 'https://a248.e.akamai.net/chartbeat.download.akamai.com/102508/' : 'http://static.chartbeat.com/') +
- 'js/chartbeat.js');
- document.body.appendChild(e);
- };
- var oldonload = window.onload;
- window.onload = (typeof window.onload != 'function') ?
- loadChartbeat : function() { oldonload(); loadChartbeat(); };
- })();
- JS
- end
- end
- end
-
- private
-
- def include_analytics(service, &block)
- return unless configured?(service)
- yield block
- end
-
- def configured?(service)
- AppConfig.privacy.send("#{service}_uid").present?
- end
-end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 3a89c597d..b46b27203 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -52,11 +52,13 @@ module ApplicationHelper
def jquery_include_tag
buf = []
if AppConfig.privacy.jquery_cdn?
- version = Jquery::Rails::JQUERY_2_VERSION
+ version = Jquery::Rails::JQUERY_3_VERSION
buf << [javascript_include_tag("//code.jquery.com/jquery-#{version}.min.js")]
- buf << [nonced_javascript_tag("!window.jQuery && document.write(unescape('#{j javascript_include_tag('jquery2')}'));")]
+ buf << [
+ nonced_javascript_tag("!window.jQuery && document.write(unescape('#{j javascript_include_tag('jquery3')}'));")
+ ]
else
- buf << [javascript_include_tag("jquery2")]
+ buf << [javascript_include_tag("jquery3")]
end
buf << [javascript_include_tag("jquery_ujs")]
buf << [nonced_javascript_tag("jQuery.ajaxSetup({'cache': false});")]
diff --git a/app/helpers/interim_stream_hackiness_helper.rb b/app/helpers/interim_stream_hackiness_helper.rb
index b531871f2..4283a8126 100644
--- a/app/helpers/interim_stream_hackiness_helper.rb
+++ b/app/helpers/interim_stream_hackiness_helper.rb
@@ -21,16 +21,6 @@ module InterimStreamHackinessHelper
end
end
- def publisher_hidden_text
- if params[:prefill].present?
- params[:prefill]
- elsif defined?(@stream)
- @stream.publisher.prefill
- else
- nil
- end
- end
-
def from_group(post)
if defined?(@stream) && params[:controller] == 'multis'
@stream.post_from_group(post)
diff --git a/app/helpers/meta_data_helper.rb b/app/helpers/meta_data_helper.rb
index 6b3dcfc7f..7fbe86ab8 100644
--- a/app/helpers/meta_data_helper.rb
+++ b/app/helpers/meta_data_helper.rb
@@ -11,7 +11,7 @@ module MetaDataHelper
end
def default_image_url
- asset_url "assets/branding/logos/asterisk.png"
+ asset_url("assets/branding/logos/asterisk.png", skip_pipeline: true)
end
def default_author_name
diff --git a/app/helpers/mobile_helper.rb b/app/helpers/mobile_helper.rb
index 818568bc7..6d8f008dc 100644
--- a/app/helpers/mobile_helper.rb
+++ b/app/helpers/mobile_helper.rb
@@ -7,25 +7,30 @@ module MobileHelper
reshare = Reshare.where(author_id: current_user.person_id,
root_guid: absolute_root.guid).first
klass = reshare.present? ? "active" : "inactive"
- link_to "", reshares_path(root_guid: absolute_root.guid),
+ link_to content_tag(:span, post.reshares.size, class: "count reshare-count"),
+ reshares_path(root_guid: absolute_root.guid),
title: t("reshares.reshare.reshare_confirmation", author: absolute_root.author_name),
class: "entypo-reshare reshare-action #{klass}"
else
- content_tag :div, nil, class: "entypo-reshare reshare-action disabled"
+ content_tag :div,
+ content_tag(:span, post.reshares.size, class: "count reshare-count"),
+ class: "entypo-reshare reshare-action disabled"
end
else
- content_tag :div, nil, class: "entypo-reshare reshare-action disabled"
+ content_tag :div,
+ content_tag(:span, post.reshares.size, class: "count reshare-count"),
+ class: "entypo-reshare reshare-action disabled"
end
end
def mobile_like_icon(post)
if current_user && current_user.liked?(post)
- link_to "",
+ link_to content_tag(:span, post.likes.size, class: "count like-count"),
"#",
data: {url: post_like_path(post.id, current_user.like_for(post).id)},
class: "entypo-heart like-action active"
else
- link_to "",
+ link_to content_tag(:span, post.likes.size, class: "count like-count"),
"#",
data: {url: post_likes_path(post.id)},
class: "entypo-heart like-action inactive"
@@ -33,7 +38,9 @@ module MobileHelper
end
def mobile_comment_icon(post)
- link_to "", new_post_comment_path(post), class: "entypo-comment comment-action inactive"
+ link_to content_tag(:span, post.comments.size, class: "count comment-count"),
+ new_post_comment_path(post),
+ class: "entypo-comment comment-action inactive"
end
def show_comments_link(post, klass="")
@@ -43,15 +50,12 @@ module MobileHelper
entypo_class = "entypo-chevron-down"
end
- if post.comments_count > 0
- link_to "#{t('admins.stats.comments', count: post.comments_count)}<i class='#{entypo_class}'></i>".html_safe,
- post_comments_path(post, format: "mobile"),
- class: "show-comments #{klass}"
- else
- html = "<span class='show-comments'>"
- html << t("admins.stats.comments", count: post.comments_count)
- html << "</span>"
- end
+ link_to safe_join([
+ t("admins.stats.comments", count: post.comments_count),
+ content_tag(:i, nil, class: entypo_class)
+ ]),
+ post_comments_path(post, format: "mobile"),
+ class: "show-comments #{klass}"
end
def additional_photos
diff --git a/app/helpers/notifications_helper.rb b/app/helpers/notifications_helper.rb
index a5bca4a24..a8c1a533f 100644
--- a/app/helpers/notifications_helper.rb
+++ b/app/helpers/notifications_helper.rb
@@ -2,42 +2,46 @@ module NotificationsHelper
include PeopleHelper
include PostsHelper
- def object_link(note, actors)
+ def object_link(note, actors_html)
target_type = note.popup_translation_key
- actors_count = note.actors.size
+ opts = {actors: actors_html, count: note.actors.size}
- if note.instance_of?(Notifications::Mentioned)
- if post = note.linked_object
- translation(target_type,
- actors: actors,
- count: actors_count,
- post_link: link_to(post_page_title(post), post_path(post)).html_safe)
- else
- t(note.deleted_translation_key, :actors => actors, :count => actors_count).html_safe
+ if note.respond_to?(:linked_object)
+ if note.linked_object.nil? && note.respond_to?(:deleted_translation_key)
+ target_type = note.deleted_translation_key
+ elsif note.is_a?(Notifications::Mentioned)
+ opts.merge!(opts_for_mentioned(note.linked_object))
+ elsif %w(Notifications::CommentOnPost Notifications::AlsoCommented Notifications::Reshared Notifications::Liked)
+ .include?(note.type)
+ opts.merge!(opts_for_post(note.linked_object))
end
- elsif note.instance_of?(Notifications::CommentOnPost) || note.instance_of?(Notifications::AlsoCommented) || note.instance_of?(Notifications::Reshared) || note.instance_of?(Notifications::Liked)
- if post = note.linked_object
- translation(target_type,
- actors: actors,
- count: actors_count,
- post_author: h(post.author_name),
- post_link: link_to(post_page_title(post),
- post_path(post),
- data: {ref: post.id},
- class: "hard_object_link").html_safe)
- else
- t(note.deleted_translation_key, :actors => actors, :count => actors_count).html_safe
- end
- else #Notifications:StartedSharing, etc.
- translation(target_type, :actors => actors, :count => actors_count)
end
+ translation(target_type, opts)
end
def translation(target_type, opts = {})
- {:post_author => nil}.merge!(opts)
t("#{target_type}", opts).html_safe
end
+ def opts_for_post(post)
+ {
+ post_author: html_escape(post.author_name),
+ post_link: link_to(post_page_title(post),
+ post_path(post),
+ data: {ref: post.id},
+ class: "hard_object_link").html_safe
+ }
+ end
+
+ def opts_for_mentioned(mentioned)
+ post = mentioned.instance_of?(Comment) ? mentioned.parent : mentioned
+ {
+ post_link: link_to(post_page_title(post), post_path(post)).html_safe
+ }.tap {|opts|
+ opts[:comment_path] = post_path(post, anchor: mentioned.guid).html_safe if mentioned.instance_of?(Comment)
+ }
+ end
+
def notification_people_link(note, people=nil)
actors =people || note.actors
number_of_actors = actors.size
diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb
index d79b6b059..5d181ea9c 100644
--- a/app/helpers/users_helper.rb
+++ b/app/helpers/users_helper.rb
@@ -31,13 +31,13 @@ module UsersHelper
# specified from AVAILABLE_COLOR_THEMES in
# config/initializers/color_themes.rb.
#
- # @example if AVAILABLE_COLOR_THEMES = {"original"=>"Original dark", "dark_green" => "Dark green"}
+ # @example if AVAILABLE_COLOR_THEMES = ["original", "dark_green"]
# available_color_themes
- # #=> [["Original dark", "original"], ["Dark green", "dark_green"]]
+ # #=> [["Original gray", "original"], ["Dark green", "dark_green"]]
def available_color_themes
opts = []
- AVAILABLE_COLOR_THEMES.map do |theme_code, theme_name|
- opts << [theme_name, theme_code]
+ AVAILABLE_COLOR_THEMES.map do |theme_code|
+ opts << [I18n.t("color_themes.#{theme_code}"), theme_code]
end
opts
end
diff --git a/app/mailers/application_mailer.rb b/app/mailers/application_mailer.rb
new file mode 100644
index 000000000..e5ed1ffd0
--- /dev/null
+++ b/app/mailers/application_mailer.rb
@@ -0,0 +1,3 @@
+class ApplicationMailer < ActionMailer::Base
+ default from: "\"#{AppConfig.settings.pod_name}\" <#{AppConfig.mail.sender_address}>"
+end
diff --git a/app/mailers/diaspora_devise_mailer.rb b/app/mailers/diaspora_devise_mailer.rb
index 9a18ffb38..069b488b5 100644
--- a/app/mailers/diaspora_devise_mailer.rb
+++ b/app/mailers/diaspora_devise_mailer.rb
@@ -1,5 +1,5 @@
class DiasporaDeviseMailer < Devise::Mailer
- default :from => AppConfig.mail.sender_address
+ default from: "\"#{AppConfig.settings.pod_name}\" <#{AppConfig.mail.sender_address}>"
def self.mailer_name
"devise/mailer"
diff --git a/app/mailers/export_mailer.rb b/app/mailers/export_mailer.rb
index a0bc8b5e5..5139be734 100644
--- a/app/mailers/export_mailer.rb
+++ b/app/mailers/export_mailer.rb
@@ -1,6 +1,4 @@
-class ExportMailer < ActionMailer::Base
- default from: AppConfig.mail.sender_address
-
+class ExportMailer < ApplicationMailer
def export_complete_for(user)
@user = user
diff --git a/app/mailers/maintenance.rb b/app/mailers/maintenance.rb
index 6b0f2e07b..185b4f949 100644
--- a/app/mailers/maintenance.rb
+++ b/app/mailers/maintenance.rb
@@ -1,6 +1,4 @@
-class Maintenance < ActionMailer::Base
- default :from => AppConfig.mail.sender_address
-
+class Maintenance < ApplicationMailer
def account_removal_warning(user)
@user = user
@login_url = new_user_session_url
diff --git a/app/mailers/notification_mailers/also_commented.rb b/app/mailers/notification_mailers/also_commented.rb
index aa063cfa8..c6c4da8de 100644
--- a/app/mailers/notification_mailers/also_commented.rb
+++ b/app/mailers/notification_mailers/also_commented.rb
@@ -7,7 +7,6 @@ module NotificationMailers
@comment = Comment.find_by_id(comment_id)
if mail?
- @headers[:from] = "\"#{@comment.author_name} (diaspora*)\" <#{AppConfig.mail.sender_address}>"
@headers[:in_reply_to] = @headers[:references] = "<#{@comment.parent.guid}@#{AppConfig.pod_uri.host}>"
if @comment.public?
@headers[:subject] = "Re: #{@comment.comment_email_subject}"
diff --git a/app/mailers/notification_mailers/base.rb b/app/mailers/notification_mailers/base.rb
index bf3569fad..a8496df47 100644
--- a/app/mailers/notification_mailers/base.rb
+++ b/app/mailers/notification_mailers/base.rb
@@ -34,12 +34,13 @@ module NotificationMailers
def default_headers
headers = {
- from: AppConfig.mail.sender_address.get,
+ from: "\"#{AppConfig.settings.pod_name}\" <#{AppConfig.mail.sender_address}>",
host: "#{AppConfig.pod_uri.host}",
to: name_and_address(@recipient.name, @recipient.email)
}
-
- headers[:from] = "\"#{@sender.name} (diaspora*)\" <#{AppConfig.mail.sender_address}>" if @sender.present?
+ return headers if @sender.blank?
+ sender_in_header = @sender.profile.full_name.empty? ? @sender.username : @sender.name
+ headers[:from] = "\"#{AppConfig.settings.pod_name} (#{sender_in_header})\" <#{AppConfig.mail.sender_address}>"
headers
end
diff --git a/app/mailers/notification_mailers/comment_on_post.rb b/app/mailers/notification_mailers/comment_on_post.rb
index 4782f52b2..c9957e86f 100644
--- a/app/mailers/notification_mailers/comment_on_post.rb
+++ b/app/mailers/notification_mailers/comment_on_post.rb
@@ -5,7 +5,6 @@ module NotificationMailers
def set_headers(comment_id)
@comment = Comment.find(comment_id)
- @headers[:from] = "\"#{@comment.author_name} (diaspora*)\" <#{AppConfig.mail.sender_address}>"
@headers[:in_reply_to] = @headers[:references] = "<#{@comment.parent.guid}@#{AppConfig.pod_uri.host}>"
if @comment.public?
@headers[:subject] = "Re: #{@comment.comment_email_subject}"
diff --git a/app/mailers/notification_mailers/mentioned.rb b/app/mailers/notification_mailers/mentioned.rb
index a06c82e75..e72c2074d 100644
--- a/app/mailers/notification_mailers/mentioned.rb
+++ b/app/mailers/notification_mailers/mentioned.rb
@@ -4,7 +4,7 @@ module NotificationMailers
delegate :author_name, to: :post, prefix: true
def set_headers(target_id)
- @post = Mention.find_by_id(target_id).post
+ @post = Mention.find_by_id(target_id).mentions_container
@headers[:subject] = I18n.t('notifier.mentioned.subject', :name => @sender.name)
@headers[:in_reply_to] = @headers[:references] = "<#{@post.guid}@#{AppConfig.pod_uri.host}>"
diff --git a/app/mailers/notification_mailers/mentioned_in_comment.rb b/app/mailers/notification_mailers/mentioned_in_comment.rb
new file mode 100644
index 000000000..0e9a51bba
--- /dev/null
+++ b/app/mailers/notification_mailers/mentioned_in_comment.rb
@@ -0,0 +1,12 @@
+module NotificationMailers
+ class MentionedInComment < NotificationMailers::Base
+ attr_reader :comment
+
+ def set_headers(target_id) # rubocop:disable Style/AccessorMethodName
+ @comment = Mention.find_by_id(target_id).mentions_container
+
+ @headers[:in_reply_to] = @headers[:references] = "<#{@comment.parent.guid}@#{AppConfig.pod_uri.host}>"
+ @headers[:subject] = I18n.t("notifier.mentioned.subject", name: @sender.name)
+ end
+ end
+end
diff --git a/app/mailers/notification_mailers/private_message.rb b/app/mailers/notification_mailers/private_message.rb
index 9cbe71dc3..60a5013e8 100644
--- a/app/mailers/notification_mailers/private_message.rb
+++ b/app/mailers/notification_mailers/private_message.rb
@@ -3,11 +3,10 @@ module NotificationMailers
attr_accessor :message, :conversation, :participants
def set_headers(message_id)
- @message = Message.find_by_id(message_id)
+ @message = Message.find_by_id(message_id)
@conversation = @message.conversation
@participants = @conversation.participants
- @headers[:from] = "\"#{@message.author_name} (diaspora*)\" <#{AppConfig.mail.sender_address}>"
@headers[:subject] = I18n.t("notifier.private_message.subject")
@headers[:in_reply_to] = @headers[:references] = "<#{@conversation.guid}@#{AppConfig.pod_uri.host}>"
end
diff --git a/app/mailers/notification_mailers/started_sharing.rb b/app/mailers/notification_mailers/started_sharing.rb
index e02c50e43..bc4a8dd44 100644
--- a/app/mailers/notification_mailers/started_sharing.rb
+++ b/app/mailers/notification_mailers/started_sharing.rb
@@ -1,7 +1,7 @@
module NotificationMailers
class StartedSharing < NotificationMailers::Base
- def set_headers
- @headers[:subject] = I18n.t('notifier.started_sharing.subject', :name => @sender.name)
+ def set_headers(*_args) # rubocop:disable Style/AccessorMethodName
+ @headers[:subject] = I18n.t("notifier.started_sharing.subject", name: @sender.name)
end
end
end
diff --git a/app/mailers/notifier.rb b/app/mailers/notifier.rb
index 80630ebe2..187c7b0ed 100644
--- a/app/mailers/notifier.rb
+++ b/app/mailers/notifier.rb
@@ -1,4 +1,4 @@
-class Notifier < ActionMailer::Base
+class Notifier < ApplicationMailer
helper :application
helper :notifier
helper :people
@@ -44,9 +44,9 @@ class Notifier < ActionMailer::Base
@invitation_code = invitation_code
I18n.with_locale(locale) do
- mail_opts = {:to => email, :from => AppConfig.mail.sender_address,
- :subject => I18n.t('notifier.invited_you', :name => @inviter.name),
- :host => AppConfig.pod_uri.host}
+ mail_opts = {to: email, from: "\"#{AppConfig.settings.pod_name}\" <#{AppConfig.mail.sender_address}>",
+ subject: I18n.t("notifier.invited_you", name: @inviter.name),
+ host: AppConfig.pod_uri.host}
mail(mail_opts) do |format|
format.text { render :layout => nil }
@@ -55,54 +55,20 @@ class Notifier < ActionMailer::Base
end
end
- def started_sharing(recipient_id, sender_id)
- send_notification(:started_sharing, recipient_id, sender_id)
- end
-
- def liked(recipient_id, sender_id, like_id)
- send_notification(:liked, recipient_id, sender_id, like_id)
- end
-
- def reshared(recipient_id, sender_id, reshare_id)
- send_notification(:reshared, recipient_id, sender_id, reshare_id)
- end
-
- def mentioned(recipient_id, sender_id, target_id)
- send_notification(:mentioned, recipient_id, sender_id, target_id)
- end
-
- def comment_on_post(recipient_id, sender_id, comment_id)
- send_notification(:comment_on_post, recipient_id, sender_id, comment_id)
- end
-
- def also_commented(recipient_id, sender_id, comment_id)
- send_notification(:also_commented, recipient_id, sender_id, comment_id)
- end
-
- def private_message(recipient_id, sender_id, message_id)
- send_notification(:private_message, recipient_id, sender_id, message_id)
- end
-
- def confirm_email(recipient_id)
- send_notification(:confirm_email, recipient_id)
- end
-
- def csrf_token_fail(recipient_id)
- send_notification(:csrf_token_fail, recipient_id)
- end
-
- private
def send_notification(type, *args)
@notification = NotificationMailers.const_get(type.to_s.camelize).new(*args)
with_recipient_locale do
mail(@notification.headers) do |format|
+ self.action_name = type
format.text
format.html
end
end
end
+ private
+
def with_recipient_locale(&block)
I18n.with_locale(@notification.recipient.language, &block)
end
diff --git a/app/mailers/report_mailer.rb b/app/mailers/report_mailer.rb
index dbb3c2f12..0ac76892f 100644
--- a/app/mailers/report_mailer.rb
+++ b/app/mailers/report_mailer.rb
@@ -1,6 +1,4 @@
-class ReportMailer < ActionMailer::Base
- default from: AppConfig.mail.sender_address
-
+class ReportMailer < ApplicationMailer
def self.new_report(report_id)
report = Report.find_by_id(report_id)
Role.moderators.map {|role| super(report.item_type, report.item_id, report.text, role) }
diff --git a/app/models/account_deletion.rb b/app/models/account_deletion.rb
index bab962dca..b929279bb 100644
--- a/app/models/account_deletion.rb
+++ b/app/models/account_deletion.rb
@@ -2,31 +2,23 @@
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
-class AccountDeletion < ActiveRecord::Base
+class AccountDeletion < ApplicationRecord
include Diaspora::Federated::Base
- scope :uncompleted, -> { where('completed_at is null') }
+ scope :uncompleted, -> { where("completed_at is null") }
belongs_to :person
- after_commit :queue_delete_account, :on => :create
+ after_commit :queue_delete_account, on: :create
- def person=(person)
- self[:diaspora_handle] = person.diaspora_handle
- self[:person_id] = person.id
- end
-
- def diaspora_handle=(diaspora_handle)
- self[:diaspora_handle] = diaspora_handle
- self[:person_id] ||= Person.find_by_diaspora_handle(diaspora_handle).id
- end
+ delegate :diaspora_handle, to: :person
def queue_delete_account
- Workers::DeleteAccount.perform_async(self.id)
+ Workers::DeleteAccount.perform_async(id)
end
def perform!
Diaspora::Federation::Dispatcher.build(person.owner, self).dispatch if person.local?
- AccountDeleter.new(diaspora_handle).perform!
+ AccountDeleter.new(person).perform!
end
def subscribers
diff --git a/app/models/account_migration.rb b/app/models/account_migration.rb
new file mode 100644
index 000000000..9d2f451d5
--- /dev/null
+++ b/app/models/account_migration.rb
@@ -0,0 +1,165 @@
+class AccountMigration < ApplicationRecord
+ include Diaspora::Federated::Base
+
+ belongs_to :old_person, class_name: "Person"
+ belongs_to :new_person, class_name: "Person"
+
+ validates :old_person, uniqueness: true
+ validates :new_person, uniqueness: true
+
+ after_create :lock_old_user!
+
+ attr_accessor :old_private_key
+
+ def receive(*)
+ perform!
+ end
+
+ def public?
+ true
+ end
+
+ def sender
+ @sender ||= old_user || ephemeral_sender
+ end
+
+ # executes a migration plan according to this AccountMigration object
+ def perform!
+ raise "already performed" if performed?
+
+ ActiveRecord::Base.transaction do
+ account_deleter.tombstone_person_and_profile
+ account_deleter.close_user if user_left_our_pod?
+ account_deleter.tombstone_user if user_changed_id_locally?
+
+ update_all_references
+ end
+
+ dispatch if locally_initiated?
+ dispatch_contacts if remotely_initiated?
+ end
+
+ def performed?
+ old_person.closed_account?
+ end
+
+ # We assume that migration message subscribers are people that are subscribed to a new user profile updates.
+ # Since during the migration we update contact references, this includes all the contacts of the old person.
+ # In case when a user migrated to our pod from a remote one, we include remote person to subscribers so that
+ # the new pod is informed about the migration as well.
+ def subscribers
+ new_user.profile.subscribers.remote.to_a.tap do |subscribers|
+ subscribers.push(old_person) if old_person.remote?
+ end
+ end
+
+ private
+
+ # Normally pod initiates migration locally when the new user is local. Then the pod creates AccountMigration object
+ # itself. If new user is remote, then AccountMigration object is normally received via the federation and this is
+ # remote initiation then.
+ def remotely_initiated?
+ new_person.remote?
+ end
+
+ def locally_initiated?
+ !remotely_initiated?
+ end
+
+ def old_user
+ old_person.owner
+ end
+
+ def new_user
+ new_person.owner
+ end
+
+ def lock_old_user!
+ old_user&.lock_access!
+ end
+
+ def user_left_our_pod?
+ old_user && !new_user
+ end
+
+ def user_changed_id_locally?
+ old_user && new_user
+ end
+
+ # We need to resend contacts of users of our pod for the remote new person so that the remote pod received this
+ # contact information from the authoritative source.
+ def dispatch_contacts
+ new_person.contacts.sharing.each do |contact|
+ Diaspora::Federation::Dispatcher.defer_dispatch(contact.user, contact)
+ end
+ end
+
+ def dispatch
+ Diaspora::Federation::Dispatcher.build(sender, self).dispatch
+ end
+
+ EphemeralUser = Struct.new(:diaspora_handle, :serialized_private_key) do
+ def id
+ diaspora_handle
+ end
+
+ def encryption_key
+ OpenSSL::PKey::RSA.new(serialized_private_key)
+ end
+ end
+
+ def ephemeral_sender
+ raise "can't build sender without old private key defined" if old_private_key.nil?
+ EphemeralUser.new(old_person.diaspora_handle, old_private_key)
+ end
+
+ def update_all_references
+ update_person_references
+ update_user_references if user_changed_id_locally?
+ end
+
+ def person_references
+ references = Person.reflections.reject {|key, _|
+ %w[profile owner notifications pod].include?(key)
+ }
+
+ references.map {|key, value|
+ {value.foreign_key => key}
+ }
+ end
+
+ def user_references
+ references = User.reflections.reject {|key, _|
+ %w[
+ person profile auto_follow_back_aspect invited_by aspect_memberships contact_people followed_tags
+ ignored_people conversation_visibilities pairwise_pseudonymous_identifiers conversations o_auth_applications
+ ].include?(key)
+ }
+
+ references.map {|key, value|
+ {value.foreign_key => key}
+ }
+ end
+
+ def update_person_references
+ logger.debug "Updating references from person id=#{old_person.id} to person id=#{new_person.id}"
+ update_references(person_references, old_person, new_person.id)
+ end
+
+ def update_user_references
+ logger.debug "Updating references from user id=#{old_user.id} to user id=#{new_user.id}"
+ update_references(user_references, old_user, new_user.id)
+ end
+
+ def update_references(references, object, new_id)
+ references.each do |pair|
+ key_id = pair.flatten[0]
+ association = pair.flatten[1]
+ object.send(association).update_all(key_id => new_id)
+ end
+ end
+
+ def account_deleter
+ @account_deleter ||= AccountDeleter.new(old_person)
+ end
+end
diff --git a/app/models/api/openid_connect/authorization.rb b/app/models/api/openid_connect/authorization.rb
index 41c6c0e6f..a57231552 100644
--- a/app/models/api/openid_connect/authorization.rb
+++ b/app/models/api/openid_connect/authorization.rb
@@ -2,12 +2,11 @@
module Api
module OpenidConnect
- class Authorization < ActiveRecord::Base
+ class Authorization < ApplicationRecord
belongs_to :user
belongs_to :o_auth_application
- validates :user, presence: true, uniqueness: {scope: :o_auth_application}
- validates :o_auth_application, presence: true
+ validates :user, uniqueness: {scope: :o_auth_application}
validate :validate_scope_names
serialize :scopes, JSON
diff --git a/app/models/api/openid_connect/o_auth_access_token.rb b/app/models/api/openid_connect/o_auth_access_token.rb
index 053bc86df..e2089fff8 100644
--- a/app/models/api/openid_connect/o_auth_access_token.rb
+++ b/app/models/api/openid_connect/o_auth_access_token.rb
@@ -23,13 +23,12 @@
module Api
module OpenidConnect
- class OAuthAccessToken < ActiveRecord::Base
+ class OAuthAccessToken < ApplicationRecord
belongs_to :authorization
before_validation :setup, on: :create
validates :token, presence: true, uniqueness: true
- validates :authorization, presence: true
scope :valid, ->(time) { where("expires_at >= ?", time) }
diff --git a/app/models/api/openid_connect/o_auth_application.rb b/app/models/api/openid_connect/o_auth_application.rb
index ccceadfea..acf2817e4 100644
--- a/app/models/api/openid_connect/o_auth_application.rb
+++ b/app/models/api/openid_connect/o_auth_application.rb
@@ -25,7 +25,7 @@ require "digest"
module Api
module OpenidConnect
- class OAuthApplication < ActiveRecord::Base
+ class OAuthApplication < ApplicationRecord
has_many :authorizations, dependent: :destroy
has_many :user, through: :authorizations
diff --git a/app/models/api/openid_connect/pairwise_pseudonymous_identifier.rb b/app/models/api/openid_connect/pairwise_pseudonymous_identifier.rb
index 7aeccc9fa..520bc782c 100644
--- a/app/models/api/openid_connect/pairwise_pseudonymous_identifier.rb
+++ b/app/models/api/openid_connect/pairwise_pseudonymous_identifier.rb
@@ -23,13 +23,12 @@
module Api
module OpenidConnect
- class PairwisePseudonymousIdentifier < ActiveRecord::Base
+ class PairwisePseudonymousIdentifier < ApplicationRecord
self.table_name = "ppid"
- belongs_to :o_auth_application
+ belongs_to :o_auth_application, optional: true
belongs_to :user
- validates :user, presence: true
validates :identifier, presence: true, uniqueness: {scope: :user}
validates :guid, presence: true, uniqueness: true
diff --git a/app/models/application_record.rb b/app/models/application_record.rb
new file mode 100644
index 000000000..10a4cba84
--- /dev/null
+++ b/app/models/application_record.rb
@@ -0,0 +1,3 @@
+class ApplicationRecord < ActiveRecord::Base
+ self.abstract_class = true
+end
diff --git a/app/models/aspect.rb b/app/models/aspect.rb
index dfacdc811..4f6054dce 100644
--- a/app/models/aspect.rb
+++ b/app/models/aspect.rb
@@ -2,7 +2,7 @@
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
-class Aspect < ActiveRecord::Base
+class Aspect < ApplicationRecord
belongs_to :user
has_many :aspect_memberships, :dependent => :destroy
diff --git a/app/models/aspect_membership.rb b/app/models/aspect_membership.rb
index 8155c241f..8901f16a2 100644
--- a/app/models/aspect_membership.rb
+++ b/app/models/aspect_membership.rb
@@ -2,7 +2,7 @@
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
-class AspectMembership < ActiveRecord::Base
+class AspectMembership < ApplicationRecord
belongs_to :aspect
belongs_to :contact
diff --git a/app/models/aspect_visibility.rb b/app/models/aspect_visibility.rb
index 88e645727..be36323cb 100644
--- a/app/models/aspect_visibility.rb
+++ b/app/models/aspect_visibility.rb
@@ -2,13 +2,11 @@
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
-class AspectVisibility < ActiveRecord::Base
+class AspectVisibility < ApplicationRecord
belongs_to :aspect
- validates :aspect, :presence => true
belongs_to :shareable, :polymorphic => true
- validates :shareable, :presence => true
validates :aspect, uniqueness: {scope: %i(shareable_id shareable_type)}
end
diff --git a/app/models/block.rb b/app/models/block.rb
index 1eba8f4c8..57b470e58 100644
--- a/app/models/block.rb
+++ b/app/models/block.rb
@@ -1,11 +1,10 @@
-class Block < ActiveRecord::Base
+class Block < ApplicationRecord
belongs_to :person
belongs_to :user
delegate :name, to: :person, prefix: true
- validates :user_id, :presence => true
- validates :person_id, :presence => true, :uniqueness => { :scope => :user_id }
+ validates :person_id, uniqueness: {scope: :user_id}
validate :not_blocking_yourself
diff --git a/app/models/comment.rb b/app/models/comment.rb
index 8d98e52ec..4b6baa250 100644
--- a/app/models/comment.rb
+++ b/app/models/comment.rb
@@ -2,7 +2,7 @@
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
-class Comment < ActiveRecord::Base
+class Comment < ApplicationRecord
include Diaspora::Federated::Base
include Diaspora::Fields::Guid
@@ -11,6 +11,7 @@ class Comment < ActiveRecord::Base
include Diaspora::Taggable
include Diaspora::Likeable
+ include Diaspora::MentionsContainer
acts_as_taggable_on :tags
extract_tags_from :text
@@ -25,7 +26,6 @@ class Comment < ActiveRecord::Base
delegate :author_name, to: :parent, prefix: true
validates :text, :presence => true, :length => {:maximum => 65535}
- validates :parent, :presence => true #should be in relayable (pending on fixing Message)
has_many :reports, as: :item
@@ -49,14 +49,14 @@ class Comment < ActiveRecord::Base
participation.unparticipate! if participation.present?
end
- def message
- @message ||= Diaspora::MessageRenderer.new text
- end
-
def text= text
self[:text] = text.to_s.strip #to_s if for nil, for whatever reason
end
+ def add_mention_subscribers?
+ super && parent.author.local?
+ end
+
class Generator < Diaspora::Federated::Generator
def self.federated_class
Comment
@@ -68,7 +68,7 @@ class Comment < ActiveRecord::Base
end
def relayable_options
- {:post => @target, :text => @text}
+ {post: @target, text: @text}
end
end
end
diff --git a/app/models/comment_signature.rb b/app/models/comment_signature.rb
index 357bcb3b8..9e7aa9270 100644
--- a/app/models/comment_signature.rb
+++ b/app/models/comment_signature.rb
@@ -1,7 +1,6 @@
-class CommentSignature < ActiveRecord::Base
+class CommentSignature < ApplicationRecord
include Diaspora::Signature
self.primary_key = :comment_id
belongs_to :comment
- validates :comment, presence: true
end
diff --git a/app/models/contact.rb b/app/models/contact.rb
index c7970a2f9..666815d47 100644
--- a/app/models/contact.rb
+++ b/app/models/contact.rb
@@ -2,14 +2,11 @@
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
-class Contact < ActiveRecord::Base
+class Contact < ApplicationRecord
include Diaspora::Federated::Base
belongs_to :user
- validates :user, presence: true
-
belongs_to :person
- validates :person, presence: true
validates :person_id, uniqueness: {scope: :user_id}
diff --git a/app/models/conversation.rb b/app/models/conversation.rb
index 4802d247e..f597af001 100644
--- a/app/models/conversation.rb
+++ b/app/models/conversation.rb
@@ -1,4 +1,4 @@
-class Conversation < ActiveRecord::Base
+class Conversation < ApplicationRecord
include Diaspora::Federated::Base
include Diaspora::Fields::Guid
include Diaspora::Fields::Author
diff --git a/app/models/conversation_visibility.rb b/app/models/conversation_visibility.rb
index 9c0afb2bd..39e7e66cd 100644
--- a/app/models/conversation_visibility.rb
+++ b/app/models/conversation_visibility.rb
@@ -1,4 +1,4 @@
-class ConversationVisibility < ActiveRecord::Base
+class ConversationVisibility < ApplicationRecord
belongs_to :conversation
belongs_to :person
@@ -6,7 +6,7 @@ class ConversationVisibility < ActiveRecord::Base
after_destroy :check_orphan_conversation
private
-
+
def check_orphan_conversation
conversation = Conversation.find_by_id(self.conversation.id)
if conversation
diff --git a/app/models/invitation_code.rb b/app/models/invitation_code.rb
index 7b732359d..1dd565871 100644
--- a/app/models/invitation_code.rb
+++ b/app/models/invitation_code.rb
@@ -1,8 +1,6 @@
-class InvitationCode < ActiveRecord::Base
+class InvitationCode < ApplicationRecord
belongs_to :user
- validates_presence_of :user
-
before_create :generate_token, :set_default_invite_count
delegate :name, to: :user, prefix: true
diff --git a/app/models/like.rb b/app/models/like.rb
index 78eb9c3da..828d5b8aa 100644
--- a/app/models/like.rb
+++ b/app/models/like.rb
@@ -2,7 +2,7 @@
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
-class Like < ActiveRecord::Base
+class Like < ApplicationRecord
include Diaspora::Federated::Base
include Diaspora::Fields::Guid
include Diaspora::Fields::Author
diff --git a/app/models/like_signature.rb b/app/models/like_signature.rb
index 6978704a9..bc21533d4 100644
--- a/app/models/like_signature.rb
+++ b/app/models/like_signature.rb
@@ -1,7 +1,6 @@
-class LikeSignature < ActiveRecord::Base
+class LikeSignature < ApplicationRecord
include Diaspora::Signature
self.primary_key = :like_id
belongs_to :like
- validates :like, presence: true
end
diff --git a/app/models/location.rb b/app/models/location.rb
index 0620104ad..37132f147 100644
--- a/app/models/location.rb
+++ b/app/models/location.rb
@@ -1,4 +1,4 @@
-class Location < ActiveRecord::Base
+class Location < ApplicationRecord
before_validation :split_coords, on: :create
validates_presence_of :lat, :lng
diff --git a/app/models/mention.rb b/app/models/mention.rb
index 9ddfd8dad..c5bb859e5 100644
--- a/app/models/mention.rb
+++ b/app/models/mention.rb
@@ -2,11 +2,13 @@
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
-class Mention < ActiveRecord::Base
- belongs_to :post
+class Mention < ApplicationRecord
+ belongs_to :mentions_container, polymorphic: true
belongs_to :person
- validates :post, presence: true
- validates :person, presence: true
+
+ scope :local, -> {
+ joins(:person).where.not(people: {owner_id: nil})
+ }
after_destroy :delete_notification
diff --git a/app/models/message.rb b/app/models/message.rb
index 82c551262..95992e689 100644
--- a/app/models/message.rb
+++ b/app/models/message.rb
@@ -1,4 +1,4 @@
-class Message < ActiveRecord::Base
+class Message < ApplicationRecord
include Diaspora::Federated::Base
include Diaspora::Fields::Guid
include Diaspora::Fields::Author
@@ -7,10 +7,6 @@ class Message < ActiveRecord::Base
delegate :name, to: :author, prefix: true
- # TODO: can be removed when messages are not relayed anymore
- alias_attribute :parent, :conversation
-
- validates :conversation, presence: true
validates :text, presence: true
validate :participant_of_parent_conversation
@@ -31,11 +27,7 @@ class Message < ActiveRecord::Base
# @return [Array<Person>]
def subscribers
- if author.local?
- conversation.participants
- else # for relaying, TODO: can be removed when messages are not relayed anymore
- conversation.participants.remote
- end
+ conversation.participants
end
private
diff --git a/app/models/notification.rb b/app/models/notification.rb
index aaa56d53d..f1adf5325 100644
--- a/app/models/notification.rb
+++ b/app/models/notification.rb
@@ -2,7 +2,7 @@
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
#
-class Notification < ActiveRecord::Base
+class Notification < ApplicationRecord
belongs_to :recipient, class_name: "User"
has_many :notification_actors, dependent: :destroy
has_many :actors, class_name: "Person", through: :notification_actors, source: :person
@@ -51,15 +51,4 @@ class Notification < ActiveRecord::Base
private_class_method def self.suppress_notification?(recipient, actor)
recipient.blocks.where(person: actor).exists?
end
-
- def self.types
- {
- "also_commented" => "Notifications::AlsoCommented",
- "comment_on_post" => "Notifications::CommentOnPost",
- "liked" => "Notifications::Liked",
- "mentioned" => "Notifications::Mentioned",
- "reshared" => "Notifications::Reshared",
- "started_sharing" => "Notifications::StartedSharing"
- }
- end
end
diff --git a/app/models/notification_actor.rb b/app/models/notification_actor.rb
index 2b47a5cff..beaeefbb6 100644
--- a/app/models/notification_actor.rb
+++ b/app/models/notification_actor.rb
@@ -2,7 +2,7 @@
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
-class NotificationActor < ActiveRecord::Base
+class NotificationActor < ApplicationRecord
belongs_to :notification
belongs_to :person
diff --git a/app/models/notifications/also_commented.rb b/app/models/notifications/also_commented.rb
index a345566f3..cc28c047c 100644
--- a/app/models/notifications/also_commented.rb
+++ b/app/models/notifications/also_commented.rb
@@ -1,5 +1,7 @@
module Notifications
class AlsoCommented < Notification
+ include Notifications::Commented
+
def mail_job
Workers::Mail::AlsoCommented
end
@@ -8,17 +10,13 @@ module Notifications
"notifications.also_commented"
end
- def deleted_translation_key
- "notifications.also_commented_deleted"
- end
-
def self.notify(comment, _recipient_user_ids)
actor = comment.author
commentable = comment.commentable
recipient_ids = commentable.participants.local.where.not(id: [commentable.author_id, actor.id]).pluck(:owner_id)
User.where(id: recipient_ids).find_each do |recipient|
- next if recipient.is_shareable_hidden?(commentable)
+ next if recipient.is_shareable_hidden?(commentable) || mention_notification_exists?(comment, recipient.person)
concatenate_or_create(recipient, commentable, actor).try(:email_the_user, comment, actor)
end
diff --git a/app/models/notifications/comment_on_post.rb b/app/models/notifications/comment_on_post.rb
index df23b558e..ee3320e39 100644
--- a/app/models/notifications/comment_on_post.rb
+++ b/app/models/notifications/comment_on_post.rb
@@ -1,5 +1,7 @@
module Notifications
class CommentOnPost < Notification
+ include Notifications::Commented
+
def mail_job
Workers::Mail::CommentOnPost
end
@@ -8,15 +10,12 @@ module Notifications
"notifications.comment_on_post"
end
- def deleted_translation_key
- "notifications.also_commented_deleted"
- end
-
def self.notify(comment, _recipient_user_ids)
actor = comment.author
commentable_author = comment.commentable.author
return unless commentable_author.local? && actor != commentable_author
+ return if mention_notification_exists?(comment, commentable_author)
concatenate_or_create(commentable_author.owner, comment.commentable, actor).email_the_user(comment, actor)
end
diff --git a/app/models/notifications/commented.rb b/app/models/notifications/commented.rb
new file mode 100644
index 000000000..e5b1b7d48
--- /dev/null
+++ b/app/models/notifications/commented.rb
@@ -0,0 +1,15 @@
+module Notifications
+ module Commented
+ extend ActiveSupport::Concern
+
+ def deleted_translation_key
+ "notifications.also_commented_deleted"
+ end
+
+ module ClassMethods
+ def mention_notification_exists?(comment, recipient_person)
+ Notifications::MentionedInComment.exists?(target: comment.mentions.where(person: recipient_person))
+ end
+ end
+ end
+end
diff --git a/app/models/notifications/mentioned.rb b/app/models/notifications/mentioned.rb
index bede65ee4..b128791bb 100644
--- a/app/models/notifications/mentioned.rb
+++ b/app/models/notifications/mentioned.rb
@@ -1,30 +1,23 @@
module Notifications
- class Mentioned < Notification
- def mail_job
- Workers::Mail::Mentioned
- end
-
- def popup_translation_key
- "notifications.mentioned"
- end
-
- def deleted_translation_key
- "notifications.mentioned_deleted"
- end
+ module Mentioned
+ extend ActiveSupport::Concern
def linked_object
- target.post
+ target.mentions_container
end
- def self.notify(mentionable, recipient_user_ids)
- actor = mentionable.author
-
- mentionable.mentions.select {|mention| mention.person.local? }.each do |mention|
- recipient = mention.person
-
- next if recipient == actor || !(mentionable.public || recipient_user_ids.include?(recipient.owner_id))
+ module ClassMethods
+ def notify(mentionable, recipient_user_ids)
+ actor = mentionable.author
+ relevant_mentions = filter_mentions(
+ mentionable.mentions.local.where.not(person: actor),
+ mentionable,
+ recipient_user_ids
+ )
- create_notification(recipient.owner, mention, actor).try(:email_the_user, mention, actor)
+ relevant_mentions.each do |mention|
+ create_notification(mention.person.owner, mention, actor).try(:email_the_user, mention, actor)
+ end
end
end
end
diff --git a/app/models/notifications/mentioned_in_comment.rb b/app/models/notifications/mentioned_in_comment.rb
new file mode 100644
index 000000000..35ef9b61a
--- /dev/null
+++ b/app/models/notifications/mentioned_in_comment.rb
@@ -0,0 +1,33 @@
+module Notifications
+ class MentionedInComment < Notification
+ include Notifications::Mentioned
+
+ def popup_translation_key
+ "notifications.mentioned_in_comment"
+ end
+
+ def deleted_translation_key
+ "notifications.mentioned_in_comment_deleted"
+ end
+
+ def self.filter_mentions(mentions, mentionable, _recipient_user_ids)
+ mentions.includes(:person).merge(Person.allowed_to_be_mentioned_in_a_comment_to(mentionable.parent))
+ end
+
+ def mail_job
+ if !recipient.user_preferences.exists?(email_type: "mentioned_in_comment")
+ Workers::Mail::MentionedInComment
+ elsif shareable.author.owner_id == recipient_id
+ Workers::Mail::CommentOnPost
+ elsif shareable.participants.local.where(owner_id: recipient_id)
+ Workers::Mail::AlsoCommented
+ end
+ end
+
+ private
+
+ def shareable
+ linked_object.parent
+ end
+ end
+end
diff --git a/app/models/notifications/mentioned_in_post.rb b/app/models/notifications/mentioned_in_post.rb
new file mode 100644
index 000000000..35ec36c45
--- /dev/null
+++ b/app/models/notifications/mentioned_in_post.rb
@@ -0,0 +1,22 @@
+module Notifications
+ class MentionedInPost < Notification
+ include Notifications::Mentioned
+
+ def mail_job
+ Workers::Mail::Mentioned
+ end
+
+ def popup_translation_key
+ "notifications.mentioned"
+ end
+
+ def deleted_translation_key
+ "notifications.mentioned_deleted"
+ end
+
+ def self.filter_mentions(mentions, mentionable, recipient_user_ids)
+ return mentions if mentionable.public
+ mentions.where(person: Person.where(owner_id: recipient_user_ids).ids)
+ end
+ end
+end
diff --git a/app/models/o_embed_cache.rb b/app/models/o_embed_cache.rb
index 17e6f073f..30967d1bd 100644
--- a/app/models/o_embed_cache.rb
+++ b/app/models/o_embed_cache.rb
@@ -1,4 +1,4 @@
-class OEmbedCache < ActiveRecord::Base
+class OEmbedCache < ApplicationRecord
serialize :data
validates :data, :presence => true
diff --git a/app/models/open_graph_cache.rb b/app/models/open_graph_cache.rb
index ffae81c94..0aa0a2fe6 100644
--- a/app/models/open_graph_cache.rb
+++ b/app/models/open_graph_cache.rb
@@ -1,4 +1,4 @@
-class OpenGraphCache < ActiveRecord::Base
+class OpenGraphCache < ApplicationRecord
validates :title, :presence => true
validates :ob_type, :presence => true
validates :image, :presence => true
diff --git a/app/models/participation.rb b/app/models/participation.rb
index 94d82fb95..4bdda1a92 100644
--- a/app/models/participation.rb
+++ b/app/models/participation.rb
@@ -1,4 +1,4 @@
-class Participation < ActiveRecord::Base
+class Participation < ApplicationRecord
include Diaspora::Federated::Base
include Diaspora::Fields::Guid
include Diaspora::Fields::Author
diff --git a/app/models/person.rb b/app/models/person.rb
index f4a5202ad..87a0f02cf 100644
--- a/app/models/person.rb
+++ b/app/models/person.rb
@@ -2,7 +2,7 @@
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
-class Person < ActiveRecord::Base
+class Person < ApplicationRecord
include Diaspora::Fields::Guid
# NOTE API V1 to be extracted
@@ -22,7 +22,7 @@ class Person < ActiveRecord::Base
end
has_one :profile, dependent: :destroy
- delegate :last_name, :image_url, :tag_string, :bio, :location,
+ delegate :last_name, :full_name, :image_url, :tag_string, :bio, :location,
:gender, :birthday, :formatted_birthday, :tags, :searchable,
:public_details?, to: :profile
accepts_nested_attributes_for :profile
@@ -37,13 +37,18 @@ class Person < ActiveRecord::Base
has_many :posts, :foreign_key => :author_id, :dependent => :destroy # This person's own posts
has_many :photos, :foreign_key => :author_id, :dependent => :destroy # This person's own photos
has_many :comments, :foreign_key => :author_id, :dependent => :destroy # This person's own comments
+ has_many :likes, foreign_key: :author_id, dependent: :destroy # This person's own likes
has_many :participations, :foreign_key => :author_id, :dependent => :destroy
- has_many :conversation_visibilities
+ has_many :poll_participations, foreign_key: :author_id, dependent: :destroy
+ has_many :conversation_visibilities, dependent: :destroy
+ has_many :messages, foreign_key: :author_id, dependent: :destroy
+ has_many :conversations, foreign_key: :author_id, dependent: :destroy
+ has_many :blocks, dependent: :destroy
has_many :roles
- belongs_to :owner, :class_name => 'User'
- belongs_to :pod
+ belongs_to :owner, class_name: "User", optional: true
+ belongs_to :pod, optional: true
has_many :notification_actors
has_many :notifications, :through => :notification_actors
@@ -61,10 +66,7 @@ class Person < ActiveRecord::Base
}
scope :remote, -> { where('people.owner_id IS NULL') }
scope :local, -> { where('people.owner_id IS NOT NULL') }
- scope :for_json, -> {
- select('DISTINCT people.id, people.guid, people.diaspora_handle')
- .includes(:profile)
- }
+ scope :for_json, -> { select("people.id, people.guid, people.diaspora_handle").includes(:profile) }
# @note user is passed in here defensively
scope :all_from_aspects, ->(aspect_ids, user) {
@@ -79,8 +81,8 @@ class Person < ActiveRecord::Base
#not defensive
scope :in_aspects, ->(aspect_ids) {
- joins(:contacts => :aspect_memberships).
- where(:aspect_memberships => {:aspect_id => aspect_ids})
+ joins(contacts: :aspect_memberships)
+ .where(aspect_memberships: {aspect_id: aspect_ids}).distinct
}
scope :profile_tagged_with, ->(tag_name) {
@@ -94,6 +96,81 @@ class Person < ActiveRecord::Base
.where(:posts => {:root_guid => StatusMessage.guids_for_author(user.person), :type => 'Reshare'} )
}
+ # This scope selects people where the full name contains the search_str or diaspora ID
+ # starts with the search_str.
+ # However, if the search_str doesn't have more than 1 non-whitespace character, it'll return an empty set.
+ # @param [String] search substring
+ # @return [Person::ActiveRecord_Relation]
+ scope :find_by_substring, ->(search_str) {
+ search_str.strip!
+ if search_str.blank? || search_str.size < 2
+ none
+ else
+ sql, tokens = search_query_string(search_str)
+ joins(:profile).where(sql, *tokens)
+ end
+ }
+
+ # Left joins likes and comments to a specific post where people are authors of these comments and likes
+ # @param [String, Integer] post ID for which comments and likes should be joined
+ # @return [Person::ActiveRecord_Relation]
+ scope :left_join_visible_post_interactions_on_authorship, ->(post_id) {
+ comments_sql = <<-SQL
+ LEFT OUTER JOIN comments ON
+ comments.author_id = people.id AND comments.commentable_type = 'Post' AND comments.commentable_id = #{post_id}
+ SQL
+
+ likes_sql = <<-SQL
+ LEFT OUTER JOIN likes ON
+ likes.author_id = people.id AND likes.target_type = 'Post' AND likes.target_id = #{post_id}
+ SQL
+
+ joins(comments_sql).joins(likes_sql)
+ }
+
+ # Selects people who can be mentioned in a comment to a specific post. For public posts all people
+ # are allowed, so no additional constraints are added. For private posts selection is limited to
+ # people who have posted comments or likes for this post.
+ # @param [Post] the post for which we query mentionable in comments people
+ # @return [Person::ActiveRecord_Relation]
+ scope :allowed_to_be_mentioned_in_a_comment_to, ->(post) {
+ allowed = if post.public?
+ all
+ else
+ left_join_visible_post_interactions_on_authorship(post.id)
+ .where("comments.id IS NOT NULL OR likes.id IS NOT NULL OR people.id = #{post.author_id}")
+ end
+ allowed.distinct
+ }
+
+ # This scope adds sorting of people in the order, appropriate for suggesting to a user (current user) who
+ # has requested a list of the people mentionable in a comment for a specific post.
+ # Sorts people in the following priority: post author > commenters > likers > contacts > non-contacts
+ # @param [Post] post for which the mentionable in comment people list is requested
+ # @param [User] user who requests the people list
+ # @return [Person::ActiveRecord_Relation]
+ scope :sort_for_mention_suggestion, ->(post, user) {
+ left_join_visible_post_interactions_on_authorship(post.id)
+ .joins("LEFT OUTER JOIN contacts ON people.id = contacts.person_id AND contacts.user_id = #{user.id}")
+ .joins(:profile)
+ .select(<<-SQL
+ people.id = #{unscoped { post.author_id }} AS is_author,
+ comments.id IS NOT NULL AS is_commenter,
+ likes.id IS NOT NULL AS is_liker,
+ contacts.id IS NOT NULL AS is_contact
+ SQL
+ )
+ .order(<<-SQL
+ is_author DESC,
+ is_commenter DESC,
+ is_liker DESC,
+ is_contact DESC,
+ profiles.full_name,
+ people.diaspora_handle
+ SQL
+ )
+ }
+
def self.community_spotlight
Person.joins(:roles).where(:roles => {:name => 'spotlight'})
end
@@ -128,7 +205,7 @@ class Person < ActiveRecord::Base
self.guid
end
- def self.search_query_string(query)
+ private_class_method def self.search_query_string(query)
query = query.downcase
like_operator = AppConfig.postgres? ? "ILIKE" : "LIKE"
@@ -146,15 +223,13 @@ class Person < ActiveRecord::Base
end
def self.search(search_str, user, only_contacts: false, mutual: false)
- search_str.strip!
- return none if search_str.blank? || search_str.size < 2
-
- sql, tokens = search_query_string(search_str)
+ query = find_by_substring(search_str)
+ return query if query.is_a?(ActiveRecord::NullRelation)
query = if only_contacts
- joins(:contacts).where(contacts: {user_id: user.id})
+ query.joins(:contacts).where(contacts: {user_id: user.id})
else
- joins(
+ query.joins(
"LEFT OUTER JOIN contacts ON contacts.user_id = #{user.id} AND contacts.person_id = people.id"
).searchable(user)
end
@@ -162,8 +237,6 @@ class Person < ActiveRecord::Base
query = query.where(contacts: {sharing: true, receiving: true}) if mutual
query.where(closed_account: false)
- .where(sql, *tokens)
- .includes(:profile)
.order(["contacts.user_id IS NULL", "profiles.last_name ASC", "profiles.first_name ASC"])
end
@@ -237,11 +310,6 @@ class Person < ActiveRecord::Base
serialized_public_key
end
- def exported_key= new_key
- raise "Don't change a key" if serialized_public_key
- serialized_public_key = new_key
- end
-
# discovery (webfinger)
def self.find_or_fetch_by_identifier(diaspora_id)
# exiting person?
diff --git a/app/models/photo.rb b/app/models/photo.rb
index 17e9b9ff8..7fa0c3871 100644
--- a/app/models/photo.rb
+++ b/app/models/photo.rb
@@ -2,7 +2,7 @@
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
-class Photo < ActiveRecord::Base
+class Photo < ApplicationRecord
include Diaspora::Federated::Base
include Diaspora::Commentable
include Diaspora::Shareable
@@ -37,7 +37,7 @@ class Photo < ActiveRecord::Base
mount_uploader :processed_image, ProcessedImage
mount_uploader :unprocessed_image, UnprocessedImage
- belongs_to :status_message, :foreign_key => :status_message_guid, :primary_key => :guid
+ belongs_to :status_message, foreign_key: :status_message_guid, primary_key: :guid, optional: true
validates_associated :status_message
delegate :author_name, to: :status_message, prefix: true
diff --git a/app/models/pod.rb b/app/models/pod.rb
index dde1e28f1..b88c76cde 100644
--- a/app/models/pod.rb
+++ b/app/models/pod.rb
@@ -1,4 +1,4 @@
-class Pod < ActiveRecord::Base
+class Pod < ApplicationRecord
enum status: %i(
unchecked
no_errors
diff --git a/app/models/poll.rb b/app/models/poll.rb
index fa9033577..15589d601 100644
--- a/app/models/poll.rb
+++ b/app/models/poll.rb
@@ -1,4 +1,4 @@
-class Poll < ActiveRecord::Base
+class Poll < ApplicationRecord
include Diaspora::Federated::Base
include Diaspora::Fields::Guid
diff --git a/app/models/poll_answer.rb b/app/models/poll_answer.rb
index 3387efe09..d91c4e13a 100644
--- a/app/models/poll_answer.rb
+++ b/app/models/poll_answer.rb
@@ -1,4 +1,4 @@
-class PollAnswer < ActiveRecord::Base
+class PollAnswer < ApplicationRecord
include Diaspora::Federated::Base
include Diaspora::Fields::Guid
diff --git a/app/models/poll_participation.rb b/app/models/poll_participation.rb
index 8dba27465..24f99f9ef 100644
--- a/app/models/poll_participation.rb
+++ b/app/models/poll_participation.rb
@@ -1,4 +1,4 @@
-class PollParticipation < ActiveRecord::Base
+class PollParticipation < ApplicationRecord
include Diaspora::Federated::Base
include Diaspora::Fields::Guid
include Diaspora::Fields::Author
@@ -6,12 +6,12 @@ class PollParticipation < ActiveRecord::Base
belongs_to :poll
belongs_to :poll_answer, counter_cache: :vote_count
+ has_one :status_message, through: :poll
has_one :signature, class_name: "PollParticipationSignature", dependent: :delete
alias_attribute :parent, :poll
- validates :poll_answer, presence: true
validate :not_already_participated
def poll_answer_guid=(new_poll_answer_guid)
diff --git a/app/models/poll_participation_signature.rb b/app/models/poll_participation_signature.rb
index 90701f286..a32b8653e 100644
--- a/app/models/poll_participation_signature.rb
+++ b/app/models/poll_participation_signature.rb
@@ -1,7 +1,6 @@
-class PollParticipationSignature < ActiveRecord::Base
+class PollParticipationSignature < ApplicationRecord
include Diaspora::Signature
self.primary_key = :poll_participation_id
belongs_to :poll_participation
- validates :poll_participation, presence: true
end
diff --git a/app/models/post.rb b/app/models/post.rb
index 3ad235f0f..4a6c51744 100644
--- a/app/models/post.rb
+++ b/app/models/post.rb
@@ -2,7 +2,7 @@
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
-class Post < ActiveRecord::Base
+class Post < ApplicationRecord
self.include_root_in_json = false
include ApplicationHelper
@@ -12,21 +12,20 @@ class Post < ActiveRecord::Base
include Diaspora::Likeable
include Diaspora::Commentable
include Diaspora::Shareable
+ include Diaspora::MentionsContainer
has_many :participations, dependent: :delete_all, as: :target, inverse_of: :target
- has_many :participants, class_name: "Person", through: :participations, source: :author
+ has_many :participants, through: :participations, source: :author
attr_accessor :user_like
has_many :reports, as: :item
- has_many :mentions, dependent: :destroy
-
has_many :reshares, class_name: "Reshare", foreign_key: :root_guid, primary_key: :guid
has_many :resharers, class_name: "Person", through: :reshares, source: :author
- belongs_to :o_embed_cache
- belongs_to :open_graph_cache
+ belongs_to :o_embed_cache, optional: true
+ belongs_to :open_graph_cache, optional: true
validates_uniqueness_of :id
@@ -55,12 +54,22 @@ class Post < ActiveRecord::Base
joins(:likes).where(:likes => {:author_id => person.id})
}
+ scope :subscribed_by, ->(user) {
+ joins(:participations).where(participations: {author_id: user.person_id})
+ }
+
+ scope :reshares, -> { where(type: "Reshare") }
+
+ scope :reshared_by, ->(person) {
+ # we join on the same table, Rails renames "posts" to "reshares_posts" for the right table
+ joins(:reshares).where(reshares_posts: {author_id: person.id})
+ }
+
def post_type
self.class.name
end
def root; end
- def mentioned_people; []; end
def photos; []; end
#prevents error when trying to access @post.address in a post different than Reshare and StatusMessage types;
diff --git a/app/models/profile.rb b/app/models/profile.rb
index 573dcb6f3..949cf8f78 100644
--- a/app/models/profile.rb
+++ b/app/models/profile.rb
@@ -2,7 +2,7 @@
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
-class Profile < ActiveRecord::Base
+class Profile < ApplicationRecord
self.include_root_in_json = false
include Diaspora::Federated::Base
@@ -40,6 +40,10 @@ class Profile < ActiveRecord::Base
Person.joins(:contacts).where(contacts: {user_id: person.owner_id})
end
+ def public?
+ public_details?
+ end
+
def diaspora_handle
#get the parent diaspora handle, unless we want to access a profile without a person
(self.person) ? self.person.diaspora_handle : self[:diaspora_handle]
@@ -102,10 +106,6 @@ class Profile < ActiveRecord::Base
end
end
- def formatted_birthday
- birthday.to_s(:long).gsub(/, 100[0|4]/, "") if birthday.present?
- end
-
def bio_message
@bio_message ||= Diaspora::MessageRenderer.new(bio)
end
@@ -126,6 +126,7 @@ class Profile < ActiveRecord::Base
end
def tombstone!
+ @tag_string = nil
self.taggings.delete_all
clearable_fields.each do |field|
self[field] = nil
diff --git a/app/models/report.rb b/app/models/report.rb
index a116e9083..2f28cfc4c 100644
--- a/app/models/report.rb
+++ b/app/models/report.rb
@@ -1,4 +1,4 @@
-class Report < ActiveRecord::Base
+class Report < ApplicationRecord
validates :user_id, presence: true
validates :item_id, presence: true
validates :item_type, presence: true, inclusion: {
@@ -9,8 +9,8 @@ class Report < ActiveRecord::Base
validate :post_or_comment_does_exist, :on => :create
belongs_to :user
- belongs_to :post
- belongs_to :comment
+ belongs_to :post, optional: true
+ belongs_to :comment, optional: true
belongs_to :item, polymorphic: true
after_commit :send_report_notification, :on => :create
diff --git a/app/models/reshare.rb b/app/models/reshare.rb
index a88208248..bc6d8bfa1 100644
--- a/app/models/reshare.rb
+++ b/app/models/reshare.rb
@@ -3,7 +3,7 @@
# the COPYRIGHT file.
class Reshare < Post
- belongs_to :root, :class_name => 'Post', :foreign_key => :root_guid, :primary_key => :guid
+ belongs_to :root, class_name: "Post", foreign_key: :root_guid, primary_key: :guid, optional: true
validate :root_must_be_public
validates_presence_of :root, :on => :create
validates_uniqueness_of :root_guid, :scope => :author_id
diff --git a/app/models/role.rb b/app/models/role.rb
index cbe5644ef..98601bb7b 100644
--- a/app/models/role.rb
+++ b/app/models/role.rb
@@ -1,9 +1,8 @@
# NOTE add the person object you want to attach role to...
-class Role < ActiveRecord::Base
+class Role < ApplicationRecord
belongs_to :person
- validates :person, presence: true
validates :name, uniqueness: {scope: :person_id}
validates :name, inclusion: {in: %w(admin moderator spotlight)}
diff --git a/app/models/service.rb b/app/models/service.rb
index 57322ce8c..890fc02bc 100644
--- a/app/models/service.rb
+++ b/app/models/service.rb
@@ -2,7 +2,7 @@
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
-class Service < ActiveRecord::Base
+class Service < ApplicationRecord
attr_accessor :provider, :info, :access_level
belongs_to :user
diff --git a/app/models/share_visibility.rb b/app/models/share_visibility.rb
index bffdf91cc..18c920a53 100644
--- a/app/models/share_visibility.rb
+++ b/app/models/share_visibility.rb
@@ -2,7 +2,7 @@
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
-class ShareVisibility < ActiveRecord::Base
+class ShareVisibility < ApplicationRecord
belongs_to :user
belongs_to :shareable, polymorphic: :true
@@ -22,7 +22,7 @@ class ShareVisibility < ActiveRecord::Base
# @param share [Shareable]
# @return [void]
def self.batch_import(user_ids, share)
- return false unless ShareVisibility.new(shareable_id: share.id, shareable_type: share.class.base_class.to_s).valid?
+ return false if share.public?
user_ids -= ShareVisibility.for_shareable(share).where(user_id: user_ids).pluck(:user_id)
return false if user_ids.empty?
diff --git a/app/models/signature_order.rb b/app/models/signature_order.rb
index 83cbfb51a..e65d0fae3 100644
--- a/app/models/signature_order.rb
+++ b/app/models/signature_order.rb
@@ -1,3 +1,3 @@
-class SignatureOrder < ActiveRecord::Base
+class SignatureOrder < ApplicationRecord
validates :order, presence: true, uniqueness: true
end
diff --git a/app/models/status_message.rb b/app/models/status_message.rb
index 6ee7d388e..a0c9d727b 100644
--- a/app/models/status_message.rb
+++ b/app/models/status_message.rb
@@ -19,17 +19,17 @@ class StatusMessage < Post
has_one :location
has_one :poll, autosave: true
+ has_many :poll_participations, through: :poll
attr_accessor :oembed_url
attr_accessor :open_graph_url
- after_create :create_mentions
after_commit :queue_gather_oembed_data, :on => :create, :if => :contains_oembed_url_in_text?
after_commit :queue_gather_open_graph_data, :on => :create, :if => :contains_open_graph_url_in_text?
#scopes
scope :where_person_is_mentioned, ->(person) {
- joins(:mentions).where(:mentions => {:person_id => person.id})
+ owned_or_visible_by_user(person.owner).joins(:mentions).where(mentions: {person_id: person.id})
}
def self.guids_for_author(person)
@@ -52,36 +52,6 @@ class StatusMessage < Post
text.try(:match, /#nsfw/i) || super
end
- def message
- @message ||= Diaspora::MessageRenderer.new(text, mentioned_people: mentioned_people)
- end
-
- def mentioned_people
- if self.persisted?
- self.mentions.includes(:person => :profile).map{ |mention| mention.person }
- else
- Diaspora::Mentionable.people_from_string(text)
- end
- end
-
- ## TODO ----
- # don't put presentation logic in the model!
- def mentioned_people_names
- self.mentioned_people.map(&:name).join(', ')
- end
- ## ---- ----
-
- def create_mentions
- ppl = Diaspora::Mentionable.people_from_string(text)
- ppl.each do |person|
- self.mentions.find_or_create_by(person_id: person.id)
- end
- end
-
- def mentions?(person)
- mentioned_people.include? person
- end
-
def comment_email_subject
message.title
end
@@ -126,6 +96,24 @@ class StatusMessage < Post
photos.each {|photo| photo.receive(recipient_user_ids) }
end
+ # Note: the next two methods can be safely removed once changes from #6818 are deployed on every pod
+ # see StatusMessageCreationService#dispatch
+ # Only includes those people, to whom we're going to send a federation entity
+ # (and doesn't define exhaustive list of people who can receive it)
+ def people_allowed_to_be_mentioned
+ @aspects_ppl ||=
+ if public?
+ :all
+ else
+ Contact.joins(:aspect_memberships).where(aspect_memberships: {aspect: aspects}).distinct.pluck(:person_id)
+ end
+ end
+
+ def filter_mentions
+ return if people_allowed_to_be_mentioned == :all
+ update(text: Diaspora::Mentionable.filter_people(text, people_allowed_to_be_mentioned))
+ end
+
private
def presence_of_content
diff --git a/app/models/tag_following.rb b/app/models/tag_following.rb
index 915221856..bd1cb62d2 100644
--- a/app/models/tag_following.rb
+++ b/app/models/tag_following.rb
@@ -1,4 +1,4 @@
-class TagFollowing < ActiveRecord::Base
+class TagFollowing < ApplicationRecord
belongs_to :user
belongs_to :tag, :class_name => "ActsAsTaggableOn::Tag"
diff --git a/app/models/user.rb b/app/models/user.rb
index 55fd554c5..d596dd9d4 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -2,7 +2,7 @@
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
-class User < ActiveRecord::Base
+class User < ApplicationRecord
include AuthenticationToken
include Connecting
include Querying
@@ -30,7 +30,7 @@ class User < ActiveRecord::Base
validates_length_of :username, :maximum => 32
validates_exclusion_of :username, :in => AppConfig.settings.username_blacklist
validates_inclusion_of :language, :in => AVAILABLE_LANGUAGE_CODES
- validates :color_theme, inclusion: {in: AVAILABLE_COLOR_THEME_CODES}, allow_blank: true
+ validates :color_theme, inclusion: {in: AVAILABLE_COLOR_THEMES}, allow_blank: true
validates_format_of :unconfirmed_email, :with => Devise.email_regexp, :allow_blank => true
validate :unconfirmed_email_quasiuniqueness
@@ -46,13 +46,15 @@ class User < ActiveRecord::Base
delegate :guid, :public_key, :posts, :photos, :owns?, :image_url,
:diaspora_handle, :name, :atom_url, :profile_url, :profile, :url,
- :first_name, :last_name, :gender, :participations, to: :person
+ :first_name, :last_name, :full_name, :gender, :participations, to: :person
delegate :id, :guid, to: :person, prefix: true
has_many :aspects, -> { order('order_id ASC') }
- belongs_to :auto_follow_back_aspect, :class_name => 'Aspect'
- belongs_to :invited_by, :class_name => 'User'
+ belongs_to :auto_follow_back_aspect, class_name: "Aspect", optional: true
+ belongs_to :invited_by, class_name: "User", optional: true
+
+ has_many :invited_users, class_name: "User", inverse_of: :invited_by, foreign_key: :invited_by_id
has_many :aspect_memberships, :through => :aspects
@@ -268,10 +270,6 @@ class User < ActiveRecord::Base
end
end
- def salmon(post)
- Salmon::EncryptedSlap.create_by_user_and_activity(self, post.to_diaspora_xml)
- end
-
# Check whether the user has liked a post.
# @param [Post] post
def liked?(target)
@@ -301,18 +299,22 @@ class User < ActiveRecord::Base
mount_uploader :export, ExportedUser
def queue_export
- update exporting: true
+ update exporting: true, export: nil, exported_at: nil
Workers::ExportUser.perform_async(id)
end
def perform_export!
- export = Tempfile.new([username, '.json.gz'], encoding: 'ascii-8bit')
+ export = Tempfile.new([username, ".json.gz"], encoding: "ascii-8bit")
export.write(compressed_export) && export.close
if export.present?
update exporting: false, export: export, exported_at: Time.zone.now
else
update exporting: false
end
+ rescue => error
+ logger.error "Unexpected error while exporting user '#{username}': #{error.class}: #{error.message}\n" \
+ "#{error.backtrace.first(15).join("\n")}"
+ update exporting: false
end
def compressed_export
@@ -323,16 +325,21 @@ class User < ActiveRecord::Base
mount_uploader :exported_photos_file, ExportedPhotos
def queue_export_photos
- update exporting_photos: true
+ update exporting_photos: true, exported_photos_file: nil, exported_photos_at: nil
Workers::ExportPhotos.perform_async(id)
end
def perform_export_photos!
PhotoExporter.new(self).perform
+ rescue => error
+ logger.error "Unexpected error while exporting photos for '#{username}': #{error.class}: #{error.message}\n" \
+ "#{error.backtrace.first(15).join("\n")}"
+ update exporting_photos: false
end
######### Mailer #######################
def mail(job, *args)
+ return unless job.present?
pref = job.to_s.gsub('Workers::Mail::', '').underscore
if(self.disable_mail == false && !self.user_preferences.exists?(:email_type => pref))
job.perform_async(*args)
@@ -346,7 +353,7 @@ class User < ActiveRecord::Base
######### Posts and Such ###############
def retract(target)
- retraction = Retraction.for(target, self)
+ retraction = Retraction.for(target)
retraction.defer_dispatch(self)
retraction.perform
end
@@ -476,14 +483,17 @@ class User < ActiveRecord::Base
def guard_unconfirmed_email
self.unconfirmed_email = nil if unconfirmed_email.blank? || unconfirmed_email == email
- if unconfirmed_email_changed?
- self.confirm_email_token = unconfirmed_email ? SecureRandom.hex(15) : nil
- end
+ return unless will_save_change_to_unconfirmed_email?
+
+ self.confirm_email_token = unconfirmed_email ? SecureRandom.hex(15) : nil
end
# Whenever email is set, clear all unconfirmed emails which match
def remove_invalid_unconfirmed_emails
- User.where(unconfirmed_email: email).update_all(unconfirmed_email: nil, confirm_email_token: nil) if email_changed?
+ return unless saved_change_to_email?
+ # rubocop:disable Rails/SkipsModelValidations
+ User.where(unconfirmed_email: email).update_all(unconfirmed_email: nil, confirm_email_token: nil)
+ # rubocop:enable Rails/SkipsModelValidations
end
# Generate public/private keys for User and associated Person
@@ -507,7 +517,7 @@ class User < ActiveRecord::Base
def close_account!
self.person.lock_access!
self.lock_access!
- AccountDeletion.create(:person => self.person)
+ AccountDeletion.create(person: person)
end
def closed_account?
diff --git a/app/models/user/connecting.rb b/app/models/user/connecting.rb
index 0781745f4..161fb429a 100644
--- a/app/models/user/connecting.rb
+++ b/app/models/user/connecting.rb
@@ -34,7 +34,7 @@ class User
if contact.person.local?
contact.person.owner.disconnected_by(contact.user.person)
else
- Retraction.for(contact).defer_dispatch(self)
+ ContactRetraction.for(contact).defer_dispatch(self)
end
contact.aspect_memberships.delete_all
diff --git a/app/models/user_preference.rb b/app/models/user_preference.rb
index 354a48400..11ba7038d 100644
--- a/app/models/user_preference.rb
+++ b/app/models/user_preference.rb
@@ -1,17 +1,18 @@
-class UserPreference < ActiveRecord::Base
+class UserPreference < ApplicationRecord
belongs_to :user
validate :must_be_valid_email_type
VALID_EMAIL_TYPES =
["someone_reported",
- "mentioned",
- "comment_on_post",
- "private_message",
- "started_sharing",
- "also_commented",
- "liked",
- "reshared"]
+ "mentioned",
+ "mentioned_in_comment",
+ "comment_on_post",
+ "private_message",
+ "started_sharing",
+ "also_commented",
+ "liked",
+ "reshared"]
def must_be_valid_email_type
unless VALID_EMAIL_TYPES.include?(self.email_type)
diff --git a/app/presenters/comment_presenter.rb b/app/presenters/comment_presenter.rb
index 95eef095c..f687ba7b8 100644
--- a/app/presenters/comment_presenter.rb
+++ b/app/presenters/comment_presenter.rb
@@ -5,11 +5,12 @@ class CommentPresenter < BasePresenter
def as_json(opts={})
{
- :id => @comment.id,
- :guid => @comment.guid,
- :text => @comment.message.plain_text_for_json,
- :author => @comment.author.as_api_response(:backbone),
- :created_at => @comment.created_at
+ id: @comment.id,
+ guid: @comment.guid,
+ text: @comment.message.plain_text_for_json,
+ author: @comment.author.as_api_response(:backbone),
+ created_at: @comment.created_at,
+ mentioned_people: @comment.mentioned_people.as_api_response(:backbone)
}
end
end
diff --git a/app/presenters/extreme_post_presenter.rb b/app/presenters/extreme_post_presenter.rb
deleted file mode 100644
index c35b54088..000000000
--- a/app/presenters/extreme_post_presenter.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-#this file should go away, hence the name that is so full of lulz
-#post interactions should probably be a decorator, and used in very few places... maybe?
-class ExtremePostPresenter
- def initialize(post, current_user)
- @post = post
- @current_user = current_user
- end
-
- def as_json(options={})
- post = PostPresenter.new(@post, @current_user)
- interactions = PostInteractionPresenter.new(@post, @current_user)
- post.as_json.merge!(:interactions => interactions.as_json)
- end
-end \ No newline at end of file
diff --git a/app/presenters/person_presenter.rb b/app/presenters/person_presenter.rb
index d9cf71c02..1c1cc88a0 100644
--- a/app/presenters/person_presenter.rb
+++ b/app/presenters/person_presenter.rb
@@ -40,6 +40,10 @@ class PersonPresenter < BasePresenter
}
end
+ def self.people_names(people)
+ people.map(&:name).join(", ")
+ end
+
protected
def own_profile?
diff --git a/app/presenters/post_presenter.rb b/app/presenters/post_presenter.rb
index 86064fbf9..a1187fba9 100644
--- a/app/presenters/post_presenter.rb
+++ b/app/presenters/post_presenter.rb
@@ -14,6 +14,20 @@ class PostPresenter < BasePresenter
.merge(non_directly_retrieved_attributes)
end
+ def with_interactions
+ interactions = PostInteractionPresenter.new(@post, current_user)
+ as_json.merge!(interactions: interactions.as_json)
+ end
+
+ def with_initial_interactions
+ as_json.tap do |post|
+ post[:interactions].merge!(
+ likes: LikeService.new(current_user).find_for_post(@post.id).limit(30).as_api_response(:backbone),
+ reshares: ReshareService.new(current_user).find_for_post(@post.id).limit(30).as_api_response(:backbone)
+ )
+ end
+ end
+
def metas_attributes
{
keywords: {name: "keywords", content: comma_separated_tags},
diff --git a/app/presenters/statistics_presenter.rb b/app/presenters/statistics_presenter.rb
deleted file mode 100644
index e6382850c..000000000
--- a/app/presenters/statistics_presenter.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-# Copyright (c) 2010-2011, Diaspora Inc. This file is
-# licensed under the Affero General Public License version 3 or later. See
-# the COPYRIGHT file.
-
-# TODO: Drop after 0.6
-class StatisticsPresenter < NodeInfoPresenter
- def initialize
- super("1.0")
- end
-
- def as_json(_options={})
- base_data.merge(user_counts)
- .merge(post_counts)
- .merge(comment_counts)
- end
-
- def base_data
- {
- "name" => name,
- "network" => "Diaspora",
- "version" => version,
- "registrations_open" => open_registrations?,
- "services" => available_services
- }
- end
-
- def user_counts
- return {} unless expose_user_counts?
- {
- "total_users" => total_users,
- "active_users_monthly" => monthly_users,
- "active_users_halfyear" => halfyear_users
- }
- end
-
- def post_counts
- return {} unless expose_posts_counts?
- {
- "local_posts" => local_posts
- }
- end
-
- def comment_counts
- return {} unless expose_comment_counts?
- {
- "local_comments" => local_comments
- }
- end
-end
diff --git a/app/serializers/export/comment_serializer.rb b/app/serializers/export/comment_serializer.rb
deleted file mode 100644
index 58b5bde1a..000000000
--- a/app/serializers/export/comment_serializer.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-module Export
- class CommentSerializer < ActiveModel::Serializer
- attributes :guid,
- :text,
- :post_guid
-
- def post_guid
- object.post.guid
- end
- end
-end
diff --git a/app/serializers/export/contact_serializer.rb b/app/serializers/export/contact_serializer.rb
index be025304f..871486777 100644
--- a/app/serializers/export/contact_serializer.rb
+++ b/app/serializers/export/contact_serializer.rb
@@ -2,11 +2,33 @@ module Export
class ContactSerializer < ActiveModel::Serializer
attributes :sharing,
:receiving,
+ :following,
+ :followed,
:person_guid,
:person_name,
- :person_first_name,
- :person_diaspora_handle
+ :account_id,
+ :public_key
- has_many :aspects, each_serializer: Export::AspectSerializer
+ has_many :contact_groups_membership
+
+ def following
+ object.sharing
+ end
+
+ def followed
+ object.receiving
+ end
+
+ def account_id
+ object.person_diaspora_handle
+ end
+
+ def contact_groups_membership
+ object.aspects.map(&:name)
+ end
+
+ def public_key
+ object.person.serialized_public_key
+ end
end
end
diff --git a/app/serializers/export/others_data_serializer.rb b/app/serializers/export/others_data_serializer.rb
new file mode 100644
index 000000000..96a819c38
--- /dev/null
+++ b/app/serializers/export/others_data_serializer.rb
@@ -0,0 +1,34 @@
+module Export
+ class OthersDataSerializer < ActiveModel::Serializer
+ # Relayables of other people in the archive: comments, likes, participations, poll participations where author is
+ # the archive owner
+ has_many :relayables, each_serializer: FederationEntitySerializer
+
+ # Parent posts of user's own relayables. We have to save metadata to use
+ # it in case when posts temporary unavailable on the target pod.
+ has_many :posts, each_serializer: FederationEntitySerializer
+
+ # Authors of posts where we participated and authors are not in contacts
+ has_many :non_contact_authors, each_serializer: PersonMetadataSerializer
+
+ private
+
+ def relayables
+ %i[comments likes poll_participations].map {|relayable|
+ others_relayables.send(relayable)
+ }.sum
+ end
+
+ def others_relayables
+ @others_relayables ||= Diaspora::Exporter::OthersRelayables.new(object.person_id)
+ end
+
+ def posts
+ @posts ||= Diaspora::Exporter::PostsWithActivity.new(object).query
+ end
+
+ def non_contact_authors
+ Diaspora::Exporter::NonContactAuthors.new(posts, object).query
+ end
+ end
+end
diff --git a/app/serializers/export/own_post_serializer.rb b/app/serializers/export/own_post_serializer.rb
new file mode 100644
index 000000000..150ecd427
--- /dev/null
+++ b/app/serializers/export/own_post_serializer.rb
@@ -0,0 +1,33 @@
+module Export
+ # This is a serializer for the user's own posts
+ class OwnPostSerializer < FederationEntitySerializer
+ # Only for public posts.
+ # Includes URIs of pods which must be notified on the post updates.
+ # Must always include local pod URI since we will want all the updates on the post if user migrates.
+ has_many :subscribed_pods_uris
+
+ # Only for private posts.
+ # Includes diaspora* IDs of people who must be notified on post updates.
+ has_many :subscribed_users_ids
+
+ # Normally accepts Post as an object.
+ def initialize(*)
+ super
+ self.except = [excluded_subscription_key]
+ end
+
+ private
+
+ def subscribed_pods_uris
+ object.subscribed_pods_uris.push(AppConfig.pod_uri.to_s)
+ end
+
+ def subscribed_users_ids
+ object.subscribers.map(&:diaspora_handle)
+ end
+
+ def excluded_subscription_key
+ entity.public ? :subscribed_users_ids : :subscribed_pods_uris
+ end
+ end
+end
diff --git a/app/serializers/export/own_relayables_serializer.rb b/app/serializers/export/own_relayables_serializer.rb
new file mode 100644
index 000000000..a38f83ccf
--- /dev/null
+++ b/app/serializers/export/own_relayables_serializer.rb
@@ -0,0 +1,13 @@
+module Export
+ # This is a serializer for the user's own relayables. We remove signature from the own relayables since it isn't
+ # useful and takes space.
+ class OwnRelayablesSerializer < FederationEntitySerializer
+ private
+
+ def modify_serializable_object(hash)
+ super.tap {|hash|
+ hash[:entity_data].delete(:author_signature)
+ }
+ end
+ end
+end
diff --git a/app/serializers/export/person_metadata_serializer.rb b/app/serializers/export/person_metadata_serializer.rb
new file mode 100644
index 000000000..911062e39
--- /dev/null
+++ b/app/serializers/export/person_metadata_serializer.rb
@@ -0,0 +1,17 @@
+module Export
+ class PersonMetadataSerializer < ActiveModel::Serializer
+ attributes :guid,
+ :account_id,
+ :public_key
+
+ private
+
+ def account_id
+ object.diaspora_handle
+ end
+
+ def public_key
+ object.serialized_public_key
+ end
+ end
+end
diff --git a/app/serializers/export/post_serializer.rb b/app/serializers/export/post_serializer.rb
deleted file mode 100644
index 84b6a91ed..000000000
--- a/app/serializers/export/post_serializer.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-module Export
- class PostSerializer < ActiveModel::Serializer
- attributes :guid,
- :text,
- :public,
- :diaspora_handle,
- :type,
- :likes_count,
- :comments_count,
- :reshares_count,
- :created_at
- end
-end
diff --git a/app/serializers/export/profile_serializer.rb b/app/serializers/export/profile_serializer.rb
deleted file mode 100644
index b8eb2001f..000000000
--- a/app/serializers/export/profile_serializer.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-module Export
- class ProfileSerializer < ActiveModel::Serializer
- attributes :first_name,
- :last_name,
- :gender,
- :bio,
- :birthday,
- :location,
- :image_url,
- :diaspora_handle,
- :searchable,
- :nsfw
- end
-end
diff --git a/app/serializers/export/user_serializer.rb b/app/serializers/export/user_serializer.rb
index 7e3b6b42d..09f26d3bd 100644
--- a/app/serializers/export/user_serializer.rb
+++ b/app/serializers/export/user_serializer.rb
@@ -1,24 +1,49 @@
module Export
class UserSerializer < ActiveModel::Serializer
- attributes :name,
+ attributes :username,
:email,
:language,
- :username,
- :serialized_private_key,
+ :private_key,
:disable_mail,
:show_community_spotlight_in_stream,
:auto_follow_back,
:auto_follow_back_aspect,
:strip_exif
- has_one :profile, serializer: Export::ProfileSerializer
- has_many :aspects, each_serializer: Export::AspectSerializer
+ has_one :profile, serializer: FederationEntitySerializer
+ has_many :contact_groups, each_serializer: Export::AspectSerializer
has_many :contacts, each_serializer: Export::ContactSerializer
- has_many :posts, each_serializer: Export::PostSerializer
- has_many :comments, each_serializer: Export::CommentSerializer
+ has_many :posts, each_serializer: Export::OwnPostSerializer
+ has_many :followed_tags
+ has_many :post_subscriptions
- def comments
- object.person.comments
+ has_many :relayables, each_serializer: Export::OwnRelayablesSerializer
+
+ private
+
+ def relayables
+ [*comments, *likes, *poll_participations]
+ end
+
+ %i[comments likes poll_participations].each {|collection|
+ delegate collection, to: :person
+ }
+
+ delegate :person, to: :object
+
+ def contact_groups
+ object.aspects
end
+ def private_key
+ object.serialized_private_key
+ end
+
+ def followed_tags
+ object.followed_tags.map(&:name)
+ end
+
+ def post_subscriptions
+ Post.subscribed_by(object).pluck(:guid)
+ end
end
end
diff --git a/app/serializers/federation_entity_serializer.rb b/app/serializers/federation_entity_serializer.rb
new file mode 100644
index 000000000..0458fc73b
--- /dev/null
+++ b/app/serializers/federation_entity_serializer.rb
@@ -0,0 +1,16 @@
+# This is an ActiveModel::Serializer based class which uses DiasporaFederation::Entity JSON serialization
+# features in order to serialize local DB objects. To determine a type of entity class to use the same routines
+# are used as for federation messages generation.
+class FederationEntitySerializer < ActiveModel::Serializer
+ include SerializerPostProcessing
+
+ private
+
+ def modify_serializable_object(hash)
+ hash.merge(entity.to_json)
+ end
+
+ def entity
+ @entity ||= Diaspora::Federation::Entities.build(object)
+ end
+end
diff --git a/app/serializers/serializer_post_processing.rb b/app/serializers/serializer_post_processing.rb
new file mode 100644
index 000000000..ea865be8a
--- /dev/null
+++ b/app/serializers/serializer_post_processing.rb
@@ -0,0 +1,20 @@
+# This module encapsulates knowledge about the way AMS works with the serializable object.
+# The main responsibility of this module is to allow changing resulting object just before the
+# JSON serialization happens.
+module SerializerPostProcessing
+ # serializable_object output is used in AMS to produce a hash from input object that is passed to JSON serializer.
+ # serializable_object of ActiveModel::Serializer is not documented as officialy available API
+ # NOTE: if we ever move to AMS 0.10, this method was renamed there to serializable_hash
+ def serializable_object(options={})
+ modify_serializable_object(super)
+ end
+
+ # Users of this module may override this method in order to change serializable_object after
+ # the serializable hash generation and before its serialization.
+ def modify_serializable_object(hash)
+ hash
+ end
+
+ # except is an array of keys that are excluded from serialized_object before JSON serialization
+ attr_accessor :except
+end
diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb
index d356a0211..b481f1b4c 100644
--- a/app/services/notification_service.rb
+++ b/app/services/notification_service.rb
@@ -1,8 +1,8 @@
class NotificationService
NOTIFICATION_TYPES = {
- Comment => [Notifications::CommentOnPost, Notifications::AlsoCommented],
+ Comment => [Notifications::MentionedInComment, Notifications::CommentOnPost, Notifications::AlsoCommented],
Like => [Notifications::Liked],
- StatusMessage => [Notifications::Mentioned],
+ StatusMessage => [Notifications::MentionedInPost],
Conversation => [Notifications::PrivateMessage],
Message => [Notifications::PrivateMessage],
Reshare => [Notifications::Reshared],
diff --git a/app/services/post_service.rb b/app/services/post_service.rb
index 140c33a0d..6d35a385d 100644
--- a/app/services/post_service.rb
+++ b/app/services/post_service.rb
@@ -31,6 +31,17 @@ class PostService
user.retract(post)
end
+ def mentionable_in_comment(post_id, query)
+ post = find!(post_id)
+ Person
+ .allowed_to_be_mentioned_in_a_comment_to(post)
+ .where.not(id: user.person_id)
+ .find_by_substring(query)
+ .sort_for_mention_suggestion(post, user)
+ .for_json
+ .limit(15)
+ end
+
private
attr_reader :user
@@ -59,8 +70,20 @@ class PostService
end
def mark_mention_notifications_read(post_id)
- mention_id = Mention.where(post_id: post_id, person_id: user.person_id).pluck(:id)
- Notification.where(recipient_id: user.id, target_type: "Mention", target_id: mention_id, unread: true)
- .update_all(unread: false) if mention_id
+ mention_ids = Mention.where(
+ mentions_container_id: post_id,
+ mentions_container_type: "Post",
+ person_id: user.person_id
+ ).ids
+ mention_ids.concat(mentions_in_comments_for_post(post_id).pluck(:id))
+
+ Notification.where(recipient_id: user.id, target_type: "Mention", target_id: mention_ids, unread: true)
+ .update_all(unread: false) if mention_ids.any?
+ end
+
+ def mentions_in_comments_for_post(post_id)
+ Mention
+ .joins("INNER JOIN comments ON mentions_container_id = comments.id AND mentions_container_type = 'Comment'")
+ .where(comments: {commentable_id: post_id, commentable_type: "Post"})
end
end
diff --git a/app/services/status_message_creation_service.rb b/app/services/status_message_creation_service.rb
index b541d194d..a262d2e54 100644
--- a/app/services/status_message_creation_service.rb
+++ b/app/services/status_message_creation_service.rb
@@ -19,20 +19,9 @@ class StatusMessageCreationService
def build_status_message(params)
public = params[:public] || false
- filter_mentions params
user.build_post(:status_message, params[:status_message].merge(public: public))
end
- def filter_mentions(params)
- unless params[:public]
- params[:status_message][:text] = Diaspora::Mentionable.filter_for_aspects(
- params[:status_message][:text],
- user,
- *params[:aspect_ids]
- )
- end
- end
-
def add_attachments(status_message, params)
add_location(status_message, params[:location_address], params[:location_coords])
add_poll(status_message, params)
@@ -47,7 +36,8 @@ class StatusMessageCreationService
if params[:poll_question].present?
status_message.build_poll(question: params[:poll_question])
[*params[:poll_answers]].each do |poll_answer|
- status_message.poll.poll_answers.build(answer: poll_answer)
+ answer = status_message.poll.poll_answers.build(answer: poll_answer)
+ answer.poll = status_message.poll
end
end
end
@@ -75,6 +65,7 @@ class StatusMessageCreationService
def dispatch(status_message, services)
receiving_services = services ? Service.titles(services) : []
+ status_message.filter_mentions # this is only required until changes from #6818 are deployed on every pod
user.dispatch_post(status_message,
url: short_post_url(status_message.guid, host: AppConfig.environment.url),
service_types: receiving_services)
diff --git a/app/uploaders/exported_user.rb b/app/uploaders/exported_user.rb
index a7c4d5a2b..f2d309c2b 100644
--- a/app/uploaders/exported_user.rb
+++ b/app/uploaders/exported_user.rb
@@ -3,17 +3,15 @@
# the COPYRIGHT file.
class ExportedUser < SecureUploader
-
def store_dir
"uploads/users"
end
- def extension_white_list
- %w(gz)
+ def extension_whitelist
+ %w[gz]
end
def filename
"#{model.username}_diaspora_data_#{secure_token}.json.gz"
end
-
end
diff --git a/app/uploaders/processed_image.rb b/app/uploaders/processed_image.rb
index 68b540cf9..226d4fd47 100644
--- a/app/uploaders/processed_image.rb
+++ b/app/uploaders/processed_image.rb
@@ -9,8 +9,8 @@ class ProcessedImage < CarrierWave::Uploader::Base
"uploads/images"
end
- def extension_white_list
- %w(jpg jpeg png gif tiff)
+ def extension_whitelist
+ %w[jpg jpeg png gif tiff]
end
def filename
diff --git a/app/uploaders/unprocessed_image.rb b/app/uploaders/unprocessed_image.rb
index 86d425eb2..10186dd9b 100644
--- a/app/uploaders/unprocessed_image.rb
+++ b/app/uploaders/unprocessed_image.rb
@@ -6,7 +6,7 @@ class UnprocessedImage < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
attr_accessor :strip_exif
-
+
def strip_exif
@strip_exif || false
end
@@ -15,8 +15,8 @@ class UnprocessedImage < CarrierWave::Uploader::Base
"uploads/images"
end
- def extension_white_list
- %w(jpg jpeg png gif)
+ def extension_whitelist
+ %w[jpg jpeg png gif]
end
def filename
@@ -38,7 +38,7 @@ class UnprocessedImage < CarrierWave::Uploader::Base
version :thumb_medium
version :thumb_large
version :scaled_full do
- process :get_version_dimensions
+ process :get_version_dimensions
end
def get_version_dimensions
diff --git a/app/views/application/_head.haml b/app/views/application/_head.haml
index 497277976..c8587e9d5 100644
--- a/app/views/application/_head.haml
+++ b/app/views/application/_head.haml
@@ -4,6 +4,8 @@
%meta{charset: "utf-8"}/
= content_for?(:meta_data) ? yield(:meta_data) : metas_tags
+%meta{content: "yes", name: "mobile-web-app-capable"}/
+
/ favicon
/ For Apple devices
%link{rel: "apple-touch-icon", href: image_path("apple-touch-icon.png")}
@@ -22,9 +24,7 @@
= include_gon(camel_case: true, nonce: content_security_policy_nonce(:script))
= yield(:javascript)
-= chartbeat_head_block
= csrf_meta_tag
= current_user_atom_tag
-= include_mixpanel
= yield(:head)
diff --git a/app/views/comments/_comment.mobile.haml b/app/views/comments/_comment.mobile.haml
index 79cf8bc9c..8664c7413 100644
--- a/app/views/comments/_comment.mobile.haml
+++ b/app/views/comments/_comment.mobile.haml
@@ -2,7 +2,7 @@
-# licensed under the Affero General Public License version 3 or later. See
-# the COPYRIGHT file.
-%li.comment{data:{guid:comment.id}, class: ("hidden" if(defined? hidden))}
+%li.comment{id: comment.guid, class: ("hidden" if defined? hidden)}
.content
.media
.media-left
diff --git a/app/views/comments/_new_comment.mobile.haml b/app/views/comments/_new_comment.mobile.haml
index 5cae52950..d58bce9b2 100644
--- a/app/views/comments/_new_comment.mobile.haml
+++ b/app/views/comments/_new_comment.mobile.haml
@@ -5,7 +5,7 @@
.add_comment_bottom_link_container
- if user_signed_in?
= form_tag(post_comments_path(post_id), id: "new-comment-on-#{post_id}",
- class: "new_comment", autocomplete: "off") do
+ class: "new-comment", autocomplete: "off") do
%fieldset
= hidden_field_tag :post_id, post_id, id: "post-id-on-#{post_id}"
.form-group.clearfix
diff --git a/app/views/comments/_post_stats.mobile.haml b/app/views/comments/_post_stats.mobile.haml
index 106ef8ae8..980bf46ef 100644
--- a/app/views/comments/_post_stats.mobile.haml
+++ b/app/views/comments/_post_stats.mobile.haml
@@ -1,13 +1,10 @@
.post-stats
- if post.public?
- .icon-count-group
- .post-action= mobile_reshare_icon(post)
- %span.reshare-count.count= post.reshares.size
+ .post-action
+ = mobile_reshare_icon(post)
- .icon-count-group
- .post-action= mobile_comment_icon(post)
- %span.comment-count.count= post.comments.size
+ .post-action
+ = mobile_comment_icon(post)
- .icon-count-group
- .post-action= mobile_like_icon(post)
- %span.like-count.count= post.likes.size
+ .post-action
+ = mobile_like_icon(post)
diff --git a/app/views/layouts/_header.html.haml b/app/views/layouts/_header.html.haml
index b5a82390c..68acaad41 100644
--- a/app/views/layouts/_header.html.haml
+++ b/app/views/layouts/_header.html.haml
@@ -9,14 +9,11 @@
.container-fluid
.row
.col-md-12
- .navbar-header
- %button.navbar-toggle.collapsed{type: "button", data: {toggle: "collapse", target: "#navbar-collapse"}}
- %span.sr-only
- = t("layouts.header.toggle_navigation")
- %span.icon-bar
- %span.icon-bar
- %span.icon-bar
- = link_to AppConfig.settings.pod_name, root_path, class: "navbar-brand"
-
- .collapse.navbar-collapse#navbar-collapse
+ .not-connected-menu
+ .navbar-header.navbar-left
+ .hidden-xs
+ = link_to AppConfig.settings.pod_name, root_path, class: "navbar-brand"
+ .visible-xs-block.header-title
+ = link_to(image_tag("branding/logos/asterisk_white_mobile.png", class: "img-responsive"),
+ root_path, class: "navbar-brand")
= render "layouts/header_not_connected"
diff --git a/app/views/layouts/_header.mobile.haml b/app/views/layouts/_header.mobile.haml
index 30c779098..73ecc6e7a 100644
--- a/app/views/layouts/_header.mobile.haml
+++ b/app/views/layouts/_header.mobile.haml
@@ -2,7 +2,7 @@
.container-fluid
.navbar
= link_to(image_tag("branding/logos/asterisk_white_mobile.png", class: "img-responsive"),
- stream_path, id: "header-title", class: "navbar-brand")
+ stream_path, class: "navbar-brand header-title")
- if user_signed_in?
%ul.nav.navbar-nav#nav-badges
diff --git a/app/views/layouts/_header_not_connected.haml b/app/views/layouts/_header_not_connected.haml
index a3d1bcae3..c8760e3cb 100644
--- a/app/views/layouts/_header_not_connected.haml
+++ b/app/views/layouts/_header_not_connected.haml
@@ -1,4 +1,5 @@
%ul.nav.navbar-nav.navbar-right
- if AppConfig.settings.enable_registrations? && !current_page?(controller: "/registrations", action: :new)
%li= link_to t("devise.shared.links.sign_up"), new_user_registration_path, class: "login"
- %li= link_to t("devise.shared.links.sign_in"), new_user_session_path, class: "login"
+ - unless current_page?(controller: "/sessions", action: :new)
+ %li= link_to t("devise.shared.links.sign_in"), new_user_session_path, class: "login"
diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml
index 8b4099a8f..a8e8a6e85 100644
--- a/app/views/layouts/application.html.haml
+++ b/app/views/layouts/application.html.haml
@@ -17,8 +17,8 @@
= javascript_include_tag :main, :templates
= load_javascript_locales
- = render "head"
= include_color_theme
+ = render "head"
= translation_missing_warnings
%body{class: "page-#{controller_name} action-#{action_name}"}
@@ -32,9 +32,6 @@
= yield :after_content
- = include_chartbeat
- = include_mixpanel_guid
-
.blueimp-gallery.blueimp-gallery-controls#blueimp-gallery
.slides
%a.prev
diff --git a/app/views/layouts/application.mobile.haml b/app/views/layouts/application.mobile.haml
index 55e4e7189..40ca264a4 100644
--- a/app/views/layouts/application.mobile.haml
+++ b/app/views/layouts/application.mobile.haml
@@ -36,6 +36,3 @@
%h3
= t("streams.activity.title")
= yield
-
- = include_chartbeat
- = include_mixpanel_guid
diff --git a/app/views/notifications/_notification.haml b/app/views/notifications/_notification.haml
index 8c537bdc0..23ff76fd3 100644
--- a/app/views/notifications/_notification.haml
+++ b/app/views/notifications/_notification.haml
@@ -1,5 +1,5 @@
-.media.stream-element{data: {guid: note.id, type: (Notification.types.key(note.type) || "")},
- class: (note.unread ? "unread" : "read")}
+.media.stream-element{data: {guid: note.id, type: (types.key(note.type) || "")},
+ class: (note.unread ? "unread" : "read")}
.unread-toggle.pull-right
%i.entypo-eye{title: (note.unread ? t("notifications.index.mark_read") : t("notifications.index.mark_unread"))}
- if note.type == "Notifications::StartedSharing" && (!defined?(no_aspect_dropdown) || !no_aspect_dropdown)
diff --git a/app/views/notifications/_notification.mobile.haml b/app/views/notifications/_notification.mobile.haml
index 2b8825505..b38977152 100644
--- a/app/views/notifications/_notification.mobile.haml
+++ b/app/views/notifications/_notification.mobile.haml
@@ -1,4 +1,5 @@
-.notification_element{:data=>{:guid => note.id, :type => (Notification.types.key(note.type) || '')}, :class => (note.unread ? "unread" : "read")}
+.notification_element{data: {guid: note.id, type: (types.key(note.type) || "")},
+ class: (note.unread ? "unread" : "read")}
.pull-right.unread-toggle
%i.entypo-eye{title: (note.unread ? t("notifications.index.mark_read") : t("notifications.index.mark_unread"))}
= person_image_tag note.actors.first, :thumb_small
diff --git a/app/views/notifications/index.html.haml b/app/views/notifications/index.html.haml
index 22e647c05..61a70fe14 100644
--- a/app/views/notifications/index.html.haml
+++ b/app/views/notifications/index.html.haml
@@ -23,7 +23,7 @@
%i.entypo-comment
- when "liked"
%i.entypo-heart
- - when "mentioned"
+ - when "mentioned", "mentioned_in_comment"
%span.mentionIcon
@
- when "reshared"
diff --git a/app/views/notifier/invite.markerb b/app/views/notifier/invite.markerb
index 1e00c6c0a..8c20a00c0 100644
--- a/app/views/notifier/invite.markerb
+++ b/app/views/notifier/invite.markerb
@@ -1 +1,6 @@
-<%= t('.message', :invite_url => invite_code_url(@invitation_code), :diasporafoundation_url => 'https://diasporafoundation.org/', :diaspora_id => @inviter.try(:diaspora_handle)) %>
+<%= t('.message',
+ invite_url: invite_code_url(@invitation_code),
+ diasporafoundation_url: 'https://diasporafoundation.org/',
+ user: @inviter.try(:full_name).empty? ? @inviter.try(:diaspora_handle) : "#{@inviter.name} (#{@inviter.diaspora_handle})",
+ diaspora_id: @inviter.try(:diaspora_handle))
+%>
diff --git a/app/views/notifier/mentioned.markerb b/app/views/notifier/mentioned.markerb
index a2469a0e5..414739665 100644
--- a/app/views/notifier/mentioned.markerb
+++ b/app/views/notifier/mentioned.markerb
@@ -4,6 +4,6 @@
<%= t('notifier.mentioned.limited_post') %>
<% end %>
-[<%= t('notifier.comment_on_post.reply', :name => @notification.post_author_name) %>][1]
+[<%= t("notifier.comment_on_post.reply", name: @notification.post_author_name) %>][1]
[1]: <%= post_url(@notification.post) %>
diff --git a/app/views/notifier/mentioned_in_comment.markerb b/app/views/notifier/mentioned_in_comment.markerb
new file mode 100644
index 000000000..3b86f409b
--- /dev/null
+++ b/app/views/notifier/mentioned_in_comment.markerb
@@ -0,0 +1,9 @@
+<% if @notification.comment.public? %>
+<%= @notification.comment.message.plain_text_without_markdown %>
+<% else %>
+<%= t("notifier.mentioned_in_comment.limited_post") %>
+<% end %>
+
+[<%= t("notifier.mentioned_in_comment.reply") %>][1]
+
+[1]: <%= post_url(@notification.comment.parent, anchor: @notification.comment.guid) %>
diff --git a/app/views/publisher/_publisher.html.haml b/app/views/publisher/_publisher.html.haml
index 1d545dd17..be5826469 100644
--- a/app/views/publisher/_publisher.html.haml
+++ b/app/views/publisher/_publisher.html.haml
@@ -4,21 +4,18 @@
= status.error_messages
%params
.publisher-textarea-wrapper#publisher_textarea_wrapper
- .mentions-input-box
- .mentions-box
- .mentions
- - if current_user.getting_started?
- = status.text_area :fake_text, :rows => 2, :value => h(publisher_formatted_text),
- :tabindex => 1, :placeholder => "#{t('contacts.index.start_a_conversation')}...",
- "data-title" => popover_with_close_html("1. " + t("shared.public_explain.share")),
- "data-content" => t("shared.public_explain.new_user_welcome_message"),
- "class" => "form-control"
- - else
- = status.text_area :fake_text, :rows => 2, :value => h(publisher_formatted_text),
- :tabindex => 1, :placeholder => "#{t('contacts.index.start_a_conversation')}...",
- "class" => "form-control"
+ - if current_user.getting_started?
+ = status.text_area :text, :rows => 2, :value => h(publisher_formatted_text),
+ :tabindex => 1, :placeholder => "#{t('contacts.index.start_a_conversation')}...",
+ "data-title" => popover_with_close_html("1. " + t("shared.public_explain.share")),
+ "data-content" => t("shared.public_explain.new_user_welcome_message"),
+ "class" => "form-control mention-textarea"
+ - else
+ = status.text_area :text, :rows => 2, :value => h(publisher_formatted_text),
+ :tabindex => 1, :placeholder => "#{t('contacts.index.start_a_conversation')}...",
+ "class" => "form-control mention-textarea"
+ .typeahead-mention-box-wrap
%input.typeahead-mention-box.hidden{type: "text"}
- = status.hidden_field :text, value: h(publisher_hidden_text), class: "clear_on_submit"
.container-fluid.photodropzone-container#photodropzone_container
%ul#photodropzone
diff --git a/app/views/users/_edit.haml b/app/views/users/_edit.haml
index 9a171a923..060778b95 100644
--- a/app/views/users/_edit.haml
+++ b/app/views/users/_edit.haml
@@ -142,6 +142,11 @@
= t(".mentioned")
.small-horizontal-spacer
+ = type.label :mentioned_in_comment, class: "checkbox-inline" do
+ = type.check_box :mentioned_in_comment, {checked: @email_prefs["mentioned_in_comment"]}, false, true
+ = t(".mentioned_in_comment")
+ .small-horizontal-spacer
+
= type.label :liked, class: "checkbox-inline" do
= type.check_box :liked, {checked: @email_prefs["liked"]}, false, true
= t(".liked")
diff --git a/app/views/users/privacy_settings.mobile.haml b/app/views/users/privacy_settings.mobile.haml
index e37698db9..d4cca2637 100644
--- a/app/views/users/privacy_settings.mobile.haml
+++ b/app/views/users/privacy_settings.mobile.haml
@@ -2,6 +2,10 @@
-# licensed under the Affero General Public License version 3 or later. See
-# the COPYRIGHT file.
+- flash.each do |name, msg|
+ .alert{class: "alert-#{flash_class name}", role: "alert"}
+ = msg
+
- content_for :page_title do
= t(".title")
diff --git a/app/workers/deferred_dispatch.rb b/app/workers/deferred_dispatch.rb
index 49d0aa365..3c60ade93 100644
--- a/app/workers/deferred_dispatch.rb
+++ b/app/workers/deferred_dispatch.rb
@@ -9,7 +9,7 @@ module Workers
def perform(user_id, object_class_name, object_id, opts)
user = User.find(user_id)
object = object_class_name.constantize.find(object_id)
- opts = HashWithIndifferentAccess.new(opts)
+ opts = ActiveSupport::HashWithIndifferentAccess.new(opts)
Diaspora::Federation::Dispatcher.build(user, object, opts).dispatch
rescue ActiveRecord::RecordNotFound # The target got deleted before the job was run
diff --git a/app/workers/deferred_retraction.rb b/app/workers/deferred_retraction.rb
index 5f3b8834a..85ee2c1ab 100644
--- a/app/workers/deferred_retraction.rb
+++ b/app/workers/deferred_retraction.rb
@@ -6,11 +6,11 @@ module Workers
class DeferredRetraction < Base
sidekiq_options queue: :high
- def perform(user_id, retraction_data, recipient_ids, opts)
+ def perform(user_id, retraction_class, retraction_data, recipient_ids, opts)
user = User.find(user_id)
subscribers = Person.where(id: recipient_ids)
- object = Retraction.new(retraction_data.deep_symbolize_keys, subscribers)
- opts = HashWithIndifferentAccess.new(opts)
+ object = retraction_class.constantize.new(retraction_data.deep_symbolize_keys, subscribers)
+ opts = ActiveSupport::HashWithIndifferentAccess.new(opts)
Diaspora::Federation::Dispatcher.build(user, object, opts).dispatch
end
diff --git a/app/workers/delete_post_from_service.rb b/app/workers/delete_post_from_service.rb
index 7d0bfe1fd..33b841f6a 100644
--- a/app/workers/delete_post_from_service.rb
+++ b/app/workers/delete_post_from_service.rb
@@ -8,7 +8,7 @@ module Workers
def perform(service_id, opts)
service = Service.find_by_id(service_id)
- opts = HashWithIndifferentAccess.new(opts)
+ opts = ActiveSupport::HashWithIndifferentAccess.new(opts)
service.delete_from_service(opts)
end
end
diff --git a/app/workers/mail/also_commented.rb b/app/workers/mail/also_commented.rb
index 52026e737..05a1ef105 100644
--- a/app/workers/mail/also_commented.rb
+++ b/app/workers/mail/also_commented.rb
@@ -1,13 +1,6 @@
module Workers
module Mail
- class AlsoCommented < Base
- sidekiq_options queue: :low
-
- def perform(recipient_id, sender_id, comment_id)
- if email = Notifier.also_commented(recipient_id, sender_id, comment_id)
- email.deliver_now
- end
- end
+ class AlsoCommented < NotifierBase
end
end
end
diff --git a/app/workers/mail/comment_on_post.rb b/app/workers/mail/comment_on_post.rb
index 070eb8e33..168b75237 100644
--- a/app/workers/mail/comment_on_post.rb
+++ b/app/workers/mail/comment_on_post.rb
@@ -1,11 +1,6 @@
module Workers
module Mail
- class CommentOnPost < Base
- sidekiq_options queue: :low
-
- def perform(recipient_id, sender_id, comment_id)
- Notifier.comment_on_post(recipient_id, sender_id, comment_id).deliver_now
- end
+ class CommentOnPost < NotifierBase
end
end
end
diff --git a/app/workers/mail/confirm_email.rb b/app/workers/mail/confirm_email.rb
index 252f030c6..efa9fb64e 100644
--- a/app/workers/mail/confirm_email.rb
+++ b/app/workers/mail/confirm_email.rb
@@ -1,11 +1,6 @@
module Workers
module Mail
- class ConfirmEmail < Base
- sidekiq_options queue: :low
-
- def perform(user_id)
- Notifier.confirm_email(user_id).deliver_now
- end
+ class ConfirmEmail < NotifierBase
end
end
end
diff --git a/app/workers/mail/csrf_token_fail.rb b/app/workers/mail/csrf_token_fail.rb
index a3372b322..f9679b8c3 100644
--- a/app/workers/mail/csrf_token_fail.rb
+++ b/app/workers/mail/csrf_token_fail.rb
@@ -1,11 +1,6 @@
module Workers
module Mail
- class CsrfTokenFail < Base
- sidekiq_options queue: :low
-
- def perform(user_id)
- Notifier.csrf_token_fail(user_id).deliver_now
- end
+ class CsrfTokenFail < NotifierBase
end
end
end
diff --git a/app/workers/mail/liked.rb b/app/workers/mail/liked.rb
index 595af3e39..16471a542 100644
--- a/app/workers/mail/liked.rb
+++ b/app/workers/mail/liked.rb
@@ -1,10 +1,8 @@
module Workers
module Mail
- class Liked < Base
- sidekiq_options queue: :low
-
- def perform(recipient_id, sender_id, like_id)
- Notifier.liked(recipient_id, sender_id, like_id).deliver_now
+ class Liked < NotifierBase
+ def perform(*args)
+ super
rescue ActiveRecord::RecordNotFound => e
logger.warn("failed to send liked notification mail: #{e.message}")
raise e unless e.message.start_with?("Couldn't find Like with")
diff --git a/app/workers/mail/mentioned.rb b/app/workers/mail/mentioned.rb
index a32f30f11..4ae477d54 100644
--- a/app/workers/mail/mentioned.rb
+++ b/app/workers/mail/mentioned.rb
@@ -5,12 +5,7 @@
module Workers
module Mail
- class Mentioned < Base
- sidekiq_options queue: :low
-
- def perform(recipient_id, actor_id, target_id)
- Notifier.mentioned( recipient_id, actor_id, target_id).deliver_now
- end
+ class Mentioned < NotifierBase
end
end
end
diff --git a/app/workers/mail/mentioned_in_comment.rb b/app/workers/mail/mentioned_in_comment.rb
new file mode 100644
index 000000000..5e8d7f91f
--- /dev/null
+++ b/app/workers/mail/mentioned_in_comment.rb
@@ -0,0 +1,6 @@
+module Workers
+ module Mail
+ class MentionedInComment < NotifierBase
+ end
+ end
+end
diff --git a/app/workers/mail/notifier_base.rb b/app/workers/mail/notifier_base.rb
new file mode 100644
index 000000000..72cb4acb8
--- /dev/null
+++ b/app/workers/mail/notifier_base.rb
@@ -0,0 +1,11 @@
+module Workers
+ module Mail
+ class NotifierBase < Base
+ sidekiq_options queue: :low
+
+ def perform(*args)
+ Notifier.send_notification(self.class.name.gsub("Workers::Mail::", "").underscore, *args).deliver_now
+ end
+ end
+ end
+end
diff --git a/app/workers/mail/private_message.rb b/app/workers/mail/private_message.rb
index d24ce0296..b851bfed0 100644
--- a/app/workers/mail/private_message.rb
+++ b/app/workers/mail/private_message.rb
@@ -5,12 +5,7 @@
module Workers
module Mail
- class PrivateMessage < Base
- sidekiq_options queue: :low
-
- def perform(recipient_id, actor_id, target_id)
- Notifier.private_message( recipient_id, actor_id, target_id).deliver_now
- end
+ class PrivateMessage < NotifierBase
end
end
end
diff --git a/app/workers/mail/reshared.rb b/app/workers/mail/reshared.rb
index 1144147ad..7e434788d 100644
--- a/app/workers/mail/reshared.rb
+++ b/app/workers/mail/reshared.rb
@@ -1,11 +1,6 @@
module Workers
module Mail
- class Reshared < Base
- sidekiq_options queue: :low
-
- def perform(recipient_id, sender_id, reshare_id)
- Notifier.reshared(recipient_id, sender_id, reshare_id).deliver_now
- end
+ class Reshared < NotifierBase
end
end
end
diff --git a/app/workers/mail/started_sharing.rb b/app/workers/mail/started_sharing.rb
index 3618d1527..ef101060c 100644
--- a/app/workers/mail/started_sharing.rb
+++ b/app/workers/mail/started_sharing.rb
@@ -5,12 +5,7 @@
module Workers
module Mail
- class StartedSharing < Base
- sidekiq_options queue: :low
-
- def perform(recipient_id, sender_id, target_id)
- Notifier.started_sharing(recipient_id, sender_id).deliver_now
- end
+ class StartedSharing < NotifierBase
end
end
end
diff --git a/app/workers/receive_base.rb b/app/workers/receive_base.rb
index aab2082e4..c49dd7c8c 100644
--- a/app/workers/receive_base.rb
+++ b/app/workers/receive_base.rb
@@ -8,7 +8,7 @@ module Workers
def filter_errors_for_retry
yield
rescue DiasporaFederation::Entity::ValidationError,
- DiasporaFederation::Entity::InvalidRootNode,
+ DiasporaFederation::Parsers::BaseParser::InvalidRootNode,
DiasporaFederation::Entity::InvalidEntityName,
DiasporaFederation::Entity::UnknownEntity,
DiasporaFederation::Entities::Relayable::SignatureVerificationFailed,
diff --git a/bin/rails b/bin/rails
index 0af1c3baf..5badb2fde 100755
--- a/bin/rails
+++ b/bin/rails
@@ -4,8 +4,6 @@ begin
rescue LoadError => e
raise unless e.message.include?('spring')
end
-# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
-
-APP_PATH = File.expand_path('../../config/application', __FILE__)
-require File.expand_path('../../config/boot', __FILE__)
+APP_PATH = File.expand_path('../config/application', __dir__)
+require_relative '../config/boot'
require 'rails/commands'
diff --git a/config/application.rb b/config/application.rb
index 98bf0609f..3a115d764 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -1,7 +1,10 @@
require_relative 'boot'
require 'rails/all'
-Bundler.require(:default, *Bundler.settings.with, Rails.env)
+
+# Require the gems listed in Gemfile, including any gems
+# you've limited to :test, :development, or :production.
+Bundler.require(*Rails.groups(*Bundler.settings.with))
# Do not dump the limit of boolean fields on MySQL,
# since that generates a db/schema.rb that's incompatible
@@ -24,13 +27,16 @@ require_relative 'asset_sync'
module Diaspora
class Application < Rails::Application
+ # Initialize configuration defaults for originally generated Rails version.
+ config.load_defaults 5.1
+
# Settings in config/environments/* take precedence over those specified here.
# Application configuration should go into files in config/initializers
# -- all .rb files in that directory are automatically loaded.
# Custom directories with classes and modules you want to be autoloadable.
- config.autoload_paths += %W{#{config.root}/app}
- config.autoload_once_paths += %W{#{config.root}/lib}
+ config.autoload_paths += %W[#{config.root}/app]
+ config.autoload_once_paths += %W[#{config.root}/lib]
# Only load the plugins named here, in the order given (default is alphabetical).
# :all can be used as a placeholder for all plugins not explicitly named.
@@ -64,14 +70,16 @@ module Diaspora
# Speed up precompile by not loading the environment
config.assets.initialize_on_precompile = false
- # Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
- config.assets.precompile += %w(
+ # Precompile additional assets.
+ # (application.js, application.css, and all non-JS/CSS in the app/assets are already added)
+ config.assets.precompile += %w[
contact-list.js
ie.js
- jquery2.js
+ jquery3.js
jquery_ujs.js
main.js
jsxc.js
+ bookmarklet.js
mobile/bookmarklet.js
mobile/mobile.js
templates.js
@@ -81,10 +89,7 @@ module Diaspora
rtl.css
color_themes/*/desktop.css
color_themes/*/mobile.css
- )
-
- # Version of your assets, change this if you want to expire all your assets
- config.assets.version = '1.0'
+ ]
# See lib/tasks/assets.rake: non_digest_assets
config.assets.non_digest_assets = %w(branding/logos/asterisk.png)
@@ -95,9 +100,6 @@ module Diaspora
g.test_framework :rspec
end
- # Will be default with Rails 5
- config.active_record.raise_in_transactional_callbacks = true
-
# Setup action mailer early
config.action_mailer.default_url_options = {
protocol: AppConfig.pod_uri.scheme,
diff --git a/config/boot.rb b/config/boot.rb
index 6e3d23427..e9f0721fe 100644
--- a/config/boot.rb
+++ b/config/boot.rb
@@ -1,9 +1,6 @@
-# Set up gems listed in the Gemfile.
-ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
-require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
+ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
-# Ensure Builder is loaded
-require 'active_support/builder' unless defined?(Builder)
+require "bundler/setup" # Set up gems listed in the Gemfile.
# Load configuration early
-require_relative 'load_config'
+require_relative "load_config"
diff --git a/config/color_themes.yml b/config/color_themes.yml
index 896658841..45dfd5106 100644
--- a/config/color_themes.yml
+++ b/config/color_themes.yml
@@ -1,7 +1,7 @@
available:
- original: "Original Gray"
- original_white: "Original White Background"
- dark_green: "Dark Green"
- magenta: "Magenta"
- egyptian_blue: "Egyptian Blue"
- dark: "Dark"
+ - original
+ - original_white
+ - dark_green
+ - magenta
+ - egyptian_blue
+ - dark
diff --git a/config/defaults.yml b/config/defaults.yml
index 9d8a29108..2ffaf3fe0 100644
--- a/config/defaults.yml
+++ b/config/defaults.yml
@@ -4,7 +4,7 @@
defaults:
version:
- number: "0.6.7.0" # Do not touch unless doing a release, do not backport the version number that's in master
+ number: "0.7.0.0" # Do not touch unless doing a release, do not backport the version number that's in master
heroku: false
environment:
url: "http://localhost:3000/"
@@ -76,8 +76,6 @@ defaults:
enable: false
host:
site_id:
- mixpanel_uid:
- chartbeat_uid:
statistics:
user_counts: false
post_counts: false
diff --git a/config/diaspora.yml.example b/config/diaspora.yml.example
index a5c2cdc51..b2573625d 100644
--- a/config/diaspora.yml.example
+++ b/config/diaspora.yml.example
@@ -306,12 +306,6 @@ configuration: ## Section
#host: 'stats.example.org'
#site_id: 1
- ## Mixpanel event tracking (disabled by default).
- #mixpanel_uid:
-
- ## Chartbeat tracking (disabled by default).
- #chartbeat_uid:
-
## Statistics
## Your pod will report its name, software version and whether
## or not registrations are open via /statistics.json.
diff --git a/config/environment.rb b/config/environment.rb
index c9482d0ee..426333bb4 100644
--- a/config/environment.rb
+++ b/config/environment.rb
@@ -1,5 +1,5 @@
-# Load the rails application
+# Load the Rails application.
require_relative 'application'
-# Initialize the rails application
-Diaspora::Application.initialize!
+# Initialize the Rails application.
+Rails.application.initialize!
diff --git a/config/environments/development.rb b/config/environments/development.rb
index 2d00a9b03..f422f016e 100644
--- a/config/environments/development.rb
+++ b/config/environments/development.rb
@@ -1,5 +1,5 @@
-Diaspora::Application.configure do
- # Settings specified here will take precedence over those in config/application.rb
+Rails.application.configure do
+ # Settings specified here will take precedence over those in config/application.rb.
# In the development environment your application's code is reloaded on
# every request. This slows down response time but is perfect for development
@@ -9,35 +9,55 @@ Diaspora::Application.configure do
# Do not eager load code on boot.
config.eager_load = false
- # Show full error reports and disable caching
- config.consider_all_requests_local = true
- config.action_controller.perform_caching = false
+ # Show full error reports.
+ config.consider_all_requests_local = true
- # Don't care if the mailer can't send
- config.action_mailer.raise_delivery_errors = false
+ # Enable/disable caching. By default caching is disabled.
+ if Rails.root.join("tmp", "caching-dev.txt").exist?
+ config.action_controller.perform_caching = true
- # Raise an error on page load if there are pending migrations
- config.active_record.migration_error = :page_load
+ config.cache_store = :memory_store
+ config.public_file_server.headers = {
+ "Cache-Control" => "public, max-age=#{2.days.seconds.to_i}"
+ }
+ else
+ config.action_controller.perform_caching = false
- # Print deprecation notices to the Rails logger
- config.active_support.deprecation = :log
+ config.cache_store = :null_store
+ end
+
+ # Don't care if the mailer can't send.
+ config.action_mailer.raise_delivery_errors = false
- # Only use best-standards-support built into browsers
- config.action_dispatch.best_standards_support = :builtin
+ config.action_mailer.perform_caching = false
+ # Print deprecation notices to the Rails logger.
+ config.active_support.deprecation = :log
- # Do not compress assets
- config.assets.compress = false
+ # Raise an error on page load if there are pending migrations.
+ config.active_record.migration_error = :page_load
- # Expands the lines which load the assets
+ # Debug mode disables concatenation and preprocessing of assets.
+ # This option may cause significant delays in view rendering with a large
+ # number of complex assets.
config.assets.debug = true
+ # Suppress logger output for asset requests.
+ config.assets.quiet = true
+
# Set the logging destination(s)
config.log_to = %w[stdout file]
# Show the logging configuration on STDOUT
config.show_log_configuration = true
+ # Raises error for missing translations
+ # config.action_view.raise_on_missing_translations = true
+
+ # Use an evented file watcher to asynchronously detect changes in source code,
+ # routes, locales, etc. This feature depends on the listen gem.
+ config.file_watcher = ActiveSupport::EventedFileUpdateChecker
+
# Speed up asset serving
config.middleware.insert 0, TurboDevAssets
end
diff --git a/config/environments/production.rb b/config/environments/production.rb
index a624236ab..65d1bc1de 100644
--- a/config/environments/production.rb
+++ b/config/environments/production.rb
@@ -1,35 +1,52 @@
-Diaspora::Application.configure do
- # Settings specified here will take precedence over those in config/application.rb
+Rails.application.configure do
+ # Settings specified here will take precedence over those in config/application.rb.
- # Code is not reloaded between requests
+ # Code is not reloaded between requests.
config.cache_classes = true
# Eager load code on boot. This eager loads most of Rails and
- # your application in memory, allowing both thread web servers
+ # your application in memory, allowing both threaded web servers
# and those relying on copy on write to perform better.
# Rake tasks automatically ignore this option for performance.
config.eager_load = true
+ config.eager_load_paths += %W[#{config.root}/lib]
- # Full error reports are disabled and caching is turned on
+ # Full error reports are disabled and caching is turned on.
config.consider_all_requests_local = false
config.action_controller.perform_caching = true
- # Disable Rails's static asset server (Apache or nginx will already do this)
- config.serve_static_files = false
+ # Attempt to read encrypted secrets from `config/secrets.yml.enc`.
+ # Requires an encryption key in `ENV["RAILS_MASTER_KEY"]` or
+ # `config/secrets.yml.key`.
+ config.read_encrypted_secrets = true
+
+ # Disable serving static files from the `/public` folder by default since
+ # Apache or NGINX already handles this.
+ config.public_file_server.enabled = ENV["RAILS_SERVE_STATIC_FILES"].present?
# Compress JavaScripts and CSS.
config.assets.js_compressor = :uglifier
# config.assets.css_compressor = :sass
- # Don't fallback to assets pipeline if a precompiled asset is missed
+ # Do not fallback to assets pipeline if a precompiled asset is missed.
config.assets.compile = false
- # Generate digests for assets URLs
+ # Generate digests for assets URLs.
config.assets.digest = true
- # Specifies the header that your server uses for sending files
- # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
- # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
+ # Enable serving of images, stylesheets, and JavaScripts from an asset server.
+ if AppConfig.environment.assets.host.present?
+ config.action_controller.asset_host = AppConfig.environment.assets.host.get
+ end
+
+ # Specifies the header that your server uses for sending files.
+ # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache
+ # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX
+
+ # Mount Action Cable outside main process or domain
+ # config.action_cable.mount_path = nil
+ # config.action_cable.url = 'wss://example.com/cable'
+ # config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ]
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
# config.force_ssl = true
@@ -37,44 +54,44 @@ Diaspora::Application.configure do
# Log level
config.log_level = :info
+ # Prepend all log lines with the following tags.
+ # config.log_tags = [ :request_id ]
+
# Set the logging destination(s)
config.log_to = %w[file]
# Show the logging configuration on STDOUT
config.show_log_configuration = false
- # Prepend all log lines with the following tags
- # config.log_tags = [ :subdomain, :uuid ]
-
- # Use a different logger for distributed setups
- # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
-
- # Use a different cache store in production
+ # Use a different cache store in production.
# config.cache_store = :mem_cache_store
- # Enable serving of images, stylesheets, and JavaScripts from an asset server
- # config.action_controller.asset_host = "http://assets.example.com"
-
- # Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
- # config.assets.precompile += %w( search.js )
+ config.action_mailer.perform_caching = false
- # Disable delivery errors, bad email addresses will be ignored
+ # Ignore bad email addresses and do not raise email delivery errors.
+ # Set this to true and configure the email server for immediate delivery to raise delivery errors.
# config.action_mailer.raise_delivery_errors = false
- # Enable autoload for rake tasks
- config.dependency_loading = true if $rails_rake_task
-
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
- # the I18n.default_locale when a translation can not be found)
+ # the I18n.default_locale when a translation cannot be found).
config.i18n.fallbacks = true
- # Send deprecation notices to registered listeners
+ # Send deprecation notices to registered listeners.
config.active_support.deprecation = :notify
- # For nginx:
- config.action_dispatch.x_sendfile_header = "X-Accel-Redirect"
+ # Use default logging formatter so that PID and timestamp are not suppressed.
+ # config.log_formatter = ::Logger::Formatter.new
- if AppConfig.environment.assets.host.present?
- config.action_controller.asset_host = AppConfig.environment.assets.host.get
- end
+ # Use a different logger for distributed setups.
+ # require 'syslog/logger'
+ # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name')
+
+ # if ENV["RAILS_LOG_TO_STDOUT"].present?
+ # logger = ActiveSupport::Logger.new(STDOUT)
+ # logger.formatter = config.log_formatter
+ # config.logger = ActiveSupport::TaggedLogging.new(logger)
+ # end
+
+ # Do not dump schema after migrations.
+ config.active_record.dump_schema_after_migration = false
end
diff --git a/config/environments/test.rb b/config/environments/test.rb
index ad12d1620..d9d87dbd0 100644
--- a/config/environments/test.rb
+++ b/config/environments/test.rb
@@ -1,5 +1,5 @@
-Diaspora::Application.configure do
- # Settings specified here will take precedence over those in config/application.rb
+Rails.application.configure do
+ # Settings specified here will take precedence over those in config/application.rb.
# The test environment is used exclusively to run your application's
# test suite. You never need to work with it otherwise. Remember that
@@ -12,28 +12,48 @@ Diaspora::Application.configure do
# preloads Rails for running tests, you may have to set it to true.
config.eager_load = false
- # Configure static asset server for tests with Cache-Control for performance
- config.serve_static_files = true
- config.static_cache_control = "public, max-age=3600"
+ # Configure public file server for tests with Cache-Control for performance.
+ config.public_file_server.enabled = true
+ config.public_file_server.headers = {
+ "Cache-Control" => "public, max-age=#{1.hour.seconds.to_i}"
+ }
- # Show full error reports and disable caching
+ # Suppress logger output for asset requests.
+ config.assets.quiet = true
+
+ # Precompile poltergeist_disable_transition.css for tests
+ config.assets.precompile += %w[poltergeist_disable_transition.css]
+
+ # Don't precompile all themes for tests
+ config.assets.precompile -= %w[color_themes/*/desktop.css color_themes/*/mobile.css]
+ config.assets.precompile += %w[
+ color_themes/original/desktop.css
+ color_themes/dark_green/desktop.css
+ color_themes/original/mobile.css
+ ]
+
+ # Show full error reports and disable caching.
config.consider_all_requests_local = true
config.action_controller.perform_caching = false
- # Raise exceptions instead of rendering exception templates
- config.action_dispatch.show_exceptions = true
+ # Raise exceptions instead of rendering exception templates.
+ config.action_dispatch.show_exceptions = false
- # Disable request forgery protection in test environment
- config.action_controller.allow_forgery_protection = false
+ # Disable request forgery protection in test environment.
+ config.action_controller.allow_forgery_protection = false
+ config.action_mailer.perform_caching = false
# Tell Action Mailer not to deliver emails to the real world.
# The :test delivery method accumulates sent emails in the
# ActionMailer::Base.deliveries array.
config.action_mailer.delivery_method = :test
- # Print deprecation notices to the stderr
+ # Print deprecation notices to the stderr.
config.active_support.deprecation = :stderr
# Set the logging destination(s)
config.log_to = %w[file]
+
+ # Raises error for missing translations
+ # config.action_view.raise_on_missing_translations = true
end
diff --git a/config/initializers/application_controller_renderer.rb b/config/initializers/application_controller_renderer.rb
new file mode 100644
index 000000000..51639b67a
--- /dev/null
+++ b/config/initializers/application_controller_renderer.rb
@@ -0,0 +1,6 @@
+# Be sure to restart your server when you modify this file.
+
+# ApplicationController.renderer.defaults.merge!(
+# http_host: 'example.org',
+# https: false
+# )
diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb
index 686871f66..33e369e29 100644
--- a/config/initializers/assets.rb
+++ b/config/initializers/assets.rb
@@ -1,15 +1,26 @@
-# Copyright (c) 2010-2011, Diaspora Inc. This file is
-# licensed under the Affero General Public License version 3 or later. See
-# the COPYRIGHT file.
+# Be sure to restart your server when you modify this file.
# bootstrap-markdown plugin relies on rails-assets-bootstrap gem but we use
# bootstrap-sass this line makes sure we exclude every asset comming
# from rails-assets-bootstrap to prevent conflicts with bootstrap-sass
-Rails.configuration.assets.paths.reject! do |path|
- path.include?("rails-assets-bootstrap") && !path.include?("rails-assets-bootstrap-markdown")
-end
-Diaspora::Application.configure do
- config.serve_static_files = AppConfig.environment.assets.serve?
- # config.static_cache_control = "public, max-age=3600" if AppConfig[:serve_static_assets].to_s == 'true'
+# See https://github.com/tenex/rails-assets/issues/314
+Rails.application.config.after_initialize do
+ # add the gem names you wish to reject to the below array
+ excluded_gem_names = ["rails-assets-bootstrap"]
+
+ excluded_gem_full_names = Gem::Specification.select {|g| excluded_gem_names.include? g.name }.flat_map(&:full_name)
+ Rails.application.config.assets.paths.reject! do |path|
+ excluded_gem_full_names.any? {|gem_name| path.include? gem_name }
+ end
end
+
+# Version of your assets, change this if you want to expire all your assets.
+Rails.application.config.assets.version = "1.0"
+
+# Add additional assets to the asset load path.
+# Rails.application.config.assets.paths << Emoji.images_path
+# Add Yarn node_modules folder to the asset load path.
+# Rails.application.config.assets.paths << Rails.root.join("node_modules")
+
+Rails.application.config.public_file_server.enabled = AppConfig.environment.assets.serve?
diff --git a/config/initializers/backtrace_silencers.rb b/config/initializers/backtrace_silencers.rb
new file mode 100644
index 000000000..59385cdf3
--- /dev/null
+++ b/config/initializers/backtrace_silencers.rb
@@ -0,0 +1,7 @@
+# Be sure to restart your server when you modify this file.
+
+# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
+# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
+
+# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
+# Rails.backtrace_cleaner.remove_silencers!
diff --git a/config/initializers/color_themes.rb b/config/initializers/color_themes.rb
index 6f76ee51c..ae4757610 100644
--- a/config/initializers/color_themes.rb
+++ b/config/initializers/color_themes.rb
@@ -8,12 +8,10 @@ if color_themes_file.exist?
# else include the original theme.
AVAILABLE_COLOR_THEMES =
if color_themes["available"].length > 0
- color_themes["available"]
+ color_themes["available"].freeze
else
- {"original" => "Original Gray"}
+ ["original"].freeze
end
else
- AVAILABLE_COLOR_THEMES = {"original" => "Original Gray"}.freeze
+ AVAILABLE_COLOR_THEMES = ["original"].freeze
end
-# Get all codes from available themes into a separate variable, so that they can be called easier.
-AVAILABLE_COLOR_THEME_CODES = AVAILABLE_COLOR_THEMES.keys
diff --git a/config/initializers/cookies_serializer.rb b/config/initializers/cookies_serializer.rb
new file mode 100644
index 000000000..1389e86a3
--- /dev/null
+++ b/config/initializers/cookies_serializer.rb
@@ -0,0 +1,5 @@
+# Be sure to restart your server when you modify this file.
+
+# Specify a serializer for the signed and encrypted cookie jars.
+# Valid options are :json, :marshal, and :hybrid.
+Rails.application.config.action_dispatch.cookies_serializer = :marshal
diff --git a/config/initializers/cors.rb b/config/initializers/cors.rb
index a50aead3e..0fccba3fe 100644
--- a/config/initializers/cors.rb
+++ b/config/initializers/cors.rb
@@ -1,4 +1,11 @@
-Rails.application.config.middleware.insert 0, Rack::Cors do
+# Be sure to restart your server when you modify this file.
+
+# Avoid CORS issues when API is called from the frontend app.
+# Handle Cross-Origin Resource Sharing (CORS) in order to accept cross-origin AJAX requests.
+
+# Read more: https://github.com/cyu/rack-cors
+
+Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins "*"
resource "/api/openid_connect/user_info", methods: %i(get post)
@@ -6,6 +13,5 @@ Rails.application.config.middleware.insert 0, Rack::Cors do
resource "/.well-known/host-meta"
resource "/.well-known/webfinger"
resource "/.well-known/openid-configuration"
- resource "/webfinger"
end
end
diff --git a/config/initializers/diaspora_federation.rb b/config/initializers/diaspora_federation.rb
index aff729ec4..e9270d469 100644
--- a/config/initializers/diaspora_federation.rb
+++ b/config/initializers/diaspora_federation.rb
@@ -13,16 +13,22 @@ DiasporaFederation.configure do |config|
person = Person.where(diaspora_handle: diaspora_id, closed_account: false).where.not(owner: nil).first
if person
DiasporaFederation::Discovery::WebFinger.new(
- acct_uri: "acct:#{person.diaspora_handle}",
- alias_url: AppConfig.url_to("/people/#{person.guid}"),
- hcard_url: AppConfig.url_to(DiasporaFederation::Engine.routes.url_helpers.hcard_path(person.guid)),
- seed_url: AppConfig.pod_uri,
- profile_url: person.profile_url,
- atom_url: person.atom_url,
- salmon_url: person.receive_url,
- subscribe_url: AppConfig.url_to("/people?q={uri}"),
- guid: person.guid,
- public_key: person.serialized_public_key
+ {
+ acct_uri: "acct:#{person.diaspora_handle}",
+ hcard_url: AppConfig.url_to(DiasporaFederation::Engine.routes.url_helpers.hcard_path(person.guid)),
+ seed_url: AppConfig.pod_uri,
+ profile_url: person.profile_url,
+ atom_url: person.atom_url,
+ salmon_url: person.receive_url,
+ subscribe_url: AppConfig.url_to("/people?q={uri}")
+ },
+ aliases: [AppConfig.url_to("/people/#{person.guid}")],
+ links: [
+ {
+ rel: OpenIDConnect::Discovery::Provider::Issuer::REL_VALUE,
+ href: Rails.application.routes.url_helpers.root_url
+ }
+ ]
)
end
end
diff --git a/config/initializers/filter_parameter_logging.rb b/config/initializers/filter_parameter_logging.rb
index d08250390..9d07a384f 100644
--- a/config/initializers/filter_parameter_logging.rb
+++ b/config/initializers/filter_parameter_logging.rb
@@ -1,4 +1,4 @@
# Be sure to restart your server when you modify this file.
# Configure sensitive parameters which will be filtered from the log file.
-Rails.application.config.filter_parameters += %i(password message text bio)
+Rails.application.config.filter_parameters += %i[password message text bio]
diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb
new file mode 100644
index 000000000..ac033bf9d
--- /dev/null
+++ b/config/initializers/inflections.rb
@@ -0,0 +1,16 @@
+# Be sure to restart your server when you modify this file.
+
+# Add new inflection rules using the following format. Inflections
+# are locale specific, and you may define rules for as many different
+# locales as you wish. All of these examples are active by default:
+# ActiveSupport::Inflector.inflections(:en) do |inflect|
+# inflect.plural /^(ox)$/i, '\1en'
+# inflect.singular /^(ox)en/i, '\1'
+# inflect.irregular 'person', 'people'
+# inflect.uncountable %w( fish sheep )
+# end
+
+# These inflection rules are supported but not enabled by default:
+# ActiveSupport::Inflector.inflections(:en) do |inflect|
+# inflect.acronym 'RESTful'
+# end
diff --git a/config/initializers/mime_types.rb b/config/initializers/mime_types.rb
new file mode 100644
index 000000000..dc1899682
--- /dev/null
+++ b/config/initializers/mime_types.rb
@@ -0,0 +1,4 @@
+# Be sure to restart your server when you modify this file.
+
+# Add new mime types for use in respond_to blocks:
+# Mime::Type.register "text/richtext", :rtf
diff --git a/config/initializers/secure_headers.rb b/config/initializers/secure_headers.rb
index 99d3fd2c5..d2b44fb9f 100644
--- a/config/initializers/secure_headers.rb
+++ b/config/initializers/secure_headers.rb
@@ -31,13 +31,7 @@ SecureHeaders::Configuration.default do |config|
end
end
- if AppConfig.privacy.mixpanel_uid.present?
- csp[:script_src] << "api.mixpanel.com"
- csp[:connect_src] << "api.mixpanel.com"
- end
-
csp[:script_src] << "code.jquery.com" if AppConfig.privacy.jquery_cdn?
- csp[:script_src] << "static.chartbeat.com" if AppConfig.privacy.chartbeat_uid.present?
csp[:form_action] << "www.paypal.com" if AppConfig.settings.paypal_donations.enable?
csp[:report_uri] = [AppConfig.settings.csp.report_uri] if AppConfig.settings.csp.report_uri.present?
diff --git a/config/initializers/wrap_parameters.rb b/config/initializers/wrap_parameters.rb
index ddd9dd5ab..c72a96765 100644
--- a/config/initializers/wrap_parameters.rb
+++ b/config/initializers/wrap_parameters.rb
@@ -5,10 +5,10 @@
# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
ActiveSupport.on_load(:action_controller) do
- wrap_parameters format: [:json] if respond_to?(:wrap_parameters)
+ wrap_parameters format: [:json]
end
# To enable root element in JSON for ActiveRecord objects.
ActiveSupport.on_load(:active_record) do
- self.include_root_in_json = true
+ self.include_root_in_json = true
end
diff --git a/config/locale_settings.yml b/config/locale_settings.yml
index 7f49e6f00..88d5047d6 100644
--- a/config/locale_settings.yml
+++ b/config/locale_settings.yml
@@ -58,6 +58,7 @@ available:
pt-BR: "Português (Brasil)"
ro: "Română"
ru: "Русский"
+ sc: "Sardu"
si: "සිංහල"
sk: "Slovenčina"
sl: "Slovenščina"
@@ -128,6 +129,10 @@ fallbacks:
- "pt"
pt-PT:
- "pt"
+ oc:
+ - "it"
+ sc:
+ - "it"
rtl:
- "ar"
diff --git a/config/locales/devise/devise.oc.yml b/config/locales/devise/devise.oc.yml
index a48509c2f..2251be5d0 100644
--- a/config/locales/devise/devise.oc.yml
+++ b/config/locales/devise/devise.oc.yml
@@ -24,7 +24,7 @@ oc:
unauthenticated: "Vos cal vos connectar o vos inscriure abans de contunhar."
unconfirmed: "Vos cal confirmar vòstre compte abans de contunhar."
invitations:
- invitation_token_invalid: "O planhèm ! Aqueste convit es pas valid."
+ invitation_token_invalid: "O planhèm ! Aqueste convit es pas valid."
send_instructions: "Vòstre convit es estat mandat."
updated: "Vòstre senhal es estat creat. Ara, sètz connectat."
mailer:
@@ -32,7 +32,7 @@ oc:
confirm: "Confirmar mon compte"
subject: "Instruccions de confirmacion"
you_can_confirm: "Podètz confirmar vòstre compte en clicant sul ligam çaijós :"
- hello: "Adieusiatz %{email} !"
+ hello: "Adieusiatz %{email} !"
inviter:
accept_at: "a %{url}, lo podètz acceptar a travèrs lo ligal çaijós."
has_invited_you: "%{name}"
@@ -50,7 +50,7 @@ oc:
click_to_unlock: "Clicatz sul ligam çaijós per desblocar vòstre compte :"
subject: "Instruccions de desverrolhatge"
unlock: "Desverrolhar mon compte"
- welcome: "Benvenguda %{email} !"
+ welcome: "Benvenguda %{email} !"
omniauth_callbacks:
failure: "Impossible de vos indentificar de %{kind} perque %{reason}"
success: "Autentificacion capitada de lo compte %{kind}."
@@ -61,7 +61,7 @@ oc:
new_password: "Senhal novèl"
new:
email: "Adreça de corrièl"
- forgot_password: "Avètz doblidat vòstre senhal ?"
+ forgot_password: "Avètz oblidat vòstre senhal ?"
no_account: "Cap de compte es pas associat a aquesta adreça de corrièr electronic."
reset_password: "Reïnicializar lo senhal"
send_password_instructions: "Mandar las instruccions de reïnicializacion de senhal"
@@ -71,7 +71,7 @@ oc:
updated: "Vòstre senhal es estat modificat. Ara, sètz connectat."
updated_not_active: "Vòstre senhal es estat cambiat amb succès."
registrations:
- destroyed: "Adissatz ! Vòstre compte es estat suprimit amb succès. Esperem vos tornar veire lèu."
+ destroyed: "Adissatz ! Vòstre compte es estat suprimit amb succès. Esperem vos tornar veire lèu."
signed_up: "Vòstra inscripcion es estada efectuada. Se aquesta darrièra es activada, una confirmacion es estada mandada a vòstra adreça de corrièr electronic."
signed_up_but_inactive: "Vos sètz inscrit amb succès. Pasmens, vos podètz pas connectar perque vòstre compte es pas encara activat."
signed_up_but_locked: "Vos sètz inscrit amb succès. Pasmens, podètz pas vos connectar perque vòstre compte es verrolhat."
@@ -91,7 +91,7 @@ oc:
signed_out: "Ara, sètz desconnectat."
shared:
links:
- forgot_your_password: "Avètz doblidat vòstre senhal ?"
+ forgot_your_password: "Avètz oblidat vòstre senhal ?"
receive_confirmation: "Avètz pas recebut las instruccions de confirmacion ?"
receive_unlock: "Avètz pas recebut las instruccions de desblocatge ?"
sign_in: "Connexion"
diff --git a/config/locales/diaspora/br.yml b/config/locales/diaspora/br.yml
index 5d4a65d89..8c38774db 100644
--- a/config/locales/diaspora/br.yml
+++ b/config/locales/diaspora/br.yml
@@ -286,18 +286,10 @@ br:
what_is_a_pod_a: "Un dafariad oc'h erounit ar meziant diaspora* ha kennasket d'ar rouedad diaspora eo ur pod. \"Pod\" a zo un dave d'ar ger Saoznek \"pod\", a dalv kement ha \"klorenn\", oc'h enderc'hel greun evel-mañ ma vez endalc'het kontoù gant an dafariad. Meur a pod a vez kavet. Gallout a rit ouzhpennañ mignoned adalek ar podoù all hag eskemm ganto. N'eus ezhomm ebet digeriñ kontoù war podoù disheñvel ! Unan 'zo trawalc'h. Gallout a rit soñjal eo ur pod disapora* evel ur pourchaser posteloù. Podoù foran a zo, reoù prevez, ha ma klaskit mat ez eus tu deoc'h erounit ho hini."
posts_and_posting:
char_limit_services_q: "Petra c'hoarvez ma rannan va fost gant ur servij kennasket gant ur vevenn arouezioù bihanoc'h ?"
- image_text: "testenn ar skeudenn"
- image_url: "URL ar skeudenn"
private_posts:
title: "Embannadennoù prevez"
- private_profiles:
- title: "aeladoù prevez"
public_posts:
title: "Embannadennoù foran"
- public_profiles:
- title: "Aeladoù foran"
- whats_in_profile_q: "Ar pezh zo em aelad foran"
- who_sees_profile_q: "Piv a wel ma aelad foran ?"
sharing:
title: "O rannañ"
tags:
diff --git a/config/locales/diaspora/bs.yml b/config/locales/diaspora/bs.yml
index a2549c2bd..77359b4ea 100644
--- a/config/locales/diaspora/bs.yml
+++ b/config/locales/diaspora/bs.yml
@@ -265,11 +265,6 @@ bs:
can_reshare_q: "Ko može ponovo dijeliti moje privatne objave?"
title: "Privatne objave"
who_sees_post_q: "Kada objavim poruku na aspekt (tj. privatnu objavu), ko je može vidjeti?"
- private_profiles:
- title: "Privatni profili"
- whats_in_profile_q: "Šta je u mojem privatnom profilu?"
- who_sees_profile_q: "Ko vidi moj privatni profil?"
- who_sees_updates_q: "Ko vidi ažuriranja na mojem privatnom profilu?"
public_posts:
can_comment_reshare_like_q: "Ko može komentarisati na, ponovo dijeliti, ili sviđati moju javnu objavu="
find_public_post_q: "Kako drugi ljudi mogu pronaći moje javne objave?"
diff --git a/config/locales/diaspora/cs.yml b/config/locales/diaspora/cs.yml
index 17d8a215c..ecf407681 100644
--- a/config/locales/diaspora/cs.yml
+++ b/config/locales/diaspora/cs.yml
@@ -170,6 +170,7 @@ cs:
description: "To umožňuje aplikaci číst váš rozšířený profil"
name: "Rozšířený profil"
read:
+ description: "Toto umožňuje aplikaci číst Váš proud, Vaše konverzace a Váš celý profil."
name: "číst profil, stream a konverzace"
write:
name: "posílat příspěvky, konverzace a reakce"
@@ -180,7 +181,9 @@ cs:
no_requirement: "%{name} nevyžaduje oprávnění"
title: "Povolené aplikace"
no_applications: "Nemáte žádné autorizované aplikace"
+ policy: "Viz podmínky ochrany osobních údajů této aplikace"
revoke_autorization: "Odebrat oprávnění"
+ tos: "Viz podmínky služby této aplikace"
are_you_sure: "Jste si jisti?"
are_you_sure_delete_account: "Opravdu chcete uzavřít svůj účet? Tuto operaci nelze vrátit!"
aspect_memberships:
@@ -400,7 +403,7 @@ cs:
mentions:
how_to_mention_a: "Napište znak „@“ a začněte psát své jméno. Mělo by se zobrazit rozbalovací menu, které vám umožní je snadněji vybrat. Berte na vědomí, že je možné zmínit jen ty osoby, které máte v aspektech."
how_to_mention_q: "Jak mohu někoho zmínit, když píšu příspěvek?"
- mention_in_comment_a: "Ne, zatím ne."
+ mention_in_comment_a: "Ano, od verze 0.7.0.0 ! V komentáři můžete někoho zmínit úplně stejně jako v příspěvku. Napište \"@\" a začněte psát jméno. Nezapomeňte, že pokud komentujete příspěvek, který není veřejný, můžete zmiňovat jen uživatele, kteří již nějak s příspěvkem pracovali."
mention_in_comment_q: "Dá se někdo zmínit v komentáři?"
see_mentions_a: "Ano, klikněte „Zmínky“ v levém sloupci na své domovské stránce"
see_mentions_q: "Je způsob, jak vidět příspěvky, v kterých jsem byl(a) zmíněn(a)?"
@@ -436,11 +439,7 @@ cs:
format_text_q: "Jak mohu formátovat text ve svých příspěvcích (tučný text, kurzíva apod.)?"
hide_posts_a: "Najedete-li myší na něčí příspěvek, objeví se vpravo nahoře malý křížek podobný písmenu x. Kliknutím na křížek příspěvek skryjete a zamezíte i e-mailovým upozorněním na něj. Při návštěvě profilové stránky autora tohoto příspěvku však příspěvek stále uvidíte."
hide_posts_q: "Jak skrýt příspěvek ? / Jak vypnout zasílání upozornění o příspěvcích, které jsem okomentoval(a) ?"
- image_text: "text k obrázku"
- image_url: "url obrázku"
insert_images_a: "Pro vložení obrázku do příspěvku klikněte na ikonku fotoaparátu vpravo dole. Klikněte na ikonku znova, pokud chcete vložit další obrázek, nebo můźete vybrat několik obrázků najednou."
- insert_images_comments_a1: "Následující Markdown kód"
- insert_images_comments_a2: "může být užito k vkládání obrázků z webu do komentářů i do příspěvků."
insert_images_comments_q: "Můžu vkládat obrázky do komentářů?"
insert_images_q: "Jak vkládat obrázky do příspěvků?"
post_location_a: "Klikněte při publikaci na ikonu špendlíku vedle fotoaparátu. Tím přidáte Vaší geografickou pozici z OpenStreetMap. Svou pozici můžete dále upravit, např. zadat pouze město, ve kterém jste, a ne detailní adresu včetně ulice."
@@ -469,14 +468,6 @@ cs:
title: "Soukromé příspěvky"
who_sees_post_a: "Jen přihlášení uživatelé diaspory*, které jste umístil(a) do toho aspektu mohou vidět váš soukromý příspěvek."
who_sees_post_q: "Co když odešlu zprávu aspektu (tj. soukromý příspěvek), kdo ji uvidí?"
- private_profiles:
- title: "Soukromé profily"
- whats_in_profile_a: "Něco o Vás, poloha, pohlaví a datum narození. To jsou údaje ve spodní sekci při editaci osobního profilu. Všechny tyto položky jsou nepovinné, je na Vás, zda je vyplníte. Přihlášení uživatelé, kteří jsou v některém z Vašich aspektů, jsou jediní, kteří mohou vidět Váš profil. Při návštěǚe Vašeho profilu také uvidí příspěvky, které jste adresoval/a jejich aspektu společně s Vašimi veřejnými příspěvky."
- whats_in_profile_q: "Co je v mém soukromém profilu?"
- who_sees_profile_a: "Každý přihlášený uživatel, se kterým sdílíte (tj. přidal/a jste jej do jednoho ze svých aspektů). Lidé, kteří Vás sledují, ale které nesledujete Vy, uvidí pouze Vaše veřejné informace."
- who_sees_profile_q: "Kdo vidí můj soukromý profil?"
- who_sees_updates_a: "Všichni v tvých aspektech vidí změny tvého soukromého profilu. "
- who_sees_updates_q: "Kdo vidí aktualizace mého soukromého profilu?"
public_posts:
can_comment_reshare_like_a: "Každý přihlášený diaspora* uživatel může komentovat, sdílet či lajkovat Váš veřejný příspěvek."
can_comment_reshare_like_q: "Kdo může komentovat, sdílet či lajkovat můj veřejný příspěvek ?"
@@ -489,16 +480,6 @@ cs:
title: "Veřejné příspěvky"
who_sees_post_a: "Každý uživatel internetu může teoreticky vidět příspěvek, který označíte jako veřejný. To je ideální cesta jak oslovit veřejnost."
who_sees_post_q: "Pokud posílám veřejný příspěvek, kdo jej můźe vidět ?"
- public_profiles:
- title: "Veřejné profily"
- what_do_tags_do_a: "Pomáhají lidem Vás poznat. Vaše profilová fotka se objeví na levé straně stránek těchto konkrétních štítků, společně s fotkami dalších uživatelů, kteří mají štítek na svém veřejném profilu."
- what_do_tags_do_q: "Jakou funkci plní štítky na mém veřejném profilu?"
- whats_in_profile_a: "Vaše jméno, pět štítků, které Vás popisují a Vaše fotografie. To jsou údaje v horní části editace profilové stránky. Tyto údaje můžete zadat velmi identifikujícím či velmi anonymním způsobem, volba je na Vás. Vaše profilová stránka také zobrazuje všechny Vaše veřejné příspěvky."
- whats_in_profile_q: "Co je v mém veřejném profilu"
- who_sees_profile_a: "Profil může vidět jakýkoliv přihlášený uživatel diaspora* a i všichni uživatelé internetu. Každý profil má svou přímou URL, která může být použita i ze stránek mimo diaspora*. Profil také mohou indexovat vyhledávače."
- who_sees_profile_q: "Kdo vidí můj veřejný profil?"
- who_sees_updates_a: "Kdokoliv může vidět změny, pokud navštíví Vaš profil."
- who_sees_updates_q: "Kdo vidí aktualizace mého veřejného profilu?"
resharing_posts:
reshare_private_post_aspects_a: "Ne, není možné sdílet něčí soukromý příspěvek. Tím je respektován záměr původního autora sdílet příspěvek jen konkrétní skupině lidí."
reshare_private_post_aspects_q: "Mohu (znovu)sdílet soukromý příspěvek jen s některými aspekty ?"
diff --git a/config/locales/diaspora/da.yml b/config/locales/diaspora/da.yml
index f8cd218aa..2cec1fffa 100644
--- a/config/locales/diaspora/da.yml
+++ b/config/locales/diaspora/da.yml
@@ -271,6 +271,13 @@ da:
heading: "Bogmærke"
post_something: "Skriv indlæg til Diaspora"
cancel: "Annuller"
+ color_themes:
+ dark: "Mørk"
+ dark_green: "Mørk grøn"
+ egyptian_blue: "Ægyptisk blå"
+ magenta: "Magenta"
+ original: "Original grå"
+ original_white: "Original hvid baggrund"
comments:
create:
error: "Du kunne ikke kommentere."
@@ -346,7 +353,7 @@ da:
data_visible_to_podmin_q: "Hvor meget af min information kan min pod-administrator se?"
download_data_a: "Ja. I bunden af din kontofane i Indstillinger er der to knapper. Den ene er til at downloade dine data, den andentil at downloade dine billeder."
download_data_q: "Kan jeg downloade en kopi af alle de data der er indeholdt i min seed (konto)?"
- move_pods_a: "I fremtiden vil du være i stand til at eksportere dine seed fra en pod og importere dem på en anden, men dette er ikke på nuværende tidspunkt muligt. Du kan altid åbne en ny konto og tilføje kontakter til aspekter der, og så bede dem om at tilføje din nye konto til deres aspekter."
+ move_pods_a: "Version 0.7.0.0 af Diaspora indleder den første fase af konto migration: Du kan nu eksportere alle dine data fra \"Konto\" sektionen af brugerindstillingerne. Hold dine data i sikkerhed! I en fremtidig udgivelse vil du kunne overføre hele din konto, herunder indlæg og kontakter, til en anden pod."
move_pods_q: "Hvordan flytter jeg min seed (konto) fra en pod til en anden?"
title: "Konto og data-administration"
aspects:
@@ -354,7 +361,7 @@ da:
change_aspect_of_post_q: "Når jeg har lagt et indlæg op kan jeg så ændre det aspekt (de aspekter) der kan se det?"
contacts_know_aspect_a: "Nej. De kan ikke under nogen omstændigheder se aspektets navn."
contacts_know_aspect_q: "Ved mine kontakter hvilke aspekter jeg har placeret dem i?"
- contacts_visible_a: "Hvis du vælger denne indstilling så vil kontakter fra dette aspekt under dit billede på din profilside være i stand til at se, hvem der ellers er i aspektet. Det er bedst at vælge denne mulighed, hvis kontakterne alle kender hinanden, f.eks. hvis de alle er del af din familie eller af en fælles forening eller klub. De vil stadig ikke være i stand til at se hvad du har kaldt aspektet."
+ contacts_visible_a: "Hvis du vælger denne indstilling så vil kontakter fra dette aspekt under dit billede på din profilside være i stand til at se, hvem der ellers er i aspektet. (I øjeblikket er kun de af dine kontakter der er på samme pod som du vil kunne se fanen \"Kontakter\" på din profil.) Det er bedst at vælge denne mulighed, hvis kontakterne alle kender hinanden, f.eks. hvis de alle er del af din familie eller af en fælles forening eller klub. De vil stadig ikke være i stand til at se hvad du har kaldt aspektet."
contacts_visible_q: "Hvad betyder: \"gør kontakter i dette aspekt synlige for hinanden?\""
delete_aspect_a: "Tryk på \"Mine aspekter\" i venstre sidemenu i din strøm og tryk på blyants-ikonet ved det aspekt du vil slette, eller gå til din kontaktside og vælg det relevante aspekt. Klik på papirkurvs-ikonet øverst til højre på siden."
delete_aspect_q: "Hvordan sletter jeg et aspekt?"
@@ -378,9 +385,11 @@ da:
add_contact_roster_q: "Hvordan chatter jeg med nogen i Diaspora?"
contacts_page: "kontakt side"
title: "Chat"
+ community_guidelines: "Sociale retningslinier"
faq: "FAQ"
foundation_website: "Diaspora-stiftelsens hjemmeside"
getting_help:
+ get_support_a_discourse: "Søg efter eksisterende diskussioner vedrørende din forespørgsel, eller åbn en ny tråd på vores %{discourse} platform"
get_support_a_faq: "Læs vores %{faq} side på wikien"
get_support_a_hashtag: "Spørg i et offentlig indlæg på Diaspora og brug %{question} hashtagget"
get_support_a_irc: "Slut dig til os på %{irc} (live chat)"
@@ -410,7 +419,7 @@ da:
mentions:
how_to_mention_a: "Skriv \"@\" efterfulgt af deres navn. En rullemenu skulle herefter nemt lade dig vælge dem. Bemærk at det kun er muligt at nævne folk som du har tilføjet til et af dine aspekter."
how_to_mention_q: "Hvordan \"nævner\" jeg nogen når jeg laver et indlæg?"
- mention_in_comment_a: "Nej, ikke på nuværende tidspunkt"
+ mention_in_comment_a: "Siden version 0.7.0.0, ja! Du kan nævne en person i en kommentar på samme måde som du ville gøre det i et indlæg ved at skrive \"@\" og derefter begynde at skrive deres navn. Bemærk, at når du kommenterer et indlæg der ikke er offentligt kan du kun nævne brugere der allerede har interageret med indlægget."
mention_in_comment_q: "Kan jeg \"nævne\" nogen i en kommentar?"
see_mentions_a: "Ja. tryk på knappen \"Dine omtaler\" i venstre kolonne på din startside."
see_mentions_q: "Er der en måde at se de indlæg hvor jeg er blevet nævnt?"
@@ -431,7 +440,7 @@ da:
find_people_a: "Hvis du vil invitere dine venner til Diaspora, brug invitationslinket eller e-mail-linket i side-baren. Følg #tags for at finde andre som du deler interesser med, og tilføj dem hvis indlæg interesserer dig til et af dine aspekter. Sørg for at alle ved at du er ny ved at sætte tagget #newhere i et offentligt indlæg."
find_people_q: "Jeg har lige tilsluttet mig en pod, hvordan kan jeg finde folk at dele med?"
title: "Pods"
- use_search_box_a: "Hvis du kender deres fulde Diaspora-ID (f.eks brugernavn@podnavn.org), kan du finde dem ved at søge efter det. Hvis du er på samme pod kan du nøjes med at søge efter deres brugernavn. Et alternativ er at søge efter dem ved at søge på deres profilnavn (det navn, du ser på skærmen). Hvis en søgning ikke virker første gang, så prøv igen."
+ use_search_box_a: "Du kan søge efter personer ved at indtaste deres brugernavn eller deres Diaspora-navn (navnet, der vises på deres profil). Hvis ingen af disse metoder virker, skal du indtaste deres fulde Diaspora-ID (brugernavn@podname.org). Hvis din søgning ikke virker første gang, kan det skyldes netværksforsinkelse. Prøv igen."
use_search_box_q: "Hvordan bruger jeg søgefeltet til at finde bestemte personer?"
what_is_a_pod_a: "En pod er en server der kører Diaspora-softwaren og er forbundet til Diaspora-netværket. \"Pod\" er engelsk ord for en plantebælg og er således en metafor: En bælg indeholder frø på samme måde som en server indeholder brugerkonti. Der er mange forskellige pods. Du kan tilføje venner fra andre pods og kommunikere med dem. Så der er ingen grund til at oprette en profil på flere pods - en er nok. Du kan tænke på en Diaspora pod som du tænker på en e-mailudbyder: Der er offentlige pods, private pods og med en vis indsats kan du endda køre din egen."
what_is_a_pod_q: "Hvad er en pod?"
@@ -442,15 +451,12 @@ da:
character_limit_q: "Hvad er grænsen for hvor mange tegn der må være i et indlæg?"
embed_multimedia_a: "Du kan som regel bare indsætte URL-adressen (f.eks http://www.youtube.com/watch?v=nnnnnnnnnnn) i dit indlæg og så vil video eller lyd blive indlejret automatisk. Nogle af de sider, der understøttes er: YouTube, Vimeo, SoundCloud, Flickr og et par mere. Diaspora bruger oEmbed til denne funktion. Vi understøtter løbende nye medie-typer. Husk altid at skrive enkle, fulde links: ingen forkortede links, ingen operatorer efter grund-URLen - og giv det lidt tid, før du opdaterer siden for at se din forhåndsvisning."
embed_multimedia_q: "Hvordan kan jeg indlejre en video, lyd eller andet multimedieindhold i et indlæg?"
- format_text_a: "Ved at bruge et simplificeret system kaldet %{markdown}. Du kan finde en komplet introduktion til Markdown syntaks %{here}. Forhåndsvisning-knappen er virkelig praktisk her, da du kan se hvordan dit indlæg vil komme til at se ud inden du deler det."
+ format_text_a: "Diaspora bruger et forenklet system kaldet %{markdown}. Over indlægsteksten er der knapper, der gør det nemt at formatere din tekst. Hvis du vil formatere dit indlæg manuelt, kan du finde den fulde Markdown-syntaks %{here}. Forhåndsvisning fanen betyder, at du kan se, hvordan din besked vil se ud, før du deler den. Husk, at du ikke kan redigere, når først indlægget er blevet lagt ud, så brug previewen for at sikre, at det er perfekt, før du trykker på del!"
format_text_q: "Hvordan kan jeg formatere teksten i mine indlæg (fed, kursiv, osv.)?"
hide_posts_a: "Hvis du peger med musen på toppen af et indlæg vil et X dukke op til højre. Tryk på det for at skjule indlægget og fjerne notifikationer om det. Du kan stadig se indlægget hvis du besøger den person der lavede indlæggets profilside."
hide_posts_q: "Hvordan skjuler jeg et indlæg?"
- image_text: "Billedtekst"
- image_url: "Billed-URL"
- insert_images_a: "Klik på det lille kameraikon for at indsætte et billede. Du kan trykke flere gange og derved indsætte flere billeder, og du kan også vælge at uploade flere billeder på en gang."
- insert_images_comments_a1: "Man kan ikke uploade billeder til kommentarer, men den følgende Markdown-kode"
- insert_images_comments_a2: "kan bruges til at indsætte billeder fra internettet i kommentarer samt indlæg."
+ insert_images_a: "Hvis du vil medtage et billede gemt på din computer i dit indlæg, skal du klikke på ikonet med det lille kamera nederst på indtastningfeltet. Du kan også trække og slippe et billede eller flere billeder fra din computer til det ikon. Hvis du vil indsætte et billede fra internettet i dit indlæg, skal du klikke på billedknappen øverst på indtastningfeltet, som vil oprette Markdown-koden for dig."
+ insert_images_comments_a: "Du kan bruge Markdown til at indsætte et billede fra internettet i en kommentar, ligesom du gør i indlæg. Du kan dog ikke uploade billeder fra din computer direkte til kommentarer. Upload dem til en billed-hosting-tjeneste, og indsæt dem ved hjælp af billedknappen over send-knappen."
insert_images_comments_q: "Kan jeg indsætte billeder i kommentarer?"
insert_images_q: "Hvordan indsætter jeg et billede i et indlæg?"
post_location_a: "Tryk på knappenåls-ikonet ved siden af kameraet i feltet hvor du skriver dine indlæg. Det vil indsætte din placering fra OpenStreetMap. Du kan redigere din placering - måske ønsker du bare at vise hvilken by du er i og ikke hvilken gade."
@@ -459,7 +465,7 @@ da:
post_notification_q: "Hvordan sørger jeg for at få notifikationer, eller at stoppe med at få notifikationer, om et indlæg?"
post_poll_a: "Tryk på det ikon der ligner en graf for at lave en afstemning. Skriv et spørgsmål og mindst to mulige svar. Husk at gøre dit indløg offentligt hvis du vil have at alle skal kunne deltage i din afstemning."
post_poll_q: "Hvordan tilføjer jeg en afstemning til et indlæg?"
- post_report_a: "Tryk på advarselstrekanten i det øvre højre hjørne af indlægget for at anmelde det til din podmin. Skriv grunden til at du anmelder indlægget i dialog-boksen."
+ post_report_a: "Tryk på advarselstrekanten i det øvre højre hjørne af indlægget for at anmelde det til din podmin. Skriv grunden til at du anmelder indlægget i dialog-boksen. Du skal kun rapportere indlæg, der bryder vores %{community_guidelines} eller din pods servicevilkår, f.eks. indlæg med ulovligt indhold, verbale overgreb eller spam."
post_report_q: "Hvordan anmelder jeg et anstødeligt indlæg?"
size_of_images_a: "Nej. Billederne skaleres automatisk til at passe til strømmen. Markdown har ikke en kode til angivelse af størrelsen af et billede."
size_of_images_q: "Kan jeg tilpasse størrelsen på ​​billeder i indlæg eller kommentarer?"
@@ -479,19 +485,19 @@ da:
title: "Private indlæg"
who_sees_post_a: "Kun Diaspora-brugere der er logget ind, og som du har placeret i dette aspekt inden du skrev dit begrænsede indlæg kan se det."
who_sees_post_q: "Når jeg sender en besked til et aspekt (dvs. en privat indlæg), hvem kan så se det?"
- private_profiles:
- title: "Private profiler"
- whats_in_profile_a: "Din private profil indeholder biografi, placering, køn og fødselsdag. Det er de ting i den nederste del af profilredigeringssiden. Disse oplysninger er valgfri - det er op til dig om du vil udfylde dem. Indloggede brugere som du har føjet til dine aspekter er de eneste, der kan se din private profil. Når de besøger din profilside kan de også se de indlæg du skrevet til de aspekt(er) de er i og dine offentlige indlæg."
- whats_in_profile_q: "Hvad indeholder min private profil?"
- who_sees_profile_a: "Enhver bruger der er logged ind og som du deler med (en du har tilføjet til et aspekt). Folk der følger dig men som du ikke følger, vil dog kun kunne se din offentlige information."
- who_sees_profile_q: "Hvem kan se min private profil?"
- who_sees_updates_a: "Alle der er i et af dine aspekter kan se ændringer i din private profil. "
- who_sees_updates_q: "Hvem kan se når jeg opdaterer min private profil?"
+ profile:
+ title: "Profil"
+ what_do_tags_do_a: "De hjælper folk med at lære dig at kende. Dit profilbillede vises også på venstre side af disse tags strøm-sider sammen med andre der har dem i deres basis profil."
+ what_do_tags_do_q: "Hvad gør de tags der er i min basisprofil?"
+ whats_in_profile_a: "Din profil er opdelt i to dele: Din basis profil og din udvidede profil. Din basis profil indeholder dit navn, de fem tags, du valgte at beskrive dig selv og dit billede. Din udvidede profil indeholder din biografi, placering, køn og fødselsdag. Alle disse oplysninger er valgfri - det er op til dig, og du kan gøre denne profilinformation så identificerbar eller anonym som du vil. Din udvidede profil vises i den venstre kolonne på din profilside under dit profilbillede."
+ whats_in_profile_q: "Hvad er der i min profil?"
+ who_sees_profile_a: "Din basis profil (navn, profilbillede og #tags) er offentligt. Din udvidede profil er som standard privat, men du kan gøre det tilgængeligt for offentligheden, hvis du vil. Kun personer, du deler med (hvilket betyder, du har tilføjet dem til et af dine aspekter) kan se din udvidede profil, hvis du holder den privat. Andre mennesker vil kun se dine offentlige oplysninger. Eventuelle profiloplysninger du offentliggør, kan ses af alle der bruger internettet og kan indekseres af søgemaskiner"
+ who_sees_profile_q: "Hvem ser min profil?"
public_posts:
can_comment_reshare_like_a: "Enhver der er logget på Diaspora kan kommentere, videredele eller like dine offentlige indlæg."
can_comment_reshare_like_q: "Hvem kan kommentere, videredele eller like mine offentlige indlæg?"
deselect_aspect_posting_a: "Det påvirker ikke offentlige indlæg at fravælge aspekter. Indlægget vil stadig være offentligt, og vil stadig være synligt i strømmen hos alle dine kontakter. For at begrænse adgangen til specifikke aspekter, skal du vælge de aspekter du ønsker skal kunne se indlægget med aspekt-menuen under indlægget."
- deselect_aspect_posting_q: "Hvad sker der, når jeg fravælger et eller flere aspekter, når jeg laver et offentligt indlæg?"
+ deselect_aspect_posting_q: "Hvad sker der, når jeg fravælger et eller flere aspekter i den venstre kolonne, når jeg laver et offentligt indlæg?"
find_public_post_a: "Dine offentlige indlæg vises i strømmen hos alle der følger dig. Hvis du har inkluderet #tags i dine offentlige indlæg, vil enhver der følger disse tags kunne se dit indlæg i deres strøm. Hvert offentligt indlæg har også en specifik webadresse som alle kan se, også selvom de er ikke logget ind på Diaspora - dermed kan man linke til offentlige indlæg direkte fra Twitter, blogs osv. Offentlige indlæg kan også blive indekseret af søgemaskiner."
find_public_post_q: "Hvordan kan folk finde mine offentlige indlæg?"
see_comment_reshare_like_a: "Kommentarer, synes om og videredelinger af offentlige indlæg er også offentlige. Enhver der er logget på Diaspora og alle andre på internettet kan se hvad du skriver og kommenterer i et offentligt indlæg."
@@ -499,16 +505,6 @@ da:
title: "Offentlige indlæg"
who_sees_post_a: "Alle der bruger internettet vil kunne se dine offentlige indlæg, så vær sikker på at du virkelig ønsker at det skal være offentligt. Det er en fin måde at række hånden ud mod verden."
who_sees_post_q: "Når jeg laver et offentligt indlæg hvem kan så se det?"
- public_profiles:
- title: "Offentlige profiler"
- what_do_tags_do_a: "De hjælper folk til at få et indtryk af dig. Dit profilbillede vil også kunne ses i den venstre side af det specifikke tags side sammen med alle de andre der har dem i deres offentlige profil."
- what_do_tags_do_q: "Hvad bruges de tags jeg har skrevet på min personlige profil til?"
- whats_in_profile_a: "Din offentlige profil indeholder dit navn, de fem tags du valgte til at beskrive dig selv og dit portræt, hvis du altså har udfyldt disse felter. Al denne information er valgfri - det er helt op til dig hvad du ønsker at folk skal kunne se. Du kan gøre denne information lige så identificerbar eller anonym som du selv synes. Din profil vil også vise de offentlige indlæg du har lavet."
- whats_in_profile_q: "Hvad indeholder min offentlige profil?"
- who_sees_profile_a: "Alle Diaspora-brugere der er logget ind og hele resten af internettet kan se det. Hver profil har en direkte URL, så man kan linke direkte til siden også fra andre sites. Det kan også indekseres af søgemaskiner."
- who_sees_profile_q: "Hvem kan se min offentlige profil?"
- who_sees_updates_a: "Alle kan se ændringer hvis de besøger din profilside."
- who_sees_updates_q: "Hvem kan se når jeg opdaterer min offentlige profil?"
resharing_posts:
reshare_private_post_aspects_a: "Nej, det er ikke muligt at videredele et privat indlæg. Dette er for at respektere intentionen hos det oprindelige indlægs forfatter der jo havde valgt kun at dele indlægget med en begrænset gruppe."
reshare_private_post_aspects_q: "Kan jeg videredele et begrænset indlæg til udvalgte aspekter?"
@@ -527,7 +523,7 @@ da:
add_to_aspect_li7: "Amy vil blive vist under \"Deler kun med mig\" på Bens kontaktside."
add_to_aspect_li8: "Amy vil også kunne @nævne Ben i et indlæg."
add_to_aspect_q: "Hvad sker der, når jeg tilføjer en person til et af ​​mine aspekter, eller når nogen føjer mig til et af ​​deres aspekter?"
- list_not_sharing_a: "Nej, men du kan se om nogen deler med dig eller ej, ved at besøge deres profilside. Hvis de gør, vil knappen der viser det (eller de) aspekter du har placeret dem i være grøn. Hvis ikke er den grå."
+ list_not_sharing_a: "Nej, men du kan se, om nogen deler med dig ved at besøge deres profilside. Hvis de er, vil der være en grøn kryds ved siden af deres Diaspora-ID. Hvis ikke, vil der være en grå cirkel."
list_not_sharing_q: "Findes der en liste over folk som jeg har tilføjet til et af ​​mine aspekter, men som ikke har tilføjet mig til en af ​​deres?"
only_sharing_a: "Dette er brugere der har tilføjet dig til en af ​​deres aspekter, men som ikke (endnu) er i et af ​​dine aspekter. Med andre ord, de deler med dig, men du deler ikke med dem. Du kan tænke på det som nogen der følger med i hvad du laver. Hvis du føjer dem til et aspekt vil de blive vist under dette aspekt og ikke længere under \"deler kun med mig\". Se ovenfor."
only_sharing_q: "Hvem er de mennesker, der er anført i \"Deler kun med mig\" på min kontakt side?"
@@ -539,7 +535,7 @@ da:
tags:
filter_tags_a: "Dette er endnu ikke tilgængelig direkte via Diaspora, men der er blevet skrevet %{third_party_tools} som kan tilbyde dette."
filter_tags_q: "Hvordan kan jeg filtrere/fjerne tags fra min strøm?"
- followed_tags_a: "Når du har søgt efter et tag, kan du klikke på knappen øverst på tag-siden for at \"følge\" det tag. Det vil herefter blive vist i din liste over fulgte tags i den venstre menu. Hvis du klikker på en af ​​dine fulgte tags kommer du til det tags side, hvor du kan se de seneste indlæg der indeholder dette tag. Klik på #fulgte tags for at se en strøm med indlæg, der omfatter et eller flere af ​​dine fulgte tags."
+ followed_tags_a: "Når du har søgt efter et tag, kan du klikke på knappen øverst på tag-siden for at \"følge\" det tag. Det vil herefter blive vist i din liste over fulgte tags i den venstre menu. Hvis du klikker på en af ​​dine fulgte tags kommer du til det tags side, hvor du kan se de seneste indlæg der indeholder dette tag. Klik på #fulgte tags for at se en strøm med indlæg, der omfatter et eller flere af ​​dine fulgte tags. Indlæg indeholdende det pågældende tag vil også blive inkluderet i din hovedstrøm."
followed_tags_q: "Hvad er #Fulgte tags\" og hvordan kan jeg følge et tag?"
people_tag_page_a: "Det er folk der har skrevet det som et tag til at beskrive sig selv i deres offentlige profil."
people_tag_page_q: "Hvem er de mennesker der er anført på den venstre side af en tag-side?"
@@ -663,6 +659,7 @@ da:
mark_read: "Marker som læst"
mark_unread: "Marker som ulæst"
mentioned: "Omtalt i indlæg"
+ mentioned_in_comment: "Nævnt i kommentar"
no_notifications: "Du har endnu ikke fået nogen notifikationer."
notifications: "Notifikationer"
reshared: "Delt"
@@ -688,6 +685,12 @@ da:
one: "%{actors} har nævnt dig i et slettet indlæg."
other: "%{actors} har nævnt dig i et slettet indlæg."
zero: "%{actors} har nævnt dig i et slettet indlæg."
+ mentioned_in_comment:
+ one: "%{actors} har nævnt dig i en <a href=\"%{comment_path}\">kommentar</a> til dette indlæg: %{post_link}."
+ other: "%{actors} har nævnt dig i en <a href=\"%{comment_path}\">kommentar</a> til dette indlæg: %{post_link}."
+ mentioned_in_comment_deleted:
+ one: "%{actors} har nævnt dig i en slettet kommentar. "
+ other: "%{actors} har nævnt dig i en slettet kommentar. "
private_message:
few: "%{actors} har sendt dig en besked."
many: "%{actors} har sendt dig en besked."
@@ -797,7 +800,7 @@ da:
message: |-
Hej!
- Du er blevet inviteret af %{diaspora_id} til at deltage på Diaspora!
+ Du er blevet inviteret af %{user} til at deltage på Diaspora!
Tryk på dette link for at komme i gang:
@@ -805,6 +808,7 @@ da:
Eller tilføj %{diaspora_id} til dine kontakter hvis du allerede har en konto.
+
Kærlig hilsen
Diasporas email-robot!
@@ -821,6 +825,9 @@ da:
mentioned:
limited_post: "Du blev nævnt i et lukket indlæg."
subject: "%{name} har omtalt dig på Diaspora"
+ mentioned_in_comment:
+ limited_post: "Du er blevet nævnt i en kommentar i et lukket indlæg."
+ reply: "Se eller skriv et svar til denne samtale >"
private_message:
reply_to_or_view: "Besvar eller se denne samtale >"
subject: "Der er en ny privat meddelelse til dig"
@@ -1189,6 +1196,7 @@ da:
last_exported_at: "(sidst opdateret %{timestamp})"
liked: "... nogen synes om dit indlæg."
mentioned: "... du er nævnt i et indlæg."
+ mentioned_in_comment: "Du er blevet nævnt i en kommentar."
new_password: "Nyt adgangskode"
private_message: "... du har modtaget en privat besked."
receive_email_notifications: "Modtag en besked på e-mail når:"
diff --git a/config/locales/diaspora/de-CH.yml b/config/locales/diaspora/de-CH.yml
index 5b835e6c1..43355da0a 100644
--- a/config/locales/diaspora/de-CH.yml
+++ b/config/locales/diaspora/de-CH.yml
@@ -247,6 +247,20 @@ de-CH:
move_pods_q: "Wie chan i mis Konto uf en andere Pod verschiebe?"
title: "Konto- und Dateverwaltig"
aspects:
+ change_aspect_of_post_a: "Nei, aber du chasch emmer en neue Biitrag mache met em gliiche Inhalt ond zomene andere Aspekt henzuefüege."
+ change_aspect_of_post_q: "Wenn ich öppis posted ha, chann ich no d'Aspekt(e) wos chöne gseh ändere?"
+ contacts_know_aspect_a: "Nei. Si chönne de Name vom Aspekt onder kene Bedingige gseh"
+ contacts_know_aspect_q: "Wösse mini Kontökt i welne Aspekt mini Kontäkt send?"
+ contacts_visible_a: "When du die Option aktiviersch, denne chöne Kontäkt vo dem Aspekt gseh wer söscht no im gliiche Aspekt esch. Esch esch am beschte, wenn du die Option nor aktiviersch, wenn alli em Aspekt sech kenne. Zom Biispel, wenn de Aspekt zo emene Club oder enere Organisation ghört, wo du ou debii besch. Sie wärde trotzdem ned chönne gseh wie de Aspekt heisst."
+ contacts_visible_q: "Was heisst \"mach Kontäkt i dem Aspekt sechtbar förenand\"?"
+ delete_aspect_q: "Wie chan ich en Aspekt lösche?"
+ person_multiple_aspects_q: "Chan ich en Person zo mehrere Aspekt henzuefüege?"
+ post_multiple_aspects_q: "Chan ich Sache zo mehrere Aspekt gliichzitig henzuefüege?"
+ remove_notification_a: "Nei. Sie werdes ou ned erfahre wenn du si zo wiitere Aspekt henzuefüegsch, wenn du met ehne scho diini Inhält duesch teile."
+ remove_notification_q: "Wenn ich öpper vo eim oder mehrere Aspekte entferne, ehrfahrt die Person das?"
+ rename_aspect_q: "Wie duen ich en Aspekt ombenenne?"
+ restrict_posts_i_see_a: "Jo. Klick zerscht of \"Miini Aspekt\" eh de Siiteliischte ond denne klick einzelni Aspekt, om si abzwähle. Ahschlüssend wärde nor noh Biiträg vo Persone os de usgwählte Aspekte em Stream ahzeigt."
+ restrict_posts_i_see_q: "Chan ich d'Biiträg eh mim Stream of die vo bestemmte Aspekt beschränke?"
title: "Aspekt"
what_is_an_aspect_a: "Apekt sind e Möglichkeit dini diaspora*-Kontäkt z'gruppiere. Du chasch Aspekt nutze für Lüüt a dim Arbetsplatz, für dini Familie oder für dini Fründe."
what_is_an_aspect_q: "Was isch en Aspekt?"
@@ -274,8 +288,33 @@ de-CH:
title: "Tastaturchürzel"
markdown: "Markdown"
mentions:
+ how_to_mention_a: "Tipp s'ät(@) Zeiche ond fang ah ihre Name iizgeh. Es drop-down Menü sött erschiene zom dech eifacher en Person uszwähle loh. Due aber beachte, dass es nor möglich esch Lüt, wo du zo emene Aspekt henzuegfüegt hesch z'erwähne."
+ how_to_mention_q: "Wie duen ich öpper erwähne wenn ich en Biitrag mache?"
+ mention_in_comment_q: "Chan ich öpper emene Kommentar erwähne?"
+ see_mentions_a: "Jo, klick \"@Erwähnige\" eh de linke Spalte of dinere Startsiite."
+ see_mentions_q: "Isch es möglech die Biiträg ahzluege wo ich drinne erwähnt worde be?"
title: "Erwähnige"
what_is_a_mention_q: "Was isch en \"Erwähnig\"?"
+ pods:
+ find_people_a: "Wenn du dini Frönde wetsch ihlade ou zo Diaspora* z'cho, chasch du de Ihladigs Link oder de E-Mail Link eh de Siiteliischte benotze. Folg a #tags om anderi wo di gliiche interresse händ z'fende, ond die wo Sache veröffentleche wo dech interressiere chasch du zo dine Aspekt henzuefüege. Rüef us, dass du do neu besch (#newhere oder #neudo) emene öffentleche Biitrag. "
+ find_people_q: "Ich be grad amene Pod biitrete. Wie chan ich Lüüt fende met dene Ich cha teile?"
+ title: "Pods"
+ use_search_box_q: "Wie benotz ich d'suechliischte om bestemmti Lüt z'fende?"
+ what_is_a_pod_a: "En Pod esch en Server wo d'Diaspora* Software droffe louft ond wo met em Diaspora* Netzwärch verbonde esch. \"Pod\" esch en Metapher för Hölse vo Pflanze, wo mehreri Sahme enthalte, so wie de Server verschednigi Benotzerkonte enthaltet. Es get verschednigi Pods. Sie chönne Kontäkt vo andere Pods henzuefüege ond met ehne Kommuniziere. Es esch ned nötig, Konte of verschednige Pods z'erschtelle! En einzige Pod esch gnueg - So gseh chönne Si sech Pods wie en E-Mail ahbieter vorstelle. Es get öffentlechi Pods, privati Pods, und met es betzeli Ufwand chöne si sogar ehre eigene Betriebe."
+ what_is_a_pod_q: "Was esch en Pod?"
+ posts_and_posting:
+ character_limit_a: "65,535 Zeiche. Das send 65,395 meh Zeiche als du be Twitter benotze chasch! ;)"
+ character_limit_q: "Was eschs s'Zeiche Limit för Biiträg?"
+ embed_multimedia_a: "Du chasch meischtens eifach d'URL inekopiere (zb. https://www.youtube.com/watch?v=nnnnnnnnnnn ) ond s'Audio oder s'Video werd automatisch iibettet. Onderstötzti Siite send onder anderem: YouTube, Vimeo, SoundCloud, Flickr ond es paar meh. Diaspora* benotzt oEmbed för die Fonktion. Es chöme ständig neui Siite dezue. Bitte beacht, immer nor eifachi ond vollständigi Links z'benotze: Keini gchörtzti Links; Kei zuesätzlechi Optione henter de Basis-URL; Ond wart nachem poste en chliine Moment, bevor du d'Siite aktualisiersch, om d'Vorschau z'erhalte."
+ embed_multimedia_q: "Wie chan ich es Video, Audio oder anderi Multimediainhalt eh emene Biitrag iibette?"
+ format_text_q: "Wie chan ich Text eh mim Biitrag formatiere (fett, korsiv, osw.)?"
+ hide_posts_q: "Wie mer en Biitrag cha verstecke?"
+ insert_images_a: "Dröck s'chliine Kamera Icon om es Beld eh din Biitrag iizfüege. Dröck s'Kamera Icon nomohl om es anders Beld iizfüege, oder du chasch ou meheri Belder zom gliichzitig ufelade uswähle."
+ insert_images_comments_q: "Chan ich Belder zo Kommentär henzuefüege?"
+ insert_images_q: "Wie chan ich Belder en min biitrag iifüege?"
+ size_of_images_a: "Nei. D'Beldergrössi werd outomatisch ahpasst, so dass d'Belder eh Stream passe. Markdown bietet keh Code, om d'Grössi vo emene Beld ahzgeh."
+ size_of_images_q: "Chan ich d'grössi vo Belder eh Biiträg oder Kommentäär verändere?"
+ title: "Biiträg ond Biiträg mache"
third_party_tools: "Drittaawendige"
tutorial: "Aaleitig"
tutorials: "Aaleitige"
diff --git a/config/locales/diaspora/de.yml b/config/locales/diaspora/de.yml
index f08250021..bb517aeeb 100644
--- a/config/locales/diaspora/de.yml
+++ b/config/locales/diaspora/de.yml
@@ -90,7 +90,7 @@ de:
week: "Woche"
user_entry:
account_closed: "Konto wurde geschlossen."
- diaspora_handle: "diaspora*-Handle"
+ diaspora_handle: "diaspora* ID"
email: "E-Mail"
guid: "GUID"
id: "ID"
@@ -274,6 +274,13 @@ de:
heading: "Lesezeichen"
post_something: "Erstelle einen Beitrag in diaspora*"
cancel: "Abbrechen"
+ color_themes:
+ dark: "Dunkel"
+ dark_green: "Dunkelgrün"
+ egyptian_blue: "Ägyptisch Blau"
+ magenta: "Magenta"
+ original: "Ursprünglich grau"
+ original_white: "Ursprünglich weißer Hintergrund"
comments:
create:
error: "Konnte nicht kommentieren."
@@ -381,9 +388,11 @@ de:
add_contact_roster_q: "Wie kann ich auf diaspora* mit jemandem chatten?"
contacts_page: "Kontaktseite"
title: "Chat"
+ community_guidelines: "Community-Richtlinien"
faq: "FAQ"
foundation_website: "Webseite der diaspora*-Stiftung"
getting_help:
+ get_support_a_discourse: "Suche nach bestehenden Diskussionen im Bezug auf deine Frage oder eröffne ein neues Thema auf unserer %{discourse}-Plattform"
get_support_a_faq: "Lies unsere %{faq}-Seite im Wiki"
get_support_a_hashtag: "Stelle auf diaspora* in einem öffentlichen Beitrag eine Frage anhand des Hashtags %{question}."
get_support_a_irc: "Nehme am %{irc} (Live Chat) teil"
@@ -413,7 +422,7 @@ de:
mentions:
how_to_mention_a: "Tippe das „@“-Zeichen und beginne, den zu erwähnenden Namen einzugeben. Ein Dropdown-Menü sollte erscheinen, um das Einfügen zu erleichtern. Beachte, dass du nur Leute erwähnen kannst, die du zu einem deiner Aspekte hinzugefügt hast."
how_to_mention_q: "Wie erwähne ich jemand in einem Beitrag?"
- mention_in_comment_a: "Nein, momentan nicht."
+ mention_in_comment_a: "Seit Version 0.7.0.0, ja! Du kannst jemanden in einem Kommentar genau so erwähnen, wie du es in einem Beitrag tun würdest, indem du „@“ eingibst und dann anfängst den Namen einzugeben. Wohlgemerkt kannst du, wenn du einen nicht öffentlichen Beitrag kommentierst, nur Benutzer erwähnen, die schon mit dem Beitrag interagiert haben."
mention_in_comment_q: "Kann ich in den Kommentaren jemanden erwähnen?"
see_mentions_a: "Ja, klicke dazu in der linken Spalte deiner Startseite auf „@Erwähnungen“."
see_mentions_q: "Gibt es eine Möglichkeit, Beiträge zu finden, in denen ich erwähnt wurde?"
@@ -449,11 +458,8 @@ de:
format_text_q: "Wie kann ich einen Beitrag formatieren (Fett, kursiv, etc.)?"
hide_posts_a: "Wenn du deinen Mauszeiger über einem Beitrag positionierst, erscheint rechts ein kleines ×. Klicke darauf, um den Beitrag zu verstecken und die Benachrichtigungen zu ihm zu deaktivieren. Du kannst den Beitrag weiterhin auf der Profilseite der Person betrachten, die ihn gepostet hat."
hide_posts_q: "Wie blende ich einen Beitrag aus?"
- image_text: "Bildtext"
- image_url: "Bildlink"
insert_images_a: "Klicke auf das kleine Kamera-Symbol, um ein Foto zu einem Beitrag hinzuzufügen. Klicke erneut darauf, um weitere Fotos hinzuzufügen, oder wähle mehrere Fotos aus, um sie alle auf einmal hinzuzufügen."
- insert_images_comments_a1: "Du kannst Bilder nicht in Kommentare hochladen, aber der folgende Markdown-Code"
- insert_images_comments_a2: "kann sowohl in Kommentaren, als auch in Beiträgen, dazu benutzt werden, Bilder aus dem Internet einzufügen."
+ insert_images_comments_a: "Du kannst Markdown verwenden, um ein Bild aus dem Internet in einen Kommentar einzufügen, genau wie in Beiträgen. Du kannst allerdings keine Bilder von deinem Computer direkt in Kommentare hochladen. Lade sie auf einen Bilder-Hosting-Dienst hoch und füge sie dann mittels der Bild-Schaltfläche über dem Eingabefeld ein."
insert_images_comments_q: "Kann ich Bilder in Kommentare einfügen?"
insert_images_q: "Wie füge ich einem Beitrag Fotos hinzu?"
post_location_a: "Klicke auf das Stecknadelsymbol neben der Kamera im Eingabefeld für Veröffentlichungen. Das wird deine Position von OpenStreetMap einfügen. Du kannst deine Position bearbeiten – vielleicht möchtest du nur die Stadt, in der du dich befindest, einbinden, und nicht die genaue Adresse."
@@ -482,14 +488,14 @@ de:
title: "Private Beiträge"
who_sees_post_a: "Nur eingeloggte diaspora*-Nutzer, welche du vorher diesem privaten Aspekt zugeordnet hast, können den Beitrag sehen."
who_sees_post_q: "Wenn ich einen Beitrag in einen Aspekt schreibe (privat), wer kann ihn sehen?"
- private_profiles:
- title: "Private Profile"
- whats_in_profile_a: "Deine Beschreibung, dein Ort, Geschlecht und Geburtstag. Das sind die Dinge aus dem unteren Bereich der Profileinstellungen. Alle diese Informationen sind freiwillig – Du entscheidest, ob du sie preisgibst. Angemeldete Benutzer, aus deinen Aspekten, sind die Einzigen, die dein privates Profil sehen können. Sie werden auf deiner Profilseite außerdem neben deinen öffentlichen Beiträgen auch private Beiträge von dir sehen können, die an Aspekte gerichtet sind, in denen sie sich befinden."
- whats_in_profile_q: "Was ist in meinem privaten Profil zu sehen?"
- who_sees_profile_a: "Jeder angemeldete Benutzer, mit dem du teilst (den du zu einem deiner Aspekte hinzugefügt hast). Leute, die dir folgen, denen du aber nicht folgst, werden nur deine öffentlichen Informationen sehen."
- who_sees_profile_q: "Wer kann mein privates Profil sehen?"
- who_sees_updates_a: "Jeder deiner Kontakte, der sich in deinen Aspekten befindet, sieht Veränderungen in deinem privaten Profil. "
- who_sees_updates_q: "Wer sieht Neuerungen auf meinem privaten Profil?"
+ profile:
+ title: "Profil"
+ what_do_tags_do_a: "Sie helfen Leuten, dich kennenzulernen. Außerdem wird dein Profilbild auf der linken Seite der Stream-Seiten dieser Tags angezeigt, zusammen mit allen anderen, die sie in ihrem grundlegenden Profil haben."
+ what_do_tags_do_q: "Was tun die Tags in meinem grundlegenden Profil?"
+ whats_in_profile_a: "Dein Profil besteht aus zwei Teilen: deinem grundlegenden Profil und deinem erweiterten Profil. Dein grundlegendes Profil enthält deinen Namen, die fünf Tags, die du ausgesucht hast um dich zu beschreiben, und dein Foto. Dein erweitertes Profil enthält deine Beschreibung, Ort, Geschlecht und Geburtstag. Diese Informationen sind alle freiwillig – es hängt von dir ab, ob du sie angibst, und du kannst diese Profilinformationen so identifizierbar oder anonym gestalten, wie du möchtest. Dein erweitertes Profil wird in der linken Spalte deiner Profilseite, unter deinem Profilbild, angezeigt."
+ whats_in_profile_q: "Was ist in meinem Profil?"
+ who_sees_profile_a: "Dein grundlegendes Profil (Name, Profilbild und #Tags) ist öffentlich. Dein erweitertes Profil ist standardmäßig privat, aber du kannst es komplett öffentlich zugänglich machen, wenn du möchtest. Nur Leute, mit denen du teilst (das heißt du hast sie zu einem deiner Aspekte hinzugefügt), können dein erweitertes Profil sehen, wenn du es privat hältst. Andere Leute werden nur deine öffentlichen Informationen sehen. Jede Profilinformation, die du öffentlich machst, kann von jedem im Internet gesehen und von Suchmaschinen indexiert werden"
+ who_sees_profile_q: "Wer sieht mein Profil?"
public_posts:
can_comment_reshare_like_a: "Jeder angemeldete diaspora*-Nutzer kann öffentliche Beiträge weitersagen, kommentieren, beziehungsweise „Gefällt mir“ drücken."
can_comment_reshare_like_q: "Wer kann meinen öffentlichen Beitrag kommentieren, weitersagen oder bei ihm auf „Gefällt mir“ drücken?"
@@ -502,16 +508,6 @@ de:
title: "Öffentliche Beiträge"
who_sees_post_a: "Jeder, der das Internet nutzt, kann öffentliche Beiträge sehen. Sei also vorsichtig, wenn du etwas öffentlich schreibst. Es ist aber auch eine tolle Möglichkeit, um die Welt da draußen zu erreichen."
who_sees_post_q: "Wer kann öffentliche Beiträge sehen?"
- public_profiles:
- title: "Öffentliche Profile"
- what_do_tags_do_a: "Sie helfen Leuten, dich besser kennen zu lernen. Außerdem wird dein Profilbild auf der linken Seite der entsprechenden Tag-Seiten erscheinen, zusammen mit denen Anderer, die sie zu ihrem öffentlichen Profil hinzugefügt haben."
- what_do_tags_do_q: "Wozu sind die Tags in meinem öffentlichen Profil?"
- whats_in_profile_a: "Dein Name, die fünf Tags, die du gewählt hast, um dich selbst zu beschreiben und dein Profilbild. Das sind die Sachen im oberen Bereich der Profileinstellungen. Du kannst diese Informationen so spezifisch oder anonym gestalten, wie du willst. Auf deiner Profilseite sind ebenfalls all deine öffentlichen Beiträge zu sehen."
- whats_in_profile_q: "Was steht in meinem öffentlichen Profil?"
- who_sees_profile_a: "Jeder angemeldete diaspora*-Nutzer, aber auch alle Anderen, können es sehen. Jedes Profil besitzt eine eindeutige URL, sodass es von außerhalb verlinkt werden kann. Außerdem kann es von Suchmaschinen indexiert werden."
- who_sees_profile_q: "Wer sieht mein öffentliches Profil?"
- who_sees_updates_a: "Jeder, der dein Profil besucht."
- who_sees_updates_q: "Wer sieht Änderungen in meinem öffentlichen Profil?"
resharing_posts:
reshare_private_post_aspects_a: "Nein, es ist nicht möglich, einen privaten Beitrag weiterzusagen. Dies ist so, um die Absichten des Originalautors zu respektieren, welcher nur mit einer bestimmten Gruppe von Leuten teilen wollte."
reshare_private_post_aspects_q: "Kann ich einen privaten Beitrag für bestimmte Aspekte weitersagen?"
@@ -665,7 +661,8 @@ de:
mark_all_shown_as_read: "Alle angezeigten als gelesen markieren"
mark_read: "Als gelesen markieren"
mark_unread: "als ungelesen markieren"
- mentioned: "Erwähnt"
+ mentioned: "In Beitrag erwähnt"
+ mentioned_in_comment: "In Kommentar erwähnt"
no_notifications: "Du hast noch keine Benachrichtigungen."
notifications: "Benachrichtigungen"
reshared: "Weitergesagt"
@@ -686,11 +683,15 @@ de:
mentioned:
one: "%{actors} hat dich im Beitrag %{post_link} erwähnt."
other: "%{actors} haben dich im Beitrag %{post_link} erwähnt."
- zero: "%{actors} haben dich im Beitrag %{post_link} erwähnt."
mentioned_deleted:
one: "%{actors} hat dich in einem gelöschten Beitrag erwähnt."
other: "%{actors} haben dich in einem gelöschten Beitrag erwähnt."
- zero: "%{actors} haben dich in einem gelöschten Beitrag erwähnt."
+ mentioned_in_comment:
+ one: "%{actors} hat dich in einem <a href='%{comment_path}'>Kommentar</a> zum Beitrag %{post_link} erwähnt."
+ other: "%{actors} haben dich in einem <a href='%{comment_path}'>Kommentar</a> zum Beitrag %{post_link} erwähnt."
+ mentioned_in_comment_deleted:
+ one: "%{actors} hat dich in einem gelöschten Kommentar erwähnt."
+ other: "%{actors} haben dich in einem gelöschten Kommentar erwähnt."
private_message:
few: "%{actors} haben dir eine Nachricht gesendet."
many: "%{actors} haben dir eine Nachricht gesendet."
@@ -799,18 +800,20 @@ de:
message: |-
Hallo!
- Du wurdest von %{diaspora_id} eingeladen, diaspora* beizutreten!
+ Du wurdest von %{user} eingeladen, diaspora* beizutreten!
- Klicke auf folgenden Link, um loszulegen.
+ Klicke auf folgenden Link, um loszulegen
[%{invite_url}][1]
- Falls du bereits ein Konto besitzt, kannst du %{diaspora_id} zu deinen Kontakten hinzufügen.
+ Oder du kannst %{diaspora_id} zu deinen Kontakten hinzufügen, falls du bereits ein Konto besitzt.
- Alles Liebe
- der diaspora*-E-Mail-Automat
- P.S. Nur für den Fall, dass du (noch) nicht weißt, was diaspora* ist: [Hier][2] erklären wir es dir.
+ Alles Liebe,
+
+ Der diaspora* E-Mail-Roboter!
+
+ P.S.: Nur für den Fall, dass du (noch) nicht weißt, was diaspora* ist: [Hier][2] ist die Antwort.
[1]: %{invite_url}
[2]: %{diasporafoundation_url}
@@ -822,6 +825,9 @@ de:
mentioned:
limited_post: "Du wurdest in einem begrenzten Beitrag erwähnt."
subject: "%{name} hat dich auf diaspora* erwähnt"
+ mentioned_in_comment:
+ limited_post: "Du wurdest in einem Kommentar zu einem begrenzten Beitrag erwähnt."
+ reply: "Auf diese Unterhaltung antworten oder sie ansehen >"
private_message:
reply_to_or_view: "Antworte oder sieh dir diese Unterhaltung an >"
subject: "Neue private Nachricht"
@@ -1049,7 +1055,7 @@ de:
control_your_audience: "Kontrolliere deine Zielgruppe"
logged_in: "Eingeloggt in %{service}"
manage: "Verbundene Dienste verwalten"
- new_user_welcome_message: "Benutze #Hashtags, um deine Beiträge einzuordnen und Leute zu finden, die deine Interessen teilen. Benenne tolle Leute mit @Mentions"
+ new_user_welcome_message: "Benutze #Hashtags, um deine Beiträge einzuordnen und Leute zu finden, die deine Interessen teilen. Benenne tolle Leute mit @Erwähnungen"
outside: "Öffentliche Nachrichten werden für andere außerhalb von diaspora* sichtbar sein."
share: "Teilen"
title: "Verbundene Dienste verwalten"
@@ -1191,6 +1197,7 @@ de:
last_exported_at: "(Zuletzt aktualisiert: %{timestamp})"
liked: "jemandem dein Beitrag gefällt"
mentioned: "du in einem Beitrag erwähnt wirst"
+ mentioned_in_comment: "du in einem Kommentar erwähnt wirst"
new_password: "Neues Kennwort"
private_message: "du eine private Nachricht erhältst"
receive_email_notifications: "E-Mail-Benachrichtigungen empfangen, wenn …"
diff --git a/config/locales/diaspora/de_formal.yml b/config/locales/diaspora/de_formal.yml
index 3c7b6a33a..04d0bb96e 100644
--- a/config/locales/diaspora/de_formal.yml
+++ b/config/locales/diaspora/de_formal.yml
@@ -222,7 +222,7 @@ de_formal:
donate: "Spenden"
donate_liberapay: "An liberapay spenden"
help:
- any_problem: "Sie sind auf ein Problem gestoßen?"
+ any_problem: "Problem entdeckt?"
contact_podmin: "Kontaktieren Sie den Administrator Ihres Pods!"
do_you: "Haben Sie:"
feature_suggestion: "… einen %{link} Vorschlag?"
@@ -274,6 +274,13 @@ de_formal:
heading: "Lesezeichen"
post_something: "Erstellen Sie einen Beitrag in diaspora*"
cancel: "Abbrechen"
+ color_themes:
+ dark: "Dunkel"
+ dark_green: "Dunkelgrün"
+ egyptian_blue: "Ägyptisch Blau"
+ magenta: "Magenta"
+ original: "Ursprünglich grau"
+ original_white: "Ursprünglich weißer Hintergrund"
comments:
create:
error: "Konnte nicht kommentieren."
@@ -381,9 +388,11 @@ de_formal:
add_contact_roster_q: "Wie kann ich auf diaspora* mit jemandem chatten?"
contacts_page: "Kontaktseite"
title: "Chat"
+ community_guidelines: "Community-Richtlinien"
faq: "FAQ"
foundation_website: "Webseite der diaspora*-Stiftung"
getting_help:
+ get_support_a_discourse: "Suchen Sie nach bestehenden Diskussionen im Bezug auf Ihre Frage oder eröffnen Sie ein neues Thema auf unserer %{discourse}-Plattform"
get_support_a_faq: "Lesen Sie die %{faq}-Seite im Wiki"
get_support_a_hashtag: "Fragen Sie in einem öffentlichen Beitrag auf diaspora* mit dem Hashtag %{question}"
get_support_a_irc: "Nehmen Sie am %{irc} (Live-Chat) teil"
@@ -413,7 +422,7 @@ de_formal:
mentions:
how_to_mention_a: "Tippen Sie das „@”-Zeichen und beginnen Sie seinen Namen einzugeben. Ein Dropdown-Menü sollte erscheinen, um das Einfügen zu erleichtern. Beachten Sie, dass Sie nur Leute erwähnen können, die Sie zu einem Ihrer Aspekte hinzugefügt haben."
how_to_mention_q: "Wie erwähne ich jemanden in einem Beitrag?"
- mention_in_comment_a: "Nein, momentan nicht."
+ mention_in_comment_a: "Seit Version 0.7.0.0, ja! Sie können jemanden in einem Kommentar genau so erwähnen, wie Sie es in einem Beitrag tun würden, indem Sie „@“ eingeben und dann anfangen den Namen einzugeben. Wohlgemerkt können Sie, wenn Sie einen nicht öffentlichen Beitrag kommentieren, nur Benutzer erwähnen, die bereits mit dem Beitrag interagiert haben."
mention_in_comment_q: "Kann ich in den Kommentaren jemanden erwähnen?"
see_mentions_a: "Ja, klicken Sie dazu in der linken Spalte Ihrer Startseite auf „Erwähnungen”."
see_mentions_q: "Gibt es eine Möglichkeit, Beiträge zu finden, in denen ich erwähnt wurde?"
@@ -449,11 +458,8 @@ de_formal:
format_text_q: "Wie kann ich einen Beitrag formatieren (Fett, kursiv, etc.)?"
hide_posts_a: "Wenn Sie Ihren Mauszeiger über einem Beitrag positionieren, erscheint rechts ein kleines ×. Klicken Sie darauf, um den Beitrag zu verstecken und die Benachrichtigungen zu ihm zu deaktivieren. Sie können den Beitrag weiterhin auf der Profilseite der Person betrachten, die ihn gepostet hat."
hide_posts_q: "Wie blende ich einen Beitrag aus?"
- image_text: "Bildtext"
- image_url: "Bild-URL"
insert_images_a: "Klicken Sie auf das kleine Kamera-Symbol, um ein Foto zu einem Beitrag hinzuzufügen. Klicken Sie erneut darauf, um weitere Fotos hinzuzufügen, oder wählen Sie mehrere Fotos aus, um sie alle auf einmal hinzuzufügen."
- insert_images_comments_a1: "Sie können in Kommentaren keine Bilder hochladen, aber der folgende Markdown-Code"
- insert_images_comments_a2: "kann sowohl in Kommentaren, als auch in Beiträgen, dazu benutzt werden, Bilder aus dem Internet einzufügen."
+ insert_images_comments_a: "Sie können Markdown verwenden, um ein Bild aus dem Internet in einen Kommentar einzufügen, genau wie in Beiträgen. Sie können allerdings keine Bilder von Ihrem Computer direkt in Kommentare hochladen. Laden Sie sie auf einen Bilder-Hosting-Dienst hoch und fügen Sie sie dann mittels der Bild-Schaltfläche über dem Eingabefeld ein."
insert_images_comments_q: "Kann ich Bilder in Kommentare einfügen?"
insert_images_q: "Wie füge ich zu einem Beitrag Fotos hinzu?"
post_location_a: "Klicken Sie auf das Stecknadelsymbol neben der Kamera im Eingabefeld für Veröffentlichungen. Dies wird Ihre Position von OpenStreetMap einfügen. Sie können Ihre Position bearbeiten – möglicherweise möchten Sie nur die Stadt, in der Sie sich befinden, einbinden, und nicht die genaue Adresse."
@@ -482,14 +488,14 @@ de_formal:
title: "Private Beiträge"
who_sees_post_a: "Nur eingeloggte diaspora*-Nutzer, welche Sie in bereits vor dem Verfassen des privaten Beitrags zu dem Aspekt hinzugefügt hatten, können den Beitrag sehen."
who_sees_post_q: "Wenn ich einen Beitrag in einen Aspekt schreibe (privat), wer kann ihn sehen?"
- private_profiles:
- title: "Private Profile"
- whats_in_profile_a: "Ihr privates Profil enthält Ihre Beschreibung, Ihren Ort, Ihr Geschlecht und Ihren Geburtstag, falls Sie diese Felder ausgefüllt haben. Alle diese Informationen sind freiwillig – Sie entscheiden, ob Sie sie preisgeben. Angemeldete Benutzer, die sich in einem Ihrer Aspekte befinden, sind die Einzigen, die Ihr privates Profil sehen können. Sie werden auf Ihrer Profilseite außerdem neben Ihren öffentlichen Beiträgen auch private Beiträge von Ihnen sehen können, die an Aspekte gerichtet sind, in denen sie sich befinden."
- whats_in_profile_q: "Was ist in meinem privaten Profil?"
- who_sees_profile_a: "Jeder angemeldete Benutzer, mit dem Sie teilen (den Sie zu einem Ihrer Aspekte hinzugefügt haben). Leute, die Ihnen folgen, denen Sie aber nicht folgen, werden nur Ihre öffentlichen Informationen sehen."
- who_sees_profile_q: "Wer kann mein privates Profil sehen?"
- who_sees_updates_a: "Jeder Ihrer Kontakte sieht Veränderungen in Ihrem privaten Profil. "
- who_sees_updates_q: "Wer sieht Neuerungen auf meinem privaten Profil?"
+ profile:
+ title: "Profil"
+ what_do_tags_do_a: "Sie helfen Leuten, Sie kennenzulernen. Außerdem wird Ihr Profilbild auf der linken Seite der Stream-Seiten dieser Tags angezeigt, zusammen mit allen anderen, die sie in ihrem grundlegenden Profil haben."
+ what_do_tags_do_q: "Was tun die Tags in meinem grundlegenden Profil?"
+ whats_in_profile_a: "Ihr Profil besteht aus zwei Teilen: Ihrem grundlegenden Profil und Ihrem erweiterten Profil. Ihr grundlegendes Profil enthält Ihren Namen, die fünf Tags, die Sie ausgesucht haben um sich zu beschreiben, und Ihr Foto. Ihr erweitertes Profil enthält Ihre Beschreibung, Ort, Geschlecht und Geburtstag. Diese Informationen sind alle freiwillig – es obliegt Ihnen, ob Sie sie angeben, und Sie können diese Profilinformationen so identifizierbar oder anonym gestalten, wie Sie möchten. Ihr erweitertes Profil wird in der linken Spalte Ihrer Profilseite, unter Ihrem Profilbild, angezeigt."
+ whats_in_profile_q: "Was ist in meinem Profil?"
+ who_sees_profile_a: "Ihr grundlegendes Profil (Name, Profilbild und #Tags) ist öffentlich. Ihr erweitertes Profil ist standardmäßig privat, aber Sie können es komplett öffentlich zugänglich machen, wenn Sie möchten. Nur Leute, mit denen Sie teilen (das heißt Sie haben sie zu einem Ihrer Aspekte hinzugefügt), können Ihr erweitertes Profil sehen, wenn Sie es privat halten. Andere Leute werden nur Ihre öffentlichen Informationen sehen. Jede Profilinformation, die Sie öffentlich machen, kann von jedem im Internet gesehen und von Suchmaschinen indexiert werden"
+ who_sees_profile_q: "Wer sieht mein Profil?"
public_posts:
can_comment_reshare_like_a: "Jeder angemeldete diaspora*-Nutzer kann öffentliche Beiträge weitersagen, kommentieren, beziehungsweise „Gefällt mir“ drücken."
can_comment_reshare_like_q: "Wer kann meinen öffentlichen Beitrag weitersagen, kommentieren oder bei ihm „Gefällt mir“ drücken?"
@@ -502,16 +508,6 @@ de_formal:
title: "Öffentliche Beiträge"
who_sees_post_a: "Potenziell kann jeder, der das Internet nutzt, öffentliche Beiträge sehen, also seien Sie sich sicher, wenn Sie einen Beitrag öffentlich machen. Es ist aber auch eine tolle Möglichkeit, um die Welt da draußen zu erreichen."
who_sees_post_q: "Wer kann öffentliche Beiträge sehen?"
- public_profiles:
- title: "Öffentliche Profile"
- what_do_tags_do_a: "Sie helfen Leuten, Sie besser kennen zu lernen. Außerdem wird Ihr Profilbild auf der linken Seite der entsprechenden Tag-Seiten erscheinen, zusammen mit denen Anderer, die sie zu ihrem öffentlichen Profil hinzugefügt haben."
- what_do_tags_do_q: "Wofür sind die Tags in meinem öffentlichen Profil?"
- whats_in_profile_a: "Ihr öffentliches Profil enthält Ihren Namen, die fünf Tags, die Sie gewählt haben, um sich selbst zu beschreiben, und Ihr Profilbild, falls Sie diese Felder ausgefüllt haben. Alle diese Informationen sind freiwillig – Sie entscheiden, ob Sie sie preisgeben. Sie können diese Informationen so spezifisch oder anonym gestalten, wie Sie wollen. Auf Ihrer Profilseite sind außerdem all Ihre öffentlichen Beiträge zu sehen."
- whats_in_profile_q: "Was steht in meinem öffentlichen Profil?"
- who_sees_profile_a: "Jeder angemeldete diaspora*-Nutzer, aber auch alle Anderen, können es sehen. Jedes Profil besitzt eine eindeutige URL, sodass es von außerhalb verlinkt werden kann. Außerdem kann es von Suchmaschinen indexiert werden."
- who_sees_profile_q: "Wer sieht mein öffentliches Profil?"
- who_sees_updates_a: "Jeder, der Ihr Profil besucht."
- who_sees_updates_q: "Wer sieht Änderungen in meinem öffentlichen Profil?"
resharing_posts:
reshare_private_post_aspects_a: "Nein, es ist nicht möglich, private Beiträge weiterzusagen. Dies dient dazu, die Absichten des Originalautors zu respektieren, welcher den Beitrag nur mit einer bestimmten Gruppe von Leuten geteilt hat."
reshare_private_post_aspects_q: "Kann ich einen privaten Beitrag an ausgewählte Aspekte weitersagen?"
@@ -661,11 +657,12 @@ de_formal:
zero: "und niemand sonst"
comment_on_post: "Einen Beitrag Kommentiert"
liked: "Gefällt"
- mark_all_as_read: "Markiere alle als gelesen"
+ mark_all_as_read: "Alle als gelesen markieren"
mark_all_shown_as_read: "Alle angezeigten als gelesen markieren"
mark_read: "Als gelesen markieren"
mark_unread: "als ungelesen markieren"
mentioned: "Erwähnt"
+ mentioned_in_comment: "In Kommentar erwähnt"
no_notifications: "Sie haben noch keine Benachrichtigungen."
notifications: "Benachrichtigungen"
reshared: "Weitergesagt"
@@ -691,6 +688,12 @@ de_formal:
one: "%{actors} hat Sie in einem gelöschten Beitrag erwähnt."
other: "%{actors} haben Sie in einem gelöschten Beitrag erwähnt."
zero: "%{actors} haben Sie in einem gelöschten Beitrag erwähnt."
+ mentioned_in_comment:
+ one: "%{actors} hat Sie in einem <a href='%{comment_path}'>Kommentar</a> zum Beitrag %{post_link} erwähnt."
+ other: "%{actors} haben Sie in einem <a href='%{comment_path}'>Kommentar</a> zum Beitrag %{post_link} erwähnt."
+ mentioned_in_comment_deleted:
+ one: "%{actors} hat Sie in einem gelöschten Kommentar erwähnt."
+ other: "%{actors} haben Sie in einem gelöschten Beitrag erwähnt."
private_message:
few: "%{actors} haben Ihnen eine Nachricht gesendet."
many: "%{actors} haben Ihnen eine Nachricht gesendet."
@@ -820,6 +823,9 @@ de_formal:
mentioned:
limited_post: "Sie wurden in einem begrenzten Beitrag erwähnt."
subject: "%{name} hat Sie auf diaspora* erwähnt"
+ mentioned_in_comment:
+ limited_post: "Sie wurden in einem Kommentar zu einem begrenzten Beitrag erwähnt."
+ reply: "Auf diese Unterhaltung antworten oder sie ansehen >"
private_message:
reply_to_or_view: "Antworten Sie oder sehen Sie sich diese Unterhaltung an >"
subject: "Es gibt eine neue private Nachricht für Sie"
@@ -1042,7 +1048,7 @@ de_formal:
control_your_audience: "Kontrollieren Sie Ihre Zielgruppe"
logged_in: "Bei %{service} angemeldet"
manage: "Verbundene Dienste verwalten"
- new_user_welcome_message: "Benutzen Sie #Hashtags um Ihre Beiträge einzuordnen und Leute zu finden, die Ihre Interessen teilen. Benennen Sie tolle Leute mit @Erwähnungen"
+ new_user_welcome_message: "Benutzen Sie #Hashtags, um Ihre Beiträge einzuordnen und um Leute zu finden, die Ihre Interessen teilen. Machen Sie mit @Erwähnungen auf interessante Leute aufmerksam"
outside: "Öffentliche Nachrichten werden für andere außerhalb von diaspora* sichtbar sein."
share: "Teilen"
title: "Verbundene Dienste verwalten"
@@ -1182,8 +1188,9 @@ de_formal:
export_photos_in_progress: "Ihre Fotos werden derzeit verarbeitet. Bitte sehen Sie in wenigen Augenblicken erneut nach."
following: "Teilen-Einstellungen"
last_exported_at: "(Zuletzt aktualisiert am %{timestamp})"
- liked: "wenn jemandem Ihr Beitrag gefällt"
+ liked: "jemandem Ihr Beitrag gefällt"
mentioned: "Sie in einem Beitrag erwähnt werden"
+ mentioned_in_comment: "Sie in einem Kommentar erwähnt werden"
new_password: "Neues Passwort"
private_message: "Sie eine private Nachricht erhalten"
receive_email_notifications: "E-Mail-Benachrichtigungen empfangen, wenn:"
diff --git a/config/locales/diaspora/el.yml b/config/locales/diaspora/el.yml
index 4b26f54e7..fbf736ba2 100644
--- a/config/locales/diaspora/el.yml
+++ b/config/locales/diaspora/el.yml
@@ -258,12 +258,9 @@ el:
pods:
use_search_box_q: "Πώς μπορώ να χρησιμοποιήσω το πλαίσιο αναζήτησης για να βρω συγκεκριμένα άτομα;"
posts_and_posting:
- image_text: "κείμενο εικόνας"
insert_images_q: "Πώς μπορώ να εισάγω εικόνες στις αναρτήσεις;"
private_posts:
title: "Ιδιωτικές αναρτήσεις"
- private_profiles:
- title: "Ιδιωτικά προφίλ"
third_party_tools: "Εργαλεία τρίτων"
title_header: "Βοήθεια"
tutorial: "οδηγός"
diff --git a/config/locales/diaspora/en.yml b/config/locales/diaspora/en.yml
index be2a06f99..cb98753f8 100644
--- a/config/locales/diaspora/en.yml
+++ b/config/locales/diaspora/en.yml
@@ -240,6 +240,14 @@ en:
post_something: "Post to diaspora*"
explanation: "Post to diaspora* from anywhere by bookmarking this link => %{link}."
+ color_themes:
+ dark: "Dark"
+ dark_green: "Dark green"
+ egyptian_blue: "Egyptian blue"
+ magenta: "Magenta"
+ original: "Original gray"
+ original_white: "Original white background"
+
comments:
create:
error: "Failed to comment."
@@ -311,6 +319,7 @@ en:
foundation_website: "diaspora* foundation website"
third_party_tools: "Third-party tools"
getting_started_tutorial: "”Getting started” tutorial series"
+ community_guidelines: "community guidelines"
getting_help:
title: "Getting help"
getting_started_q: "Help! I need some basic help to get me started!"
@@ -322,10 +331,11 @@ en:
get_support_a_irc: "Join us on %{irc} (live chat)"
get_support_a_faq: "Read our %{faq} page on wiki"
get_support_a_hashtag: "Ask in a public post on diaspora* using the %{question} hashtag"
+ get_support_a_discourse: "Search for existing discussions relating to your enquiry or open a new thread in our %{discourse} platform"
account_and_data_management:
title: "Account and data management"
move_pods_q: "How do I move my seed (account) from one pod to another?"
- move_pods_a: "In the future you will be able to export your seed from a pod and import it on another, but this is not currently possible. You could always open a new account and add your contacts to aspects on that new seed, and ask them to add your new seed to their aspects."
+ move_pods_a: "Version 0.7.0.0 of diaspora* provides the first stage of account migration: you can now export all your data from the “Account” section of the user settings. Keep your data safely! In a future release you will be able to migrate your whole account, including posts and contacts, to another pod."
download_data_q: "Can I download a copy of all of my data contained in my seed (account)?"
download_data_a: "Yes. At the bottom of the Account tab of your settings page you will find two buttons: one for downloading your data and one for downloading your photos."
close_account_q: "How do I delete my seed (account)?"
@@ -345,7 +355,7 @@ en:
person_multiple_aspects_q: "Can I add a person to multiple aspects?"
person_multiple_aspects_a: "Yes. Go to your contacts page and click on “My contacts”. For each contact you can use the menu on the right to add them to (or remove them from) as many aspects as you want. Or you can add them to a new aspect (or remove them from an aspect) by clicking the aspect selector button on their profile page. Or you can even just move the pointer over their name where you see it in the stream, and a “hovercard” will appear. You can change the aspects they are in right there."
contacts_visible_q: "What does “make contacts in this aspect visible to each other” mean?"
- contacts_visible_a: "If you check this option then contacts from that aspect will be able to see who else is in it, in the “Contacts” tab on your profile page. It’s best to select this option only if the contacts in that aspect all know each other, for example if the aspect is for a club or society you belong to. They still won’t be able to see what the aspect is called."
+ contacts_visible_a: "If you check this option then contacts from that aspect will be able to see who else is in it, in the “Contacts” tab on your profile page. (At the moment, only your contacts who are on the same pod as you will be able to see the “Contacts” tab on your profile.) It’s best to select this option only if the contacts in that aspect all know each other, for example if the aspect is for a club or society you belong to. They still won’t be able to see what the aspect is called."
remove_notification_q: "If I remove someone from an aspect, or all of my aspects, are they notified of this?"
remove_notification_a: "No. They are also not notified if you add them to more aspects, when you are already sharing with them."
change_aspect_of_post_q: "Once I have posted something, can I change the aspect(s) that can see it?"
@@ -370,7 +380,7 @@ en:
how_to_mention_q: "How do I mention someone when making a post?"
how_to_mention_a: "Type the “@” sign and start typing their name. A drop-down menu should appear to let you select them more easily. Note that it is only possible to mention people you have added to an aspect."
mention_in_comment_q: "Can I mention someone in a comment?"
- mention_in_comment_a: "No, not currently."
+ mention_in_comment_a: "Since version 0.7.0.0, yes! You can mention someone in a comment the same way you would do it in a post, by typing “@” and then start typing their name. Please note that when you comment on a post which is not public, you can only mention users who have already interacted with the post."
see_mentions_q: "Is there a way to see the posts in which I have been mentioned?"
see_mentions_a: "Yes, click “@Mentions” in the left-hand column on your home page."
pods:
@@ -380,7 +390,7 @@ en:
find_people_q: "I just joined a pod, how can I find people to share with?"
find_people_a: "If you want to invite your friends to join diaspora*, use the invitation link or the email link in the side-bar. Follow #tags to discover others who share your interests, and add those who post things that interest you to an aspect. Shout out that you’re #newhere in a public post."
use_search_box_q: "How do I use the search box to find particular individuals?"
- use_search_box_a: "If you know their full diaspora* ID (e.g. username@podname.org), you can find them by searching for it. If you are on the same pod you can search for just their username. Alternatively you can search for them by their profile name (the name you see on screen). If a search does not work the first time, try it again."
+ use_search_box_a: "You can search for people by entering their username or their diaspora* name (the name that is shown on their profile). If neither of these methods work, enter their full diaspora* ID (username@podname.org). If your search doesn’t work the first time, it could be due to network latency. Try it again."
posts_and_posting:
title: "Posts and posting"
stream_full_of_posts_q: "Why is my stream full of posts from people I don’t know and don’t share with?"
@@ -393,20 +403,17 @@ en:
post_notification_q: "How do I get notifications, or stop getting notifications, about a post?"
post_notification_a: "You will find a bell icon next to the X at the top right of a post. Click this to enable or disable notifications for that post."
post_report_q: "How do I report an offensive post?"
- post_report_a: "Click the alert triangle icon at the top right of the post to report it to your podmin. Enter a reason for reporting this post in the dialog box."
+ post_report_a: "Click the alert triangle icon at the top right of the post to report it to your podmin. Enter a reason for reporting this post in the dialog box. Please only report posts that break our %{community_guidelines} or your pod’s terms of service, for example posts containing illegal content, or which are abusive or spam."
character_limit_q: "What is the character limit for posts?"
character_limit_a: "65,535 characters. That’s 65,395 more characters than you get on Twitter! ;)"
char_limit_services_q: "What if I'm sharing my post with a connected service with a smaller character count?"
char_limit_services_a: "In that case you should restrict your post to the smaller character count (140 in the case of Twitter; 1000 in the case of Tumblr), and the number of characters you have left to use is displayed when that service’s icon is highlighted. You can still post to these services if your post is longer than their limit, but the text will be truncated on those services with a link to the post on diaspora*."
format_text_q: "How can I format the text in my posts (bold, italics, etc.)?"
- format_text_a: "By using a simplified system called %{markdown}. You can find the full Markdown syntax %{here}. The preview button is really helpful here, as you can see how your message will look before you share it."
+ format_text_a: "diaspora* uses a simplified system called %{markdown}. The publisher has buttons to make it easy to format your text. If you want to format your post manually, you can find the full Markdown syntax %{here}. The preview tab means you can see how your message will look before you share it. Remember that you can’t edit it once posted, so use the preview to make sure it’s perfect before pressing Share!"
insert_images_q: "How do I insert images into posts?"
- insert_images_a: "Click the little camera icon to insert an image into a post. Press the camera icon again to add another photo, or you can select multiple photos to upload in one go."
+ insert_images_a: "If you want to include an image stored on your computer in your post, click the little camera icon at the bottom of the publisher. You can also drag and drop an image, or multiple images, from your computer onto that icon. If you want to insert an image from the web into your post, click the image button on the top of the publisher, which will create the Markdown code for you."
insert_images_comments_q: "Can I insert images into comments?"
- insert_images_comments_a1: "You cannot upload images into comments, but the following Markdown code"
- image_text: "image text"
- image_url: "image url"
- insert_images_comments_a2: "can be used to insert images from the web into comments as well as posts."
+ insert_images_comments_a: "You can use Markdown to insert an image from the web into a comment, just like in posts. However, you cannot upload images from your computer directly into comments. Upload them to an image-hosting service and then insert them using the image button above the publisher."
size_of_images_q: "Can I customize the size of images in posts or comments?"
size_of_images_a: "No. Images are resized automatically to fit the stream or single-post view. Markdown does not have a code for specifying the size of an image."
embed_multimedia_q: "How do I embed a video, audio, or other multimedia content into a post?"
@@ -425,14 +432,6 @@ en:
can_reshare_a: "Nobody. Private posts are not resharable. Logged-in diaspora* users in that aspect can potentially copy and paste it, however. It’s up to you whether you trust those people!"
see_comment_q: "When I comment on or like a private post, who can see it?"
see_comment_a: "Only the people that the post was shared with (the people who are in the aspects selected by the original poster) can see its comments and likes. "
- private_profiles:
- title: "Private profiles"
- who_sees_profile_q: "Who sees my private profile?"
- who_sees_profile_a: "Any logged-in user that you are sharing with (meaning, you have added them to one of your aspects). However, people following you, but whom you do not follow, will see only your public information."
- whats_in_profile_q: "What’s in my private profile?"
- whats_in_profile_a: "Your private profile contains your biography, location, gender, and birthday, if you have completed these sections. All this information is optional – it’s up to you whether you provide it. Logged-in users who you have added to your aspects are the only people who can see your private profile. When they visit your profile page they will also see the private posts that made to the aspect(s) they are in, mixed in with your public posts."
- who_sees_updates_q: "Who sees updates to my private profile?"
- who_sees_updates_a: "Anyone in your aspects sees changes to your private profile. "
public_posts:
title: "Public posts"
who_sees_post_q: "When I post something publicly, who can see it?"
@@ -440,21 +439,19 @@ en:
find_public_post_q: "How can other people find my public post?"
find_public_post_a: "Your public posts will appear in the streams of anyone following you. If you included #tags in your public post, anyone following those tags will find your post in their streams. Every public post also has a specific URL that anyone can view, even if they’re not logged in – thus public posts may be linked to directly from Twitter, blogs, etc. Public posts may also be indexed by search engines."
can_comment_reshare_like_q: "Who can comment on, reshare, or like my public post?"
- can_comment_reshare_like_a: "Any logged-in diaspora* user can comment on, reshare, or like your public post."
+ can_comment_reshare_like_a: "Any logged-in diaspora* user can comment on, reshare, or like your public post. The exception to this is people you have ignored, who won’t be able to like or comment on your posts."
see_comment_reshare_like_q: "When I comment on, reshare, or like a public post, who can see it?"
see_comment_reshare_like_a: "Comments, likes, and reshares of public posts are also public. Any logged-in diaspora* user and anyone else on the internet can see your interactions with a public post."
- deselect_aspect_posting_q: "What happens when I deselect one or more aspects when making a public post?"
+ deselect_aspect_posting_q: "What happens when I deselect one or more aspects in the left-hand column when making a public post?"
deselect_aspect_posting_a: "Deselecting aspects does not affect a public post. It will still be public and will appear in the streams of all of your contacts. To make a post visible only to specific aspects, you need to select those aspects from the aspect selector under the publisher."
- public_profiles:
- title: "Public profiles"
- who_sees_profile_q: "Who sees my public profile?"
- who_sees_profile_a: "Any logged-in diaspora* user, as well as the wider internet, can see it. Each profile has a direct URL, so it may be linked to directly from outside sites. It may be indexed by search engines."
- whats_in_profile_q: "What’s in my public profile?"
- whats_in_profile_a: "Your public profile contains your name, the five tags you chose to describe yourself, and your photo, if you have completed these sections. All this information is optional – it’s up to you whether you provide it. You can make this profile information as identifiable or anonymous as you like. Your profile page also shows any public posts you have made."
- who_sees_updates_q: "Who sees updates to my public profile?"
- who_sees_updates_a: "Anyone can see changes if they visit your profile page."
- what_do_tags_do_q: "What do the tags on my public profile do?"
- what_do_tags_do_a: "They help people get to know you. Your profile picture will also appear on the left-hand side of those particular tag pages, along with anyone else who has them in their public profile."
+ profile:
+ title: "Profile"
+ whats_in_profile_q: "What’s in my profile?"
+ whats_in_profile_a: "Your profile is in two parts: your basic profile and your extended profile. Your basic profile contains your name, the five tags you chose to describe yourself, and your photo. Your extended profile contains your biography, location, gender, and birthday. All this information is optional – it’s up to you whether you provide it, and you can make this profile information as identifiable or anonymous as you like. Your extended profile is displayed in the left-hand column of your profile page, under your profile picture."
+ who_sees_profile_q: "Who sees my profile?"
+ who_sees_profile_a: "Your basic profile (name, profile image and #tags) is public. Your extended profile is private by default, but you can make it all publicly accessible if you want. Only people you are sharing with (meaning, you have added them to one of your aspects) can see your extended profile if you keep it private. Other people will see only your public information. Any profile information you make public can be viewed by anyone using the web, and can be indexed by search engines"
+ what_do_tags_do_q: "What do the tags in my basic profile do?"
+ what_do_tags_do_a: "They help people get to know you. Your profile picture will also appear on the left-hand side of the stream pages of those tags, along with anyone else who has them in their basic profile."
resharing_posts:
title: "Resharing posts"
reshare_public_post_aspects_q: "Can I reshare a public post to selected aspects?"
@@ -479,7 +476,7 @@ en:
only_sharing_q: "Who are the people listed under “Only sharing with me” on my contacts page?"
only_sharing_a: "These are people that have added you to one of their aspects, but who are not (yet) in any of your aspects. In other words, they are sharing with you, but you are not sharing with them: you can think of this as them “following” you. If you add them to an aspect, they will then appear under that aspect and not under “Only sharing with me”. See above."
list_not_sharing_q: "Is there a list of people whom I have added to one of my aspects, but who have not added me to one of theirs?"
- list_not_sharing_a: "No, but you can see whether or not someone is sharing with you by visiting their profile page. If they are, the button showing the aspect(s) in which you have placed them will be green; if not, it’ll be gray."
+ list_not_sharing_a: "No, but you can see whether or not someone is sharing with you by visiting their profile page. If they are, there will be a green tick next to their diaspora* ID. If they are not, there will be a gray circle."
see_old_posts_q: "When I add someone to an aspect, can they see older posts that I have already posted to that aspect?"
see_old_posts_a: "No. They will only be able to see new posts to that aspect. They (and everyone else) can see your older public posts on your profile page, and they may also see them in their stream."
tags:
@@ -489,7 +486,7 @@ en:
tags_in_comments_q: "Can I put tags in comments or just in posts?"
tags_in_comments_a: "A tag added to a comment will still appear as a link to that tag’s page, but it will not make that post (or comment) appear on that tag page. This only works for tags in posts."
followed_tags_q: "What are “#Followed Tags” and how do I follow a tag?"
- followed_tags_a: "After searching for a tag you can click the button at the top of the tag’s page to “follow” that tag. It will then appear in your list of followed tags in the left-hand menu. Clicking one of your followed tags takes you to that tag’s page so you can see recent posts containing that tag. Click on #Followed Tags to see a stream of posts that include any one of your followed tags."
+ followed_tags_a: "After searching for a tag you can click the button at the top of the tag’s page to “follow” that tag. It will then appear in your list of followed tags in the left-hand menu. Clicking one of your followed tags takes you to that tag’s page so you can see recent posts containing that tag. Click on #Followed Tags to see a stream of posts that include any one of your followed tags. Posts containing that tag will also be included in your main stream."
people_tag_page_q: "Who are the people listed on the left-hand side of a tag page?"
people_tag_page_a: "They are people who have listed that tag to describe themselves in their public profile."
filter_tags_q: "How can I filter/exclude some tags from my stream?"
@@ -613,9 +610,11 @@ en:
one: "%{actors} also commented on %{post_author}’s post %{post_link}."
other: "%{actors} also commented on %{post_author}’s post %{post_link}."
mentioned:
- zero: "%{actors} have mentioned you in the post %{post_link}."
one: "%{actors} has mentioned you in the post %{post_link}."
other: "%{actors} have mentioned you in the post %{post_link}."
+ mentioned_in_comment:
+ one: "%{actors} has mentioned you in a <a href='%{comment_path}'>comment</a> to the post %{post_link}."
+ other: "%{actors} have mentioned you in a <a href='%{comment_path}'>comment</a> to the post %{post_link}."
liked:
zero: "%{actors} have liked your post %{post_link}."
one: "%{actors} has liked your post %{post_link}."
@@ -637,9 +636,11 @@ en:
one: "%{actors} reshared your deleted post."
other: "%{actors} reshared your deleted post."
mentioned_deleted:
- zero: "%{actors} mentioned you in a deleted post."
one: "%{actors} mentioned you in a deleted post."
other: "%{actors} mentioned you in a deleted post."
+ mentioned_in_comment_deleted:
+ one: "%{actors} mentioned you in a deleted comment."
+ other: "%{actors} mentioned you in a deleted comment."
index:
notifications: "Notifications"
mark_all_as_read: "Mark all as read"
@@ -652,7 +653,8 @@ en:
also_commented: "Also commented"
comment_on_post: "Comment on post"
liked: "Liked"
- mentioned: "Mentioned"
+ mentioned: "Mentioned in post"
+ mentioned_in_comment: "Mentioned in comment"
reshared: "Reshared"
started_sharing: "Started sharing"
no_notifications: "You don't have any notifications yet."
@@ -686,6 +688,9 @@ en:
mentioned:
subject: "%{name} has mentioned you on diaspora*"
limited_post: "You were mentioned in a limited post."
+ mentioned_in_comment:
+ limited_post: "You were mentioned in a comment to a limited post."
+ reply: "Reply to or view this conversation >"
private_message:
subject: "There’s a new private message for you"
reply_to_or_view: "Reply to or view this conversation >"
@@ -791,7 +796,7 @@ en:
message: |-
Hello!
- You have been invited to join diaspora* by %{diaspora_id}!
+ You have been invited to join diaspora* by %{user}!
Click this link to get started
@@ -1183,6 +1188,7 @@ en:
started_sharing: "someone starts sharing with you"
someone_reported: "someone sends a report"
mentioned: "you are mentioned in a post"
+ mentioned_in_comment: "you are mentioned in a comment"
liked: "someone likes your post"
reshared: "someone reshares your post"
comment_on_post: "someone comments on your post"
diff --git a/config/locales/diaspora/en_valspeak.yml b/config/locales/diaspora/en_valspeak.yml
index 7bcd8ba3a..57dafc68d 100644
--- a/config/locales/diaspora/en_valspeak.yml
+++ b/config/locales/diaspora/en_valspeak.yml
@@ -330,7 +330,6 @@ en_valspeak:
mentions:
how_to_mention_a: "So like, you type this thing: @ n start typin their name. Then this like... little menu thingy will come up n like let u pick their name. But like, remember that u can like.. only mention ppl u've added n stuff. Totally lame sometimes :\\"
how_to_mention_q: "So like, how do I like... mention some1 when making a postie?"
- mention_in_comment_a: "Mmm... nope. sry bout that :\\"
mention_in_comment_q: "So can I like... mention some1 in a comment? :o"
see_mentions_a: "Ya, click \"Mentionz\" in the like.. left column on ur home page. K?"
see_mentions_q: "Is there like, a way 2 c the posties that ive been mentioned in?"
@@ -366,11 +365,7 @@ en_valspeak:
format_text_q: "So how can I like, format txt in mah posties (bold, slanted txt, etc)?"
hide_posts_a: "So like, if u point ur mouse at the top of a postie, a cute lil X comes up on the right. click it 2 hide the postie n mute noties bout it. u can still c the post f u visit the profile of the person who made it.(:"
hide_posts_q: "So like, how do I like.. hide a postie? N how do I stop gettin noties bout a postie that i like.. commented on? :o"
- image_text: "pic txt"
- image_url: "pic linkk"
insert_images_a: "So like, click on the cute lil camera thingy 2 add a pic into a postie. Press the pic icon thingy again 2 add another pic, or u can like... pick multiple pics 2 add in 1 go at it. :D"
- insert_images_comments_a1: "The followin Markydown code"
- insert_images_comments_a2: "can b used 2 like.. put pics from the web into comments as well as in posties :)"
insert_images_comments_q: "Can I insert picz into commentz? :o"
insert_images_q: "How do I like... put picz into posties?"
post_location_a: "so like, you have to click the little pin icon thingy next to the grandpa camera in the publisher thingy. it will like... say where u r from this site called like... openstreetmap... you know that thing that google maps like rips off from... anyway... you can also like... edit your location... its rlly rad."
@@ -396,14 +391,6 @@ en_valspeak:
title: "Privy posties!"
who_sees_post_a: "Only like, d* ppl who r logged in that r in tht aspect can c ur private postie."
who_sees_post_q: "So like, when i post a txt 2 an aspect (as in a private postie), who can c it???"
- private_profiles:
- title: "Private profilez!!!"
- whats_in_profile_a: "ur like, bio, location, gendah, n bday. its the stuff in the bottom part of the edit profile page thingy. all this info is optional - its up 2 u whether u fill it in. logged in ppl who u have added 2 ur aspectz r the only ppl who can c ur private stuff. they will also like, c the private posties that r made to the aspectz they r in, mixed in with ur public posties, n when they look at ur profile. kay?"
- whats_in_profile_q: "So like, wats in mah private profile? :o"
- who_sees_profile_a: "ne logged in ppl that u r sharin wit (meanin, u have added them 2 1 of ur aspectz). howevah, ppl followin u, but u do not follow, will c only ur public info."
- who_sees_profile_q: "Who can like... c my private profile?"
- who_sees_updates_a: "Ne in ur aspectz can like... c the changes 2 ur private profile. "
- who_sees_updates_q: "Who can like... c updates 2 mah private profile? :o"
public_posts:
can_comment_reshare_like_a: "Ne d* ppl who r logged in can do that. Yeah."
can_comment_reshare_like_q: "Who can like... comment on, reshare or like... like my public posties?"
@@ -416,16 +403,6 @@ en_valspeak:
title: "Public posties!!!"
who_sees_post_a: "ne1 usin the internet can possibly c a postie u mark public, so make for sure u rlly do want ur postie 2 b public. its a great way of reachin out 2 the world tho."
who_sees_post_q: "When I like... post somethin publicly, like, who can c it?"
- public_profiles:
- title: "Public profilez!"
- what_do_tags_do_a: "They halp ppl get 2 kno u. Ur profile pic will also come up on the left side of those certain tag pagez, along wit ne1 else who has them in their public profile n stuff."
- what_do_tags_do_q: "Wat do the tagz on mah public profile do? Like, so confused.."
- whats_in_profile_a: "Ur like, name, the 5 tagz u chose 2 describe urself, n ur pic. its the stuff in the top part of the edit profile page thingy. u can like, make this profile info as obvious or not obvious as u would like. Ur profile page also showz ne public posties u have made.."
- whats_in_profile_q: "So like, wats in my public profile?"
- who_sees_profile_a: "ne logged in d* usah, as well as the internetz, can c it. so liek, each profile has a link, so it may b linked 2 directly from other sites. it may b listed by search engine ppl."
- who_sees_profile_q: "Who can like.. c my public profile? o_o"
- who_sees_updates_a: "Ne1 can like... c changes if they go to ur profile page..."
- who_sees_updates_q: "Who like... c's updates 2 my public profile?"
resharing_posts:
reshare_private_post_aspects_a: "Nah, its not possible 2 reshare a private postie. This is 2 respect the intention of teh original poster who only shared it wit a certain group of ppl. Kay? Kay, good."
reshare_private_post_aspects_q: "Can I like... reshare a private postie with like... only certain aspectz?"
diff --git a/config/locales/diaspora/es-AR.yml b/config/locales/diaspora/es-AR.yml
index db4df5fcd..d21b2b106 100644
--- a/config/locales/diaspora/es-AR.yml
+++ b/config/locales/diaspora/es-AR.yml
@@ -274,6 +274,13 @@ es-AR:
heading: "Marcador"
post_something: "Publicar en diaspora*"
cancel: "Cancelar"
+ color_themes:
+ dark: "Oscuro"
+ dark_green: "Verde oscuro"
+ egyptian_blue: "Azul egipcio"
+ magenta: "Magenta"
+ original: "Gris original"
+ original_white: "Fondo blanco original"
comments:
create:
error: "Hubo un error al comentar."
@@ -413,7 +420,6 @@ es-AR:
mentions:
how_to_mention_a: "Escribe el signo \"@\" y comience a escribir el nombre. Un menú desplegable con opciones aparecerá para seleccionarlo más fácilmente. Sólo es posible mencionar a las personas que tienes agregadas a uno o varios aspectos."
how_to_mention_q: "¿Cómo puedo mencionar a alguien cuando hago una publicación?"
- mention_in_comment_a: "No, no por el momento."
mention_in_comment_q: "¿Puedo mencionar a alguien en un comentario?"
see_mentions_a: "Sí, haz clic en \"@Menciones\" en la columna izquierda de tu página de inicio."
see_mentions_q: "¿Existe alguna manera de ver las publicaciones en las cuales he sido mencionado?"
@@ -449,11 +455,7 @@ es-AR:
format_text_q: "¿Cómo puedo darle formato al texto de mis publicaciones (negrita, itálica, etc.)?"
hide_posts_a: "Si llevas el puntero de tu ratón a la parte de arriba de la publicación, una X aparecerá a la derecha. Has un clic sobre esta para esconder la publicación y desactivar las notificaciones sobre ella. Aún podrás ver la publicación si visitas la pagina de perfil de la persona que la publicó."
hide_posts_q: "¿Cómo puedo ocultar una publicación? / ¿Cómo puedo hacer para dejar de recibir notificaciones de una publicación en la que comenté?"
- image_text: "texto de la imagen"
- image_url: "URL de la imagen"
insert_images_a: "Haz clic en el icono pequeño con forma de cámara para insertar imágenes en una publicación. Presiona el icono de imágenes nuevamente para añadir otra foto, o selecciona varias al mismo tiempo."
- insert_images_comments_a1: "No puedes subir imágenes en los comentarios, pero puedes insertarlas usando el código Markdown"
- insert_images_comments_a2: "puede ser utilizada para insertar imágenes desde la web en los comentarios y también en las publicaciones."
insert_images_comments_q: "¿Puedo insertar imágenes en los comentarios?"
insert_images_q: "¿Cómo puedo insertar imágenes en las publicaciones?"
post_location_a: "Pulsa el icono de localización al lado de la cámara en el publicador (el cuadro de publicación). Ello insertará tu localización desde OpenStreetMap. Puedes editar tu localización y escoger publicar sólo el nombre de la ciudad en la que estás en lugar de tu dirección exacta."
@@ -482,14 +484,6 @@ es-AR:
title: "Publicaciones privadas"
who_sees_post_a: "Solo los usuarios de diaspora* que hayas agregado a ese aspecto podrán ver tu publicación restringida."
who_sees_post_q: "Cuando publico un mensaje en un aspecto (es decir, una publicación restringida o limitada), ¿quienes pueden verlo?"
- private_profiles:
- title: "Perfiles privados"
- whats_in_profile_a: "Tu perfil privado contiene tu biografía, ubicación, género y fecha de cumpleaños, si es que has completado esas secciones. Están ubicadas en la parte inferior de la página de edición de perfil. Toda esa información es opcional -depende de vos si la llenás o no-. Los usuarios que tengas agregados a tus aspectos son las únicas personas que podrán ver tu perfil privado. Ellos también podrán ver las publicaciones privadas que hagas en él o los aspectos a los que pertenecen, mezcladas con tus publicaciones públicas, cuando visiten tu página de perfil."
- whats_in_profile_q: "¿Qué hay en mi perfil privado?"
- who_sees_profile_a: "Cualquier usuario conectado que esta compartiendo contigo (es decir, que tú tienes en uno de tus aspectos). Sin embargo, las personas que te siguen, pero que tu no sigues, solo verán tu información publica."
- who_sees_profile_q: "¿Quiénes pueden ver mi perfil privado?"
- who_sees_updates_a: "Cualquier contacto de tus aspectos podrá ver los cambios o actualizaciones de tu perfil privado. "
- who_sees_updates_q: "¿Quién puede ver las actualizaciones de mi perfil privado?"
public_posts:
can_comment_reshare_like_a: "Cualquier usuario de diaspora* conectado puede comentar, volver a compartir o marcar como \"Me gusta\" tus publicaciones públicas."
can_comment_reshare_like_q: "¿Quién puede comentar, volver a compartir o poner \"Me gusta\" en mis publicaciones públicas?"
@@ -502,16 +496,6 @@ es-AR:
title: "Publicaciones públicas"
who_sees_post_a: "Cualquiera que use Internet puede potencialmente ver una publicación que hayas marcado como pública, así que asegúrate de que realmente quieres que tu publicación sea pública. Es una buena forma de hacerse escuchar en todo el mundo."
who_sees_post_q: "Cuando publico algo de manera pública, ¿quién puede verlo?"
- public_profiles:
- title: "Perfiles públicos"
- what_do_tags_do_a: "Las etiquetas ayudan a la gente a conocerte. Las fotos de perfil también aparecerán en el lado izquierdo de las páginas de esas etiquetas, junto con cualquier otra persona que las tenga en su perfil público."
- what_do_tags_do_q: "¿Qué hacen las etiquetas de mi perfil público?"
- whats_in_profile_a: "Tu perfil público contiene tu nombre, las cinco etiquetas que elijas para describirte a ti mismo, y tu foto. Están en la sección superior de la página de edición de perfil. Puedes hacer que esta información de perfil sea identificable o anónima. También, tu página de perfil muestra cualquier publicación pública que hayas hecho."
- whats_in_profile_q: "¿Qué hay en mi perfil público?"
- who_sees_profile_a: "Cualquier usuario de diaspora* conectado, así como la inmensidad de Internet, puede verlo. Cada perfil tiene una URL directa, así que puede ser enlazado directamente desde sitios externos y puede ser indexado por los motores de búsqueda."
- who_sees_profile_q: "¿Quién puede ver mi perfil público?"
- who_sees_updates_a: "Cualquier persona puede ver los cambios si visitan tu página de perfil."
- who_sees_updates_q: "¿Quién puede ver las actualizaciones de mi perfil público?"
resharing_posts:
reshare_private_post_aspects_a: "No, no es posible volver a compartir una publicación privada. Es por respeto a las intenciones del autor original de sólo compartirla con un grupo determinado de personas."
reshare_private_post_aspects_q: "¿Puedo volver a compartir una publicación limitada sólo con ciertos aspectos?"
@@ -666,6 +650,7 @@ es-AR:
mark_read: "Marcar como leído"
mark_unread: "Marcar como no leído"
mentioned: "Mencionados"
+ mentioned_in_comment: "Fuiste mencionado en un comentario"
no_notifications: "Aún no tienes ninguna notificación."
notifications: "Notificaciones"
reshared: "Compartidos"
@@ -691,6 +676,12 @@ es-AR:
one: "%{actors} te mencionó en una publicación eliminada."
other: "%{actors} te mencionaron en una publicación eliminada."
zero: "%{actors} te mencionaron en una publicación eliminada."
+ mentioned_in_comment:
+ one: "%{actors} te mencionó en un <a href='%{comment_path}'>comentario</a> de la publicación %{post_link}"
+ other: "%{actors} te mencionarion en un <a href='%{comment_path}'>comentario</a> de la publicación %{post_link}"
+ mentioned_in_comment_deleted:
+ one: "%{actors} te mencionó en un comentario que fue eliminado."
+ other: "%{actors} te mencionaron en un comentario que fue eliminado."
private_message:
few: "%{actors} te enviaron un mensaje."
many: "%{actors} te enviaron un mensaje."
@@ -820,6 +811,9 @@ es-AR:
mentioned:
limited_post: "Se te mencionó en una publicación privada."
subject: "%{name} te mencionó en diaspora*"
+ mentioned_in_comment:
+ limited_post: "Fuiste mencionado en un comentario de una publicación limitada."
+ reply: "Contestar o ver esta conversación >"
private_message:
reply_to_or_view: "Responder o ver esta conversación >"
subject: "Tienes un nuevo mensaje privado en diaspora*"
@@ -1187,6 +1181,7 @@ es-AR:
last_exported_at: "(Última actualización en %{timestamp})"
liked: "...a alguien le gusta una publicación tuya?"
mentioned: "...te mencionan en una publicación?"
+ mentioned_in_comment: "te han mencionado en un comentario"
new_password: "Contraseña nueva"
private_message: "...recibís un mensaje privado?"
receive_email_notifications: "¿Recibir notificaciones por correo electrónico cuando..."
diff --git a/config/locales/diaspora/es-CL.yml b/config/locales/diaspora/es-CL.yml
index b35d92f5a..eff5a5b85 100644
--- a/config/locales/diaspora/es-CL.yml
+++ b/config/locales/diaspora/es-CL.yml
@@ -265,7 +265,6 @@ es-CL:
mentions:
how_to_mention_a: "Utiliza el signo \"@\" y comienzas a escribir el nombre. Un menú desplegable con opciones aparecerá para seleccionarlo más fácilmente. Sólo es posible mencionar a las personas que tienes agregadas en un aspecto."
how_to_mention_q: "¿Cómo puedo mencionar a alguien cuando hago una publicación?"
- mention_in_comment_a: "No, de momento no."
mention_in_comment_q: "¿Puedo mencionar a alguien en un comentario?"
see_mentions_a: "Sí, haz clic en \"@Menciones\" en la columna izquierda de tu página de inicio."
see_mentions_q: "¿Existe alguna manera de ver las publicaciones en las cuales he sido mencionado?"
@@ -291,11 +290,7 @@ es-CL:
format_text_q: "¿Cómo puedo darle formato al texto de mis publicaciones (negrita, itálica, etc.)?"
hide_posts_a: "Si apuntas tu ratón a la parte superior de una publicación, aparecerá una X a la derecha. Haz click para ocultar la publicación y para dejar de recibir notificaciones al respecto. Aún podrás ver la publicación si visitas el perfil de la persona que la publicó."
hide_posts_q: "¿Cómo oculto una publicación? / ¿Cómo dejo de recibir notificaciones de una publicación en la que comenté?"
- image_text: "texto de la imagen"
- image_url: "URL de imagen"
insert_images_a: "Haz click en el ícono pequeño con forma de cámara para insertar imágenes en una publicación. Presiona el ícono de imágenes nuevamente para añadir otra foto, o selecciona varias al mismo tiempo."
- insert_images_comments_a1: "Siguiendo el código Markdown"
- insert_images_comments_a2: "puede ser utilizada para insertar imágenes desde la web en los comentarios y también en las publicaciones."
insert_images_comments_q: "¿Puedo insertar imágenes en los comentarios?"
insert_images_q: "¿Cómo puedo insertar imágenes en las publicaciones?"
size_of_images_a: "No. El tamaño de las imágenes automáticamente se ajusta a la Entrada. Markdown no tiene un código para especificar el tamaño de una imagen."
@@ -316,14 +311,6 @@ es-CL:
title: "Publicaciones limitadas"
who_sees_post_a: "Solo los usuarios de diaspora* conectados que estén en ese aspecto podrán ver tu publicación limitada."
who_sees_post_q: "Cuando publico un mensaje a un aspecto (publicación limitada), ¿quienes pueden verlo?"
- private_profiles:
- title: "Perfiles privados"
- whats_in_profile_a: "Tu Biografía, Ubicación, Género y Fecha de Cumpleaños. Son las cosas en la parte inferior de la página de edición del perfil. Esta información es opcional, es cosa tuya si la llenas o no. Los usuarios conectados que tengas agregados a tus aspectos son los únicos que podrán ver tu perfil privado. Ellos también podrán ver las publicaciones limitadas a los aspectos en los que se encuentren, combinadas con tus publicaciones públicas, cuando visiten tu página de perfil."
- whats_in_profile_q: "¿Qué hay en mi perfil privado?"
- who_sees_profile_a: "Cualquier usuario conectado con quien compartas (es decir, que esté agregado a uno de tus aspectos). Sin embargo, las personas que te siguen, pero que tu no sigues, solo verán tu información publica."
- who_sees_profile_q: "¿Quiénes pueden ver mi perfil privado?"
- who_sees_updates_a: "Cualquier contacto de tus aspectos podrá ver los cambios o actualizaciones de tu perfil privado. "
- who_sees_updates_q: "¿Quién puede ver las actualizaciones de mi perfil privado?"
public_posts:
can_comment_reshare_like_a: "Cualquier usuario de diaspora* conectado puede comentar, compartir o marcar como \"Me gusta\" tus publicaciones públicas."
can_comment_reshare_like_q: "¿Quién puede comentar, volver a compartir o poner \"Me gusta\" en mis publicaciones públicas?"
@@ -336,16 +323,6 @@ es-CL:
title: "Publicaciones públicas"
who_sees_post_a: "Cualquiera que use internet puede potencialmente ver una publicación que marques como pública, así que asegúrate de que realmente quieras que tu publicación sea pública. Es una buena forma de hacerce escuchar en todo el mundo."
who_sees_post_q: "Cuando publico algo de manera pública, ¿quién puede verlo?"
- public_profiles:
- title: "Perfiles públicos"
- what_do_tags_do_a: "Ellas ayudan a que las personas te conozcan. Tu foto de perfil también aparecerá al lado izquierdo de las páginas de esas etiquetas, junto con cualquier otra persona que las tiene en su perfil público."
- what_do_tags_do_q: "¿Qué hacen las etiquetas de mi perfil público?"
- whats_in_profile_a: "Tu nombre, las cinco etiquetas que escogiste para describirte, y tu foto. Son las cosas en la parte superior de la página de edición de perfil. puedes hacer esta información de perfil tan exacta o anónima como quieras. tu página de perfil también muestra cualquier publicación pública que hayas hecho."
- whats_in_profile_q: "¿Qué hay en mi perfil público?"
- who_sees_profile_a: "Cualquier usuario de diaspora* conectado, así como la inmensidad de internet puede verlo. Cada perfil tiene una URL directo, así que puede ser enlazado directamente desde sitios externos. Puede ser indexado a motores de búsqueda."
- who_sees_profile_q: "¿Quién puede ver mi perfil público?"
- who_sees_updates_a: "Cualquier persona puede ver los cambios si visitan tu página de perfil."
- who_sees_updates_q: "¿Quién puede ver las actualizaciones de mi perfil público?"
resharing_posts:
reshare_private_post_aspects_q: "¿Puedo volver a compartir una publicación privada solo con ciertos aspectos?"
reshare_public_post_aspects_q: "¿Puedo compartir una publicación pública con solo ciertos aspectos?"
diff --git a/config/locales/diaspora/es-MX.yml b/config/locales/diaspora/es-MX.yml
index f4e29a8ab..165843769 100644
--- a/config/locales/diaspora/es-MX.yml
+++ b/config/locales/diaspora/es-MX.yml
@@ -268,7 +268,6 @@ es-MX:
mentions:
how_to_mention_a: "Escribe el símbolo «@», y comienza a escribir su nombre. Un menú contextual aparecerá para permitirte seleccionar más fácilmente los nombres. Ten en cuenta que únicamente es posible mencionar a aquellas personas que hayas añadido a un aspecto."
how_to_mention_q: "¿Cómo menciono a alguien al realizar una publicación?"
- mention_in_comment_a: "No por el momento."
mention_in_comment_q: "¿Puedo mencionar a alguien en un comentario?"
see_mentions_a: "Sí, haz clic en «Menciones», en la columna izquierda de tu página de inicio."
see_mentions_q: "¿Es posible ver las publicaciones en las cuales he sido mencionado?"
@@ -303,11 +302,7 @@ es-MX:
format_text_q: "¿Cómo puedo dar formato al texto en las publicaciones (negrita, cursiva, etcétera)?"
hide_posts_a: "Si colocas tu cursor en la parte superior de una publicación, una X aparecerá a la derecha. Haz clic en ella para ocultar la publicación, y desactivar las notificaciones sobre esta. Aún te será posible ver la publicación en la página de perfil del autor."
hide_posts_q: "¿Cómo oculto una publicación? ¿Cómo evito recibir notificaciones sobre una publicación en la cual realicé un comentario?"
- image_text: "texto de la imagen"
- image_url: "URL de la imagen"
insert_images_a: "Haz clic en el ícono de la cámara para insertar una imagen en la publicación. Haz clic de nuevo para añadir otra foto. También es posible seleccionar múltiples imágenes para agregarlas todas a la vez."
- insert_images_comments_a1: "El siguiente código de Markdown"
- insert_images_comments_a2: "se puede utilizar para insertar imágenes desde la web en los comentarios, así como en las publicaciones."
insert_images_comments_q: "¿Puedo insertar imágenes en los comentarios?"
insert_images_q: "¿Cómo inserto imágenes en una publicación?"
size_of_images_a: "No. Las imágenes se dimensionan automáticamente para ajustarse a la «Entrada». Markdown no proporciona un código para especificar el tamaño de una imagen."
@@ -322,14 +317,6 @@ es-MX:
title: "Publicaciones privadas"
who_sees_post_a: "Únicamente los usuarios de diaspora* que hayan iniciado sesión, y a quienes hayas añadido a dicho aspecto, podrán ver tu publicación limitada."
who_sees_post_q: "¿Cuando publico un mensaje para un aspecto (es decir, una publicación privada) quién puede verlo?"
- private_profiles:
- title: "Perfil privado"
- whats_in_profile_a: "Biografía, ubicación geográfica, género y fecha de cumpleaños. Es la información que se encuentra en la sección inferior de la página de edición de perfil. Toda esta información es opcional: de ti depende completarla. Los usuarios que hayan iniciado sesión, y que se encuentren en tus aspectos, serán los únicos que puedan ver tu perfil privado. También podrán ver los mensajes limitados a los aspectos en los cuales se encuentren, mezclados con tus publicaciones públicas, cuando visiten tu página de perfil."
- whats_in_profile_q: "¿De qué se compone mi perfil privado?"
- who_sees_profile_a: "Cualquier usuario que haya iniciado sesión, y con quien estés compartiendo (es decir, a quien hayas añadido a uno de tus aspectos). Sin embargo, la gente que te siga, pero a quien tú no sigas, solamente podrán ver tu información pública."
- who_sees_profile_q: "¿Quién puede ver mi perfil privado?"
- who_sees_updates_a: "Cualquiera que se encuentre en tus aspectos verá los cambios a tu perfil privado. "
- who_sees_updates_q: "¿Quién ve las actualizaciones a mi perfil privado?"
public_posts:
can_comment_reshare_like_a: "Cualquier usuario de diaspora* que haya iniciado sesión puede marcar como «me gusta», volver a compartir, o comentar en tu publicación pública."
can_comment_reshare_like_q: "¿Quién puede marcar como «me gusta», volver a compartir, o comentar en mi publicación pública?"
@@ -339,16 +326,6 @@ es-MX:
title: "Publicaciones públicas"
who_sees_post_a: "Cualquiera que utilice el Internet podría ver una publicación que marques como «pública»; por tanto, asegúrate de que realmente deseas hacerla pública. Es una buena manera de compartir con el mundo."
who_sees_post_q: "¿Cuándo realizo una publicación pública, quién puede verla?"
- public_profiles:
- title: "Perfiles públicos"
- what_do_tags_do_a: "Ayudan a la gente a conocerte. Tu imagen de perfil también aparecerá al lado izquierdo de dichas páginas de etiquetas, junto con cualquier otro usuario que tenga estas etiquetas en su perfil público."
- what_do_tags_do_q: "¿Para qué sirven las etiquetas en una publicación pública?"
- whats_in_profile_a: "Tu nombre, las cinco etiquetas que elegiste para describirte, y tu fotografía. Es la información que se encuentra en la sección superior de tu página de edición de perfil. Puedes hacer que esta información sea tan identificable o anónima como desees. Tu página de perfil también muestra cualquier publicación pública que hayas realizado."
- whats_in_profile_q: "¿De qué se compone mi perfil público?"
- who_sees_profile_a: "Cualquier usuario de diaspora* que haya iniciado sesión, así como cualquiera con acceso a Internet puede verlo. Cada perfil tiene una URL directa, así que podría ser enlazado directamente desde sitios externos. Podría también ser indexada por motores de búsqueda."
- who_sees_profile_q: "¿Quién puede ver mi perfil público?"
- who_sees_updates_a: "Cualquiera puede ver los cambios, si visita tu página de perfil."
- who_sees_updates_q: "¿Quién puede ver las actualizaciones a mi perfil público?"
resharing_posts:
reshare_public_post_aspects_a: "No, cuando vuelves a compartir una publicación pública, esta se convierte automáticamente en una de tus publicación públicas. Para compartirla solamente con ciertos aspectos, copia y pega el contenido de esta en una nueva publicación."
reshare_public_post_aspects_q: "¿Puedo volver a compartir una publicación pública solo para ciertos aspectos?"
diff --git a/config/locales/diaspora/es.yml b/config/locales/diaspora/es.yml
index a366bc7bb..6d20ada0f 100644
--- a/config/locales/diaspora/es.yml
+++ b/config/locales/diaspora/es.yml
@@ -33,7 +33,7 @@ es:
reshare:
attributes:
root_guid:
- taken: "Es buena, ¿eh? ¡Ya habías compartido esa publicación!"
+ taken: "Es buena, ¿eh? ¡Ya habías compartido esa publicación!"
user:
attributes:
email:
@@ -69,7 +69,7 @@ es:
zero: "%{count} comentarios"
current_segment: "El período actual tiene un promedio de <b>%{post_yest}</b> publicaciones por usuario, de <b>%{post_day}</b>"
daily: "Diario"
- display_results: "Mostrando resultados del período <b>%{segment}</b>"
+ display_results: "Mostrando resultados del período %{segment}"
go: "Adelante"
month: "Mes"
posts:
@@ -159,7 +159,11 @@ es:
description: "Permite que la aplicación lea tu perfil básico"
name: "perfil básico"
picture:
+ description: "Esto otorga permisos de imagen a la aplicación."
name: "fotografía"
+ profile:
+ description: "Esto permite que la aplicación lea tu perfil completo"
+ name: "Perfil completo"
read:
description: "Esto permite a la aplicación leer tu portada, tus conversaciones y tu perfil completo"
name: "leer perfil, portada y conversaciones"
@@ -252,7 +256,7 @@ es:
success: "Tu aspecto, %{name}, fue editado con éxito."
blocks:
create:
- failure: "No puede ignorar a este usuario. #evasion"
+ failure: "No pude ignorar a este usuario. #evasion"
success: "Bien, no verás a esa persona en tu entrada otra vez. #silencio!"
destroy:
failure: "No podría dejar de ignorar a ese usuario. #evasion"
@@ -262,6 +266,13 @@ es:
heading: "Marcador"
post_something: "Publica en Diaspora*"
cancel: "Cancelar"
+ color_themes:
+ dark: "Oscuro"
+ dark_green: "Verde oscuro"
+ egyptian_blue: "Azul egipcio"
+ magenta: "Magenta"
+ original: "Gris original"
+ original_white: "Fondo blanco original"
comments:
create:
error: "Hubo un error al comentar."
@@ -321,6 +332,7 @@ es:
delete: "Eliminar"
email: "Correo Electrónico"
error_messages:
+ csrf_token_fail: "El token CSFR no es válido. Por favor, inicia la sesión e inténtalo de nuevo."
helper:
correct_the_following_errors_and_try_again: "Corrige los siguientes errores e inténtalo de nuevo."
need_javascript: "Esta web necesita JavaScript para funcionar correctamente. Si lo desactivaste, por favor actívalo y actualiza la página."
@@ -368,9 +380,11 @@ es:
add_contact_roster_q: "¿Cómo puedo chatear con alguien en Diaspora*?"
contacts_page: "página de contactos"
title: "Chat"
+ community_guidelines: "normas de la comunidad"
faq: "Preguntas Más Frecuentes"
foundation_website: "página web de la fundación Diaspora*"
getting_help:
+ get_support_a_discourse: "Buscar discusiones anteriores relativas a tu pregunta o abrir un nuevo hilo en nuestra plataforma %{discourse}"
get_support_a_faq: "Lee nuestra página %{faq} en la wiki"
get_support_a_hashtag: "Pregunta en un mensaje público en diaspora* usando la etiqueta %{question}"
get_support_a_irc: "Únete a nosotros en %{irc} (chat en vivo)"
@@ -400,7 +414,6 @@ es:
mentions:
how_to_mention_a: "Escribe \"@\" y empieza a escribir su(s) nombre(s). Debería aparecer un menú desplegable para ayudarte en la selección. Ten en cuenta que solo es posible mencionar personas a aquellas personas que se encuentren en tus aspectos."
how_to_mention_q: "¿Cómo puedo mencionar a alguien cuando hago una publicación?"
- mention_in_comment_a: "No, de momento no."
mention_in_comment_q: "¿Puedo mencionar a alguien en un comentario?"
see_mentions_a: "Sí, pulsa en \"@menciones\" en la columna izquierda de tu pagina principal."
see_mentions_q: "¿Hay alguna forma de ver las publicaciones en las cuales he sido mencionado?"
@@ -436,11 +449,8 @@ es:
format_text_q: "¿Cómo puedo formatear el texto en mis publicaciones (negrita, italica, etc.)?"
hide_posts_a: "Si apuntas tu mouse a la parte superior de una publicación, una X aparecerá en la derecha. Hazle click para ocultar la publicación y silenciar las notificaciones relacionadas. Puedes aún asi ver la publicación si visitas la pagina de perfil de la persona que le publico."
hide_posts_q: "¿Cómo oculto una publicación?"
- image_text: "texto de la imagen"
- image_url: "url de la imagen"
insert_images_a: "Haz click en el pequeño ícono de la camara para insertar una imagen en una publicación. Presiona la foto otra ves para agregar otra foto, o puedes seleccionar multipes fotos para subir de una vez."
- insert_images_comments_a1: "El siguiente codigo de marcado"
- insert_images_comments_a2: "puede ser usado para insertar imagenes desde la web tanto en comentarios como en publicaciones."
+ insert_images_comments_a: "Puedes usar Markdown para insertar una imagen desde la web en un comentario, como en los posts. Sin embargo, no puedes subir imágenes de tu ordenador directamente a los comentarios. Súbelas a un servicio de almacenamiento de imágenes y entonces insértales usando el botón de imagen encima del editor."
insert_images_comments_q: "¿Puedo insertar imágenes en los comentarios?"
insert_images_q: "¿Cómo puedo insertar imágenes en las publicaciones?"
post_location_a: "Pulsa el icono de localización al lado de la cámara en la ventana de publicación. Insertarás tu localización desde OpenStreetMap. Puedes editar tu localización (puedes escoger publicar sólo el nombre de la ciudad en la que estás en lugar de tu dirección exacta)."
@@ -469,14 +479,14 @@ es:
title: "Publicaciones privadas"
who_sees_post_a: "Sólo los conectados a diaspora* que hayas alojado en ese aspecto podrán ver tu publicación privada."
who_sees_post_q: "¿Cuando publico un mensage a un aspecto (ej., una publicación privada), quién puede verla?"
- private_profiles:
- title: "Perfil privado"
- whats_in_profile_a: "Biografia, localización, genero, y cumpleaños. Es la información en la sección inferior de la pagina de edición de perfil. Toda la información es opcional - depende de ti con que la llenas. Usuarios conectados que hayas agregado a tus aspectos, son las unicas personas que podrán ver tu perfil privado. Ellos podrán tambien ver las publicaciones privadas que se han hecho para los aspectos en los cuales se encuentran, mezcladas con tus publicaciones públicas, cuando visiten tu pagina de perfil."
- whats_in_profile_q: "¿Qué hay en mi perfil privado?"
- who_sees_profile_a: "Cualquier usuario conectado con el cual estés compartiendo (es decir, que hayas agregado a alguno de tus aspectos). En cualquier caso, gente siguiendote, pero a la cual no sigues, solo verá tu información pública."
- who_sees_profile_q: "¿Quién puede ver mi perfil privado?"
- who_sees_updates_a: "Cualquier contacto de tus aspectos podrá ver los cambios o actualizaciones de tu perfil privado. "
- who_sees_updates_q: "¿Quién puede ver las actualizaciones de mi perfil privado?"
+ profile:
+ title: "Perfil"
+ what_do_tags_do_a: "Ayudan a que la gente te conozca. La foto de tu perfil también aparecerá en el lado izquierdo de las páginas relativas a esas etiquetas, junto con cualquiera que las haya usado en su perfil básico."
+ what_do_tags_do_q: "¿Para qué sirven las etiquetas en mi perfil básico?"
+ whats_in_profile_a: "Tu perfil tiene dos partes: el perfil básico y el perfil extendido. Tu perfil básico contiene tu nombre, las cinco etiquetas que escogiste para describirte, y tu foto. Tu perfil extendido contiene tu biografía, localización, género y cumpleaños. Toda esta información es opcional - depende de ti si quieres proporcionarla, y puedes hacer que sea visible o anonima, como prefieras. Tu perfil extendido se muestra en la columna de la izquierda de la página de tu perfil, debajo de tu foto."
+ whats_in_profile_q: "¿Qué hay en mi perfil?"
+ who_sees_profile_a: "Tu perfil básico (nombre, foto y etiquetas) es público. Tu perfil extendido es privado por defecto, pero puedes hacerlo público si quieres. Sólo la gente con la que estás compartiendo (cualquiera que hayas agregado a alguno de tus aspectos) puede ver tu perfil extendido si lo mantienes en privado. Otras personas verás solo tu información pública. Cada información de perfil que hagas pública podrá ser vista por cualquiera, y puede ser indexada por buscadores."
+ who_sees_profile_q: "¿Quién puede ver mi perfil?"
public_posts:
can_comment_reshare_like_a: "Cualquier usuario de diaspora* conectado puede comentar, compartir o marcar como \"Me gusta\" tus publicaciones públicas."
can_comment_reshare_like_q: "¿Quién puede comentar, volver a compartir o hacer \"Me gusta\" en mis publicaciones públicas?"
@@ -489,16 +499,6 @@ es:
title: "Publicaciones públicas"
who_sees_post_a: "Cualquiera que use Internet puede potencialmente ver una publicación que marques como pública, así que pregúntate si realmente quieres que tu publicación sea pública. Es una buena forma de hacerse escuchar en todo el mundo."
who_sees_post_q: "Cuando publico algo de manera pública, ¿quién puede verlo?"
- public_profiles:
- title: "Perfiles públicos"
- what_do_tags_do_a: "Las etiquetas ayudan a la gente a conocerte. Tu foto de perfil también aparecerá en el lado izquierdo de las páginas de esas etiquetas, junto con cualquier otra persona que las tenga en su perfil público."
- what_do_tags_do_q: "¿Qué hacen las etiquetas de mi perfil público?"
- whats_in_profile_a: "Tu nombre, las cinco etiquetas que elijas para describirte a ti mismo, y tu foto. Están en la sección superior de la pagina de edición de perfil. Tú puedes hacer que esta información de perfil sea identificable o anónima. Tú pagina de perfil también muestra cualquier publicación pública que hayas hecho."
- whats_in_profile_q: "¿Que hay en mi perfil público?"
- who_sees_profile_a: "Cualquier usuario de diaspora* conectado, así como la inmensidad de internet, puede verlo. Cada perfil tiene una URL directa, así que puede ser enlazado directamente desde sitios externos y puede ser indexado por los motores de búsqueda."
- who_sees_profile_q: "¿Quién puede ver mi perfil público?"
- who_sees_updates_a: "Cualquier persona puede ver los cambios si visitan tu página de perfil."
- who_sees_updates_q: "¿Quién puede ver las actualizaciones de mi perfil público?"
resharing_posts:
reshare_private_post_aspects_a: "No es posible volver a compartir una publicación privada. Es por respeto a las intenciones del publicador original de solo compartirla con un grupo determinado de personas."
reshare_private_post_aspects_q: "¿Puedo volver a compartir una publicación privada sólo con algunos aspectos?"
@@ -573,6 +573,7 @@ es:
update_your_pod: "Actualiza tu pod"
update_your_pod_info: "Puedes encontrar %{update_instructions}"
invitation_codes:
+ already_logged_in: "Has sido invitado por %{inviter} para unirte a este pod, pero ya tienes la sesión iniciada."
not_valid: "Ese código de invitación ya no es válido"
invitations:
create:
@@ -580,7 +581,7 @@ es:
empty: "Por favor, introduce al menos una dirección de correo electrónico."
no_more: "No tienes más invitaciones."
note_already_sent: "Las invitaciones han sido enviadas a: %{emails}"
- rejected: "Hubo problemas con las siguientes direcciones de correo: "
+ rejected: "Hubo problemas con las siguientes direcciones de correo: %{emails}"
sent: "Las invitaciones han sido enviadas a: %{emails}"
new:
codes_left:
@@ -611,6 +612,8 @@ es:
settings: "Ajustes"
toggle_navigation: "Cambiar navegación"
likes:
+ create:
+ error: "¡Falló el 'me gusta'!"
destroy:
error: "Ocurrió un error al quitar el \"Me gusta\""
limited: "Limitado"
@@ -661,7 +664,7 @@ es:
mentioned:
one: "%{actors} te ha mencionado en %{post_link}."
other: "%{actors} te han mencionado en %{post_link}."
- zero: "%{actors} menciones en %{post_link}."
+ zero: "%{actors} te han mencionado en %{post_link}."
mentioned_deleted:
one: "%{actors} te ha mencionado en una publicación eliminada."
other: "%{actors} te han mencionado en una publicación eliminada."
@@ -695,6 +698,29 @@ es:
confirm_email:
click_link: "Para activar tu nueva dirección de correo %{unconfirmed_email}, sigue este enlace:"
subject: "Por favor activa tu nueva dirección de correo %{unconfirmed_email}"
+ csrf_token_fail:
+ body: |-
+ Hola %{name},
+
+ diaspora* ha detectado un intento de acceso a tu cuenta que podría ser no autorizado. Para evitar que tu información pueda verse comprometida, se ha cerrado tu sesión. No te preocupes, puedes entrar otra vez de forma segura.
+
+ Se ha recibido una solicitud usando un token CSFR incorrecto o incompleto. Podría ser algo inocente, pero podría ser también una petición falsificada procedente de otra web (CSFR).
+
+ Esto podría haber sido causado por:
+
+ - Una extensión manipulando la solicitud o realizando solicitudes sin emplear un token (código de seguridad);
+ - Una pestaña abierta de la sesión anterior;
+ - Otra página web realizando solicitudes, con o sin tu permiso;
+ - Otras aplicaciones externas;
+ - Código malicioso intentando acceder a tu información.
+
+ Para más información acerca de CSFR ver %{link}%{link}.
+
+ Si ves este mensaje de forma repetida, por favor revisa los anteriores puntos, incluyendo las extensiones de tu buscador de internet. 
+
+ Gracias,
+ El robot del email de dispora*!
+ subject: "Hemos recibido una solicitud no autorizada desde tu cuenta, %{name}"
email_sent_by_diaspora: "Este correo electrónico fue enviado por %{pod_name}. Si quieres dejar de recibir correos como este,"
export_email:
body: |-
@@ -932,8 +958,14 @@ es:
destroyed: "La publicación ha sido eliminada"
failed: "Algo salió mal"
title: "Resúmen de Informes"
+ unreviewed_reports:
+ one: "Hay %{count} reporte sin revisar."
+ other: "Hay %{count} reportes sin revisar."
+ zero: "No hay ningún reporte sin revisar."
reshares:
comment_email_subject: "%{resharer} compartió la publicación de %{author}"
+ create:
+ error: "Error al compartir."
reshare:
deleted: "La publicación original fue eliminada por su autor."
reshare_confirmation: "¿Compartir la publicación de %{author}?"
@@ -973,9 +1005,9 @@ es:
toggle:
one: "En %{count} aspecto"
other: "En %{count} aspectos"
- zero: "Añadir contacto"
+ zero: "En ningún aspecto"
invitations:
- by_email: "Por correo electrónico"
+ by_email: "Invita a más personas a través de correo electrónico."
invite_your_friends: "Invita a tus contactos"
invites: "Invitaciones"
share_this: "¡Comparte este enlace a través de correo electrónico, blog o tu red social favorita!"
@@ -984,11 +1016,11 @@ es:
control_your_audience: "Controla tu público"
logged_in: "Conectado a %{service}"
manage: "Gestionar servicios conectados"
- new_user_welcome_message: "Utiliza #etiquetas para clasificar tus publicaciones y encontrar gente que comparta tus intereses. Llama a gente asombrosa usando las @Menciones"
+ new_user_welcome_message: "Utiliza #etiquetas para clasificar tus publicaciones y encuentra a gente que comparte tus intereses. Nombra a personas especiales usando @Mentions"
outside: "Los mensajes públicos podrán ser vistos por otros fuera de Diaspora*."
share: "Comparte"
title: "Configurar los servicios conectados"
- visibility_dropdown: "Usa este menú desplegable para cambiar la visibilidad de tu publicación. (Sugerimos hacerlo público la primera vez.)"
+ visibility_dropdown: "Usa este menú desplegable para cambiar la visibilidad de tu publicación. (Te sugerimos hacerlo público la primera vez.)"
publisher:
discard_post: "Descartar publicación"
formatWithMarkdown: "Puedes usar %{markdown_link} para dar formato al mensaje."
@@ -1114,6 +1146,7 @@ es:
comment_on_post: "...alguien comentó en tu publicación"
current_password: "Contraseña actual"
current_password_expl: "con la que inicias sesión..."
+ default_post_visibility: "Seleccionados los aspectos por defecto para publicar."
download_export: "Descargar mi perfil"
download_export_photos: "Descargar mis fotografías"
edit_account: "Editar cuenta"
diff --git a/config/locales/diaspora/fi.yml b/config/locales/diaspora/fi.yml
index 3c832b4f7..ba9c2050a 100644
--- a/config/locales/diaspora/fi.yml
+++ b/config/locales/diaspora/fi.yml
@@ -331,7 +331,6 @@ fi:
mentions:
how_to_mention_a: "Kirjoita \"@\" merkki ja ryhdy kirjoittamaan hänen nimeään. Alasvetovalikon pitäisi ilmestyä, josta voit valita hänet helpommin. Huomioi, että voit mainita ainoastaan henkilöitä, joita olet lisännyt johonkin näkymään."
how_to_mention_q: "Kuinka mainitsen jonkun tehdessäni julkaisua?"
- mention_in_comment_a: "Ei, et tällä hetkellä."
mention_in_comment_q: "Voinko mainita jonkun kommentissa?"
see_mentions_a: "Kyllä, klikkaa \"Maininnat\" aloitussivun vasemmassa sarakkeessa."
see_mentions_q: "Onko minun mahdollista nähdä julkaisut joissa minut on mainittu?"
@@ -367,11 +366,7 @@ fi:
format_text_q: "Kuinka voin muotoilla julkaisuni tekstiä (lihavointi, kursiivi jne.)?"
hide_posts_a: "Jos osoitat hiirelläsi julkaisusi yläosaa, ilmestyy oikealle X. Klikkaa sitä piilottaaksesi julkaisun ja estääksesi siihen liittyvät ilmoitukset. Voit edelleen nähdä piilotetun julkaisun, jos vierailet julkaisun tehneen henkilön profiilisivulla."
hide_posts_q: "Kuinka piilotan julkaisun? / Kuinka estän saamasta ilmoituksia julkaisusta johon olen kommentoinut?"
- image_text: "kuvateksti"
- image_url: "kuvan url"
insert_images_a: "Klikkaa pientä kamerakuvaketta lisätäksesi kuvan julkaisuun. Klikkaa kamerakuvaketta uudelleen lisätäksesi muita kuvia, tai voit valita useita kuvia ladataksesi ne samalla kertaa."
- insert_images_comments_a1: "Seuraava Markdown-koodi"
- insert_images_comments_a2: "voidaan käyttää kuvien lisäämiseksi Internetistä kommenttehin ja julkaisuihin."
insert_images_comments_q: "Voinko lisätä kuvia kommentteihini?"
insert_images_q: "Kuinka lisään kuvia julkaisuihini?"
post_location_a: "Klikkaa kameran vieressä sijaitsevaa pinniä julkaisijassa. Se lisää sijaintisi OpenStreetMapin avulla. Voit muokata sijaintiasi – haluat ehkä lisätä tietyn katuosoitteen sijaan vain kaupungin."
@@ -400,14 +395,6 @@ fi:
title: "Yksityiset julkaisut"
who_sees_post_a: "Vain kirjautuneet Diaspora* käyttäjät, jotka olet sijoittanut kyseiseen näkymään voivat nähdä yksityisen julkaisusi."
who_sees_post_q: "Kun lähetän julkaisun näkymälle (esim. yksityinen julkaisu) kuka voi nähdä sen?"
- private_profiles:
- title: "Yksityiset profiilit"
- whats_in_profile_a: "Elämäkerta, sijainti, sukupuoli ja syntymäpäivä. Ne tiedot, jotka ovat profiilisivun alaosassa. Kaikki tämä tieto on vapaaehtoista - on siis oma valintasi haluatko täydentää ne sivullesi. Kirjautuneet käyttäjät, jotka olet lisännyt johonkin näkymääsi, ovat ainota jotka voivat nähdä yksityisen profiilisi. He näkevät myös yksityiset julkaisusi jotka julkaiset niihin näkymiin mihin olet heidät sijoittanut, mukaan lukien julkiset julkaisusi, kun he vierailevat profiilisivullasi."
- whats_in_profile_q: "Mitä julkisessa profiilissani on?"
- who_sees_profile_a: "Kuka tahansa kirjautunut käyttäjä, jonka kanssa jaat (toisin sanoen, olet lisännyt hänet johonkin näkymistäsi). Mutta sellaiset henkilöt jotka seuraavat sinua, mutta joita et itse seuraa, voivat nähdä vain julkiset tietosi."
- who_sees_profile_q: "Kuka voi nähdä yksityisen profiilini?"
- who_sees_updates_a: "Kuka tahansa joka on jossakin näkymässäsi voi nähdä muutokset yksityisessä profiilissasi. "
- who_sees_updates_q: "Kuka tai ketkä voivat nähdä yksityiseen profiiliini tekemät muutokset?"
public_posts:
can_comment_reshare_like_a: "Kuka tahansa kirjautunut Diaspora* käyttäjä voi kommentoida, uudelleenjakaa tai tykätä julkista julkaisuasi."
can_comment_reshare_like_q: "Kuka voi kommentoida, uudelleenjakaa tai tykätä julkista julkaisuani?"
@@ -420,16 +407,6 @@ fi:
title: "Julkiset julkaisut"
who_sees_post_a: "Jokaisella internetin käyttäjällä on mahdollisuus nähdä julkaisu jonka merkitset julkiseksi. Pidä siis huoli, että todella haluat sen olevan julkinen. Tämä on erinomainen tapa saada näkyvyyttä julkaisuillesi."
who_sees_post_q: "Kun julkaisen jotain julkisesti kuka voi nähdä sen?"
- public_profiles:
- title: "Julkiset profiilit"
- what_do_tags_do_a: "Ne auttavat ihmisiä tuntemaan sinut. Profiilikuvasi on myös näkyvillä sellaisten sivujen vasemmalla puolen, jotka on merkitty samalla tagilla kaikkien muiden käyttäjien kanssa, joilla myös on samanlainen tagi."
- what_do_tags_do_q: "Mitä tehtävä on tageilla julkisessa profiilissani?"
- whats_in_profile_a: "Nimesi, viisi tagia jotka olet valinnut kuvaamaan itseäsi ja kuvasi. Nämä tiedot löytyvät profiilisivusi yläosasta. Voit määrittää nämä tiedot niin todenmukaisiksi tai tuntemattoiksi kuin haluat. Profiilisivusi näyttää myös jokaisen julkisen julkaisusi, jonka olet tehnyt."
- whats_in_profile_q: "Mitä julkisessa profiilissani on?"
- who_sees_profile_a: "Jokainen kirjautunut diaspora* käyttäjä ja kuka tahansa Internetistä voi nähdä sen. Jokaisessa profiilissa on suora URL johon voidaan linkittää ulkopuolisista sivuista. Myös hakukoneet voivat luetteloida sen."
- who_sees_profile_q: "Kuka voi nähdä julkisen profiilini?"
- who_sees_updates_a: "Jokainen joka vierailee profiilisivullasi."
- who_sees_updates_q: "Kuka voi nähdä päivitykset julkiseen profiiliini?"
resharing_posts:
reshare_private_post_aspects_a: "Et. Ei ole mahdollilsta uudelleenjakaa yksityistä julkaisua. Tällä kunnioitetaan alkuperäisen julkaisijan tarkoitusta jakaa vain tietyille henkilöille."
reshare_private_post_aspects_q: "Voinko uudelleenjakaa yksityisen julkaisun vain tietyille näkymille?"
diff --git a/config/locales/diaspora/fr.yml b/config/locales/diaspora/fr.yml
index 6f6f7099b..b57c2d5fa 100644
--- a/config/locales/diaspora/fr.yml
+++ b/config/locales/diaspora/fr.yml
@@ -270,6 +270,13 @@ fr:
heading: "Bookmarklet"
post_something: "Publiez sur diaspora*"
cancel: "Annuler"
+ color_themes:
+ dark: "Sombre"
+ dark_green: "Vert sombre"
+ egyptian_blue: "Bleu égyptien"
+ magenta: "Magenta"
+ original: "Gris par défaut"
+ original_white: "Fond blanc"
comments:
create:
error: "Impossible de commenter."
@@ -379,9 +386,11 @@ fr:
add_contact_roster_q: "Comment chatter avec quelqu'un dans diaspora* ?"
contacts_page: "page des contacts"
title: "Chat"
+ community_guidelines: "Lignes directrices pour la communauté"
faq: "FAQ"
foundation_website: "site Internet de la fondation diaspora*"
getting_help:
+ get_support_a_discourse: "Cherchez des discussions en rapport avec votre demande ou ouvrez un nouveau fil de discussion sur notre plate-forme %{discourse}."
get_support_a_faq: "Lire la page %{faq} de notre wiki"
get_support_a_hashtag: "Posez une question dans un message public sur diaspora* en utilisant le hashtag %{question}"
get_support_a_irc: "Rejoignez-nous sur %{irc} (Tchat instantané)"
@@ -411,7 +420,6 @@ fr:
mentions:
how_to_mention_a: "Tapez le symbole \"@\" et commencez à taper leur nom. Un menu déroulant devrait apparaître pour vous permettre de les choisir plus facilement. Notez qu'il n'est possible de mentionner que des gens que vous avez ajoutés à un aspect."
how_to_mention_q: "Comment puis-je mentionner quelqu'un lorsque je rédige un message ?"
- mention_in_comment_a: "Non, pas pour le moment."
mention_in_comment_q: "Puis-je mentionner quelqu'un dans un commentaire ?"
see_mentions_a: "Oui, cliquez sur \"@Mentions\" dans la colonne de gauche de votre page d'accueil."
see_mentions_q: "Il y a t-il un moyen de voir les messages dans lesquels j'ai été mentionné ?"
@@ -447,11 +455,8 @@ fr:
format_text_q: "Comment puis-je formater le texte de mes messages (gras, italique, etc.) ?"
hide_posts_a: "Si vous pointez votre souris en haut d'un message, une croix apparaît sur la droite. Cliquez dessus pour masquer le message et empêcher toute notification le concernant. Vous pourrez toujours voir le message si vous visitez la page de profil de la personne qui l'a rédigé."
hide_posts_q: "Comment puis-je masquer un message ?"
- image_text: "texte de l'image"
- image_url: "url de l'image"
insert_images_a: "Cliquez sur la petite icône représentant un appareil photo pour insérer une image dans un message. Appuyez une seconde fois pour ajouter une autre photo, ou vous pouvez sélectionner de multiples photos à téléverser en une seule fois."
- insert_images_comments_a1: "Vous ne pouvez pas téléverser des images dans les commentaires mais le code Markdown suivant"
- insert_images_comments_a2: "cela peut être utilisé pour insérer des images à partir du web dans les commentaires ou les messages."
+ insert_images_comments_a: "Comme dans le cas des messages, vous pouvez utiliser la syntaxe Markdown pour insérer une image à partir du web dans un commentaire. Par contre, il n'est pas possible de téléverser une image stockée sur votre ordinateur. Dans ce cas, commencez par téléverser l'image sur un site d'hébergement d'images, puis insérez-la via l'icône d'insertion d'image de la barre d'outils dans la partie supérieure de la boîte de rédaction."
insert_images_comments_q: "Puis-je insérer des images dans un commentaire ?"
insert_images_q: "Comment puis-je insérer des images dans un message ?"
post_location_a: "Dans l'éditeur, cliquez sur l'icône en forme d'épingle à côté de l'appareil photo. Ceci va insérer votre emplacement à partir d'OpenStreetMap. Vous pourrez modifier votre position - pour inclure uniquement la ville plutôt que la rue par exemple."
@@ -480,14 +485,14 @@ fr:
title: "Messages privés"
who_sees_post_a: "Seuls les utilisateurs placés dans cet aspect et connectés à diaspora* peuvent voir votre message privé."
who_sees_post_q: "Lorsque j'envoie un message à un aspect (c'est-à-dire un message privé), qui peut le voir ?"
- private_profiles:
- title: "Profils privés"
- whats_in_profile_a: "La biographie, la localisation, le genre, et l'anniversaire. Ce sont les éléments dans le bas de la section de l'édition de la page de profil. Toutes ces informations sont optionnelles — c'est à vous de décider si vous les renseignez ou non. Les utilisateurs connectés que vous avez ajoutés à vos aspects sont les seuls qui peuvent lire votre profil privé. Ils verront aussi les messages privés publiés dans les aspects dont ils font partie, mélangés avec vos publications publiques, lorsqu'ils visiteront votre page de profil."
- whats_in_profile_q: "Qu'est ce que mon profil privé ?"
- who_sees_profile_a: "N'importe quel utilisateur connecté avec lequel vous partagez (ce qui signifie que vous l'avez ajouté dans l'un de vos aspects). Les gens qui vous suivent, mais que vous ne suivez pas, verrons uniquement vos informations publiques."
- who_sees_profile_q: "Qui peut voir mon profil privé ?"
- who_sees_updates_a: "N'importe qui dans vos aspects peut voir les modifications de votre profil privé. "
- who_sees_updates_q: "Qui peut voir les mises à jour de mon profil privé ?"
+ profile:
+ title: "Profil"
+ what_do_tags_do_a: "Ces tags permettent aux gens de mieux vous connaître. Ils seront visibles, ainsi que votre image de profil, dans la partie gauche des pages de flux associées à ces tags ; le profil de base de toute autre personne dont le profil contient un tag identique à un des vôtres apparaîtra également dans la partie gauche."
+ what_do_tags_do_q: "Pourquoi fournir des tags dans mon profil ?"
+ whats_in_profile_a: "Votre profil est subdivisé en deux parties : un profil élémentaire (basique) et un profil complet. Votre profil basique comprend vos nom et prénom, les cinq tags que vous avez choisis pour vous décrire et votre photo. Votre profil complet comprend des informations d'ordre biographique, de localisation, de genre et de date d'anniversaire. Aucune de ces données n'est obligatoire ; vous êtes libre de les fournir ou pas, qu'elles soient authentiques ou imaginaires. Votre profil complet apparaît dans la colonne de gauche de votre page de profil, sous votre photo."
+ whats_in_profile_q: "Que trouve-t-on dans mon profil ?"
+ who_sees_profile_a: "Votre profil basique (nom, image du profil et #tags) est public. Par défaut, votre profil complet est privé, mais rien ne vous empêche de le rendre public. Un profil complet privé est uniquement visible par les personnes avec qui vous partagez (les personnes que vous avez ajoutées à un de vos aspects) ; les autres ne peuvent voir que vos données publiques ; celles-ci sont visibles par tout internaute et peuvent être indexées par des moteurs de recherche."
+ who_sees_profile_q: "Qui peut voir mon profil ?"
public_posts:
can_comment_reshare_like_a: "N'importe quel utilisateur connecté à diaspora* peut commenter, repartager, ou aimer votre message public."
can_comment_reshare_like_q: "Qui peut commenter, repartager, ou aimer mon message public ?"
@@ -500,16 +505,6 @@ fr:
title: "Messages publics"
who_sees_post_a: "N'importe qui utilisant internet peut potentiellement voir un message que vous marquez comme public, donc soyez sûrs de vouloir rendre ce message public. C'est le meilleur moyen de s'ouvrir sur le monde."
who_sees_post_q: "Lorsque je publie quelque chose publiquement, qui peut le voir ?"
- public_profiles:
- title: "Profils publics"
- what_do_tags_do_a: "Ils aident les gens à mieux vous connaître. Votre photo de profil apparaîtra également dans le panneau latéral sur la gauche des pages de ces tags, avec tous ceux qui les ont dans leur profil public."
- what_do_tags_do_q: "Qu'est ce que font les tags sur mon profil public ?"
- whats_in_profile_a: "Votre nom, les cinq tags que vous choisissez pour vous décrire, et votre photo. C'est l'ensemble des éléments dans la partie haute de votre page d'édition de profil. Vous pouvez créer un profil avec des informations vous identifiant ou vous laissant anonyme selon votre souhait. Votre page de profil montre uniquement les messages publics que vous avez créés."
- whats_in_profile_q: "Qu'y a-t-il dans mon profil public ?"
- who_sees_profile_a: "N'importe quel utilisateur connecté à diaspora*, ainsi que le reste d'Internet, peut le voir. Chaque profil a une URL directe, permettant d'avoir un lien pointant dessus depuis des sites extérieurs. Il peut être indexé par les moteurs de recherche."
- who_sees_profile_q: "Qui peut voir mon profil public ?"
- who_sees_updates_a: "N'importe qui peut voir ces changements en visitant votre page de profil."
- who_sees_updates_q: "Qui peut voir les mises à jour de mon profil public ?"
resharing_posts:
reshare_private_post_aspects_a: "Non, il n'est pas possible de repartager un message privé. Ceci dans le but de respecter les intentions du rédacteur initial qui souhaite uniquement partager avec un groupe particulier de personnes."
reshare_private_post_aspects_q: "Puis-je repartager un message privé uniquement avec certains aspects ?"
@@ -661,6 +656,7 @@ fr:
mark_read: "Marquer comme lu"
mark_unread: "Marquer comme non lu"
mentioned: "Vous mentionnant"
+ mentioned_in_comment: "Vous mentionnant dans un commentaire"
no_notifications: "Vous n'avez pas encore de notifications."
notifications: "Notifications"
reshared: "Repartagé"
@@ -683,6 +679,12 @@ fr:
one: "%{actors} vous a mentionné dans un message supprimé."
other: "%{actors} vous ont mentionné dans un message supprimé."
zero: "Personne ne vous a mentionné dans un message supprimé."
+ mentioned_in_comment:
+ one: "%{actors} vous a mentionné dans un <a href=%{comment_path}>commentaire</a> sur le message %{post_link}."
+ other: "%{actors} vous ont mentionné dans un <a href=%{comment_path}>commentaire</a> sur le message %{post_link}."
+ mentioned_in_comment_deleted:
+ one: "%{actors} vous a mentionné sur un commentaire supprimé."
+ other: "%{actors} vous ont mentionné sur un commentaire supprimé."
private_message:
one: "%{actors} vous a envoyé un message."
other: "%{actors} vous ont envoyé un message."
@@ -808,6 +810,9 @@ fr:
mentioned:
limited_post: "Vous avez été mentionné dans une publication restreinte."
subject: "%{name} vous a mentionné(e) sur diaspora*"
+ mentioned_in_comment:
+ limited_post: "Vous avez été mentionné dans un commentaire sur une publication restreinte."
+ reply: "Répondre ou voir cette conversation >"
private_message:
reply_to_or_view: "Répondre ou voir cette conversation >"
subject: "Vous avez un nouveau message privé"
@@ -1173,6 +1178,7 @@ fr:
last_exported_at: "(Dernière mise à jour à %{timestamp})"
liked: "…quelqu'un a aimé votre message."
mentioned: "…l'on vous mentionne dans un message."
+ mentioned_in_comment: "…vous êtes mentionné dans un commentaire"
new_password: "Nouveau mot de passe"
private_message: "…vous recevez un message privé."
receive_email_notifications: "Recevoir des notifications par courrier électronique lorsque…"
diff --git a/config/locales/diaspora/he.yml b/config/locales/diaspora/he.yml
index 39ecf8b31..6fcc0c0cc 100644
--- a/config/locales/diaspora/he.yml
+++ b/config/locales/diaspora/he.yml
@@ -250,7 +250,6 @@ he:
here: "כאן"
irc: "IRC"
mentions:
- mention_in_comment_a: "לא, לא כרגע."
mention_in_comment_q: "האם אני יכול להזכיר מישהו בהערה?"
see_mentions_q: "האם יש דרך לראות פוסטים שבהם אני מוזכר?"
third_party_tools: "כלים צד שלישי"
diff --git a/config/locales/diaspora/hu.yml b/config/locales/diaspora/hu.yml
index e0dcd1b17..b7c7a00dd 100644
--- a/config/locales/diaspora/hu.yml
+++ b/config/locales/diaspora/hu.yml
@@ -291,14 +291,14 @@ hu:
foundation_website: "diaspora* alapítvány"
getting_help:
get_support_a_faq: "tekintsd meg %{faq} oldalunkat"
- get_support_a_hashtag: "kérdezz magyarul a közösségi hálón, nyilvános bejegyzésben a %{question} címke használatával"
+ get_support_a_hashtag: "kérdezz nyilvános bejegyzésben a közösségi hálón a %{question} (vagy magyarul a #kérdés) címke használatával"
get_support_a_irc: "kapcsolódj be %{irc}-en az élő csevegésbe"
get_support_a_tutorials: "nézd át az általunk készített %{tutorials}at"
get_support_a_website: "látogasd meg a %{link} honlapját"
get_support_a_wiki: "kutass a %{link} adattárunkban"
get_support_q: "Mit tegyek, ha a kérdésemre itt nem találok választ? Hol kaphatok még felvilágosítást?"
- getting_started_a: "Szerencséd van. %{tutorial_series} nevű bemutató oldalunk lépésről lépésre végigvezet téged a regisztrációs eljáráson és megismerteti a diaspora* használatához szükséges alapvető tudnivalókat."
- getting_started_q: "Húha! A kezdéshez elkélne némi alapvető segítség!"
+ getting_started_a: "Szerencséd van. %{tutorial_series} nevű bemutató oldalunk lépésről lépésre végigvezet téged a regisztrációs folyamaton és megismerteti a diaspora* használatához szükséges alapvető tudnivalókat."
+ getting_started_q: "Segítség! A kezdéshez elkélne egy kis útmutatás!"
title: "Források a tájékozódáshoz"
getting_started_tutorial: "'Kezdő lépések'"
here: "itt"
@@ -311,7 +311,6 @@ hu:
mentions:
how_to_mention_a: "Írj le egy \"@\" jelet és kezdd el gépelni az illető nevét. Egy legördülő menü fog megjelenni annak érdekében, hogy könnyebben választhass. Fontos, hogy csak azokat az embereket tudod megemlíteni, akiket hozzáadtál valamely csoporthoz."
how_to_mention_q: "Hogyan említhetek meg valakit, amikor bejegyzést írok?"
- mention_in_comment_a: "Jelenleg ez még nem lehetséges."
mention_in_comment_q: "Megemlíthetek valakit egy hozzászólásban?"
see_mentions_a: "Igen, kattints a \"Megemlítettek\" feliratra a kezdőlapod bal oldalán."
see_mentions_q: "Van rá mód, hogy megtekinthessem azokat a bejegyzéseket, melyekben megemlítettek engem?"
@@ -337,11 +336,7 @@ hu:
embed_multimedia_q: "Hogyan ágyazhatok be mozgóképet, hangot vagy más multimédiás tartalmat a bejegyzésembe?"
format_text_a: "A %{markdown} nevű egyszerűsített leíró rendszer segítségével, melynek pontos alaki követelményeit %{here} találod. Az előnézet gomb ekkor különösen hasznosnak bizonyulhat, hiszen segítségével láthatod, hogyan fog kinézni az üzeneted mielőtt megosztod azt."
format_text_q: "Hogyan formázhatom meg a bejegyzéseim szövegét (kövér, dőlt, stb.)?"
- image_text: "kép szövege"
- image_url: "kép url"
insert_images_a: "Kattints a kis fényképezőgép jelére, ha képet szeretnél beszúrni a bejegyzésedbe. Nyomd meg az ikont ismételten, ha újabbat is szeretnél hozzáadni. Lehetőséged van több képet is egyszerre kiválasztani."
- insert_images_comments_a1: "Nem tudsz képeket feltölteni hozzászólásokba, de a következő markdown kód"
- insert_images_comments_a2: "használható a világhálóról származó képek bejegyzésekbe és hozzászólásokba való beillesztéséhez"
insert_images_comments_q: "Beilleszthetek képeket a hozzászólásaimba?"
insert_images_q: "Hogyan helyezhetek el képeket a bejegyzésemben?"
size_of_images_a: "Nem. A képek automatikusan átméreteződnek, hogy megfelelően épülhessenek be a hírfolyamba. A markdown nem támogatja a képek átméretezését szolgáló kódok semmilyen formáját."
@@ -349,6 +344,7 @@ hu:
stream_full_of_posts_a1: "A hírfolyamod három fajta bejegyzésből áll:"
stream_full_of_posts_li3: "Végül olyan nyilvános bejegyzések, melyek az úgymond \"figyelem középpontjában\" álló, vagyis a közösség által javasolt népszerű tagoktól származnak. Az ilyen bejegyzések bármikor elrejthetőek, ha azt a beállításainkban kikapcsoljuk (fiók fül - \"A figyelem középpontjában szereplő tartalmak megjelenítése a hírfolyamban\")."
stream_full_of_posts_q: "Miért van tele a hírfolyamom olyan emberek bejegyzéseivel, akiket nem ismerek és nem is osztok meg velük semmit?"
+ title: "Bejegyzések"
private_posts:
can_comment_a: "Csak azok a bejelentkezett diaspora* felhasználók tehetik meg ezt, akiket az érintett csoportba helyeztél."
can_comment_q: "Ki nyilváníthatja ki tetszését a magánjellegű bejegyzéseimre és ki szólhat hozzájuk?"
@@ -357,29 +353,14 @@ hu:
see_comment_a: "Csak azok az emberek láthatják a hozzászólásokat és tetszésnyilvánításokat, akik szerepeltek a tartalmat eredetileg megosztó felhasználó általa kiválasztott csoportjaiban. "
see_comment_q: "Ki láthatja azt, ha hozzászólok egy bejegyzéshez vagy tetszést nyilvánítok?"
title: "Személyes bejegyzések"
- private_profiles:
- title: "Személyes adatlapok"
- whats_in_profile_a: "Rövid önéletrajzot, tartózkodási helyet, nemet és születésnapot. Az \"adatlap szerkesztése\" oldal alsó részén található. Az adatok megadása nem kötelező - rajtad múlik, hogy kitöltöd-e vagy sem. Kizárólag azok a bejelentkezett felhasználók láthatják a személyes adatlapodat, akiket hozzáadtál valamelyik csoportodhoz. Amikor valaki meglátogatja az adatlapodat, a nyilvános bejegyzéseiddel egyetemben azokat a személyes bejegyzéseket is látni fogja, amelyek azon csoport(ok) számára íródtak, ahová az illetőt soroltad."
- whats_in_profile_q: "Mit tartalmaz a személyes adatlapom?"
- who_sees_profile_a: "Bármely bejelentkezett felhasználó, akivel megosztasz (vagyis akit hozzáadtál valamely csoportodhoz). Ugyanakkor, azok a személyek, akik téged követnek, de te nem követed őket, csak a nyilvános adataidat láthatják."
- who_sees_profile_q: "Ki láthatja a személyes adatlapomat?"
- who_sees_updates_a: "A csoportjaidból bárki láthatja a személyes adatlapod változásait. "
- who_sees_updates_q: "Ki látja a személyes adatlapom frissítéseit?"
public_posts:
find_public_post_a: "Nyilvános bejegyzéseid megjelennek minden téged követő személy hírfolyamában. Ha #címkéket is elhelyeztél benne, akkor bárki, aki követi azokat, meg fogja találni a bejegyzéseidet a saját folyamában. Ezen kívül minden nyilvános bejegyzés egy meghatározott elérési úttal is rendelkezik, amit bárki megnyithat - még akkor is, ha nincs bejelentkezve - így az ilyen bejegyzések közvetlenül lehivatkozhatóak Twitterből, blogokból, stb. Nem mellékesen a különböző internetes keresők is nyilvántartásba vehetik őket."
find_public_post_q: "Hogy találhatják meg mások a nyilvános bejegyzésemet?"
title: "Nyilvános bejegyzések"
who_sees_post_a: "Elviekben bármely internet felhasználó láthatja az ilyen bejegyzéseidet, ezért gondold meg, hogy biztosan a széles nyilvánosságnak szánod-e az adott tartalmat. Ugyanakkor jó lehetőség, hogy elérd üzeneteddel a tágas világot."
who_sees_post_q: "Ki láthatja a nyilvánosnak jelölt bejegyzésemet?"
- public_profiles:
- title: "Nyilvános adatlapok"
- what_do_tags_do_a: "Segítenek abban, hogy mások megismerhessenek téged. Az önarcképed is meg fog jelenni az egyes címkék oldalainak bal szélén, azokkal egyetemben, akik szintén megadtak a nyilvános adatlapjukon ilyeneket."
- what_do_tags_do_q: "Mi a szerepük a címkéknek a nyilvános adatlapomon?"
- whats_in_profile_a: "A nevedet, az öt címkét, melyet saját magad jellemzésére választhatsz és a fényképedet. Mindezek az 'adatlapom szerkesztése' oldal felső részén találhatóak. Te döntöd el, hogy névtelen szeretnél lenni, vagy könnyedén azonosítható. Az adatlapod oldala ezen kívül az összes nyilvános bejegyzésedet is tartalmazza."
- whats_in_profile_q: "Mit tartalmaz a nyilvános adatlapom?"
- who_sees_profile_q: "Ki láthatja a nyilvános adatlapomat?"
- who_sees_updates_a: "Bárki láthatja a változásokat, ha meglátogatják az adatlapodat."
- who_sees_updates_q: "Ki láthatja a nyilvános adatlapom frissítéseit?"
+ resharing_posts:
+ title: "Bejegyzések újramegosztása"
sharing:
add_to_aspect_a1: "Tegyük fel, hogy Anna hozzáadja Bencét egy csoportjához, de ekkor Bence (még) nem adta hozzá Annát egyetlen csoporthoz sem. Ekkor:"
add_to_aspect_a2: "Mindez egyoldalú megosztásként ismert. Abban a pillanatban, hogy Bence szintén hozzáadja Annát valamely csoportjába, kölcsönössé válik a megosztás, vagyis mind Anna és mind Bence összes nyilvános- és kapcsolódó magánbejegyzése meg fog jelenni a másik hírfolyamában. "
@@ -427,7 +408,7 @@ hu:
other: "%{count} meghívó maradt még ezen a kódon"
zero: "Nem maradt több meghívó ezen a kódon"
comma_separated_plz: "Megadhatsz több e-mail címet is vesszővel elválasztva."
- invite_someone_to_join: "Hívj meg valakit, hogy csatlakozzon a diaspora*-hoz!"
+ invite_someone_to_join: "Hívj meg valakit a diaspora* közösségbe!"
language: "Nyelv"
paste_link: "Ha szeretnéd meghívni a barátaidat a diaspora*-ra, oszd meg velük ezt a hivatkozást vagy küldd el nekik közvetlenül levélben."
send_an_invitation: "Küldj egy meghívót"
@@ -436,7 +417,8 @@ hu:
application:
back_to_top: "Vissza az elejére"
be_excellent: "Legyetek mindig jók egymáshoz! ♥"
- powered_by: "diaspora* - fordította adamex & danielwine"
+ discourse: "fórum és támogatás"
+ powered_by: "diaspora* által hajtva"
public_feed: "%{name} nyilvános diaspora* hírfolyama"
source_package: "forráskódcsomag letöltése"
statistics_link: "pod statisztika"
@@ -836,6 +818,8 @@ hu:
aspects_stream: "Csoportok"
comment_stream:
title: "Kommentált bejegyzések"
+ commented:
+ title: "Kommentált bejegyzések"
community_spotlight_stream: "A figyelem középpontjában"
followed_tag:
add_a_tag: "Címke hozzáadása"
@@ -844,6 +828,8 @@ hu:
followed_tags_stream: "#követett címkék"
like_stream:
title: "Kedveled"
+ liked:
+ title: "Kedvelt bejegyzések"
mentioned_stream: "@említések"
mentions:
title: "@Megemlítettek"
diff --git a/config/locales/diaspora/hy.yml b/config/locales/diaspora/hy.yml
index 6f9a83188..1173c99d5 100644
--- a/config/locales/diaspora/hy.yml
+++ b/config/locales/diaspora/hy.yml
@@ -398,7 +398,6 @@ hy:
mentions:
how_to_mention_a: "Հավաքիր «@» և սկսիր հավաքել այդ մարդու անունը։ Բացվող ցանկ կհայտնվի, որտեղից հեշտությամբ կարող ես ընտրել մարդկանց։ Ի դեպ, նշել հնարավոր է միայն այն մարդկանց, ում ավելացրել ես խմբերումդ։"
how_to_mention_q: "Ինչպե՞ս նշեմ ինչ-որ մեկին գրառում անելիս։"
- mention_in_comment_a: "Ոչ, դեռ ոչ։"
mention_in_comment_q: "Կարո՞ղ եմ նշել ինչ-որ մեկին մեկնաբանության մեջ։"
see_mentions_a: "Ահա, սեղմիր «@Նշվածները» հիմնական էջի ձախ կողմում։"
see_mentions_q: "Կարո՞ղ եմ տեսնել այն գրառումները, որոնցում նշված եմ։"
@@ -436,11 +435,7 @@ hy:
format_text_q: "Ինչպե՞ս կարող եմ ձեւավորել տեքստը իմ գրառումների մեջ (թավ (bold), շեղ (italic) եւ այլն)։"
hide_posts_a: "Եթե մկնիկդ պահես գրառման վրա, վերևի աջ կողմում կնկատես x նշանը։ Սեղմիր այն՝ գրառումը թաքցնելու և դրա ծանուցումները անջատելու համար։ Այնուամենայնիվ այդ գրառումը մնալու ու քեզ տեսանելի է լինելու այն կատարած մարդու էջում։"
hide_posts_q: "Ինչպե՞ս թաքցնեմ գրառումը։"
- image_text: "նկարի տեքստը"
- image_url: "նկարի հասցեն"
insert_images_a: "Սեղմիր տեսախցիկի նշանը գրառման մեջ նկար ավելացնելու համար։ Կրկին սեղմիր հաջորդ նկարը ավելացնելու համար կամ կարող ես միանգամից մի քանի նկար ընտրել։"
- insert_images_comments_a1: "Մեկնաբանություններում նկարներ վերբեռնելու հնարավորոթյուն չունես, սակայն նշաձևի (Markdown) հետևյալ կոդը`"
- insert_images_comments_a2: "թույլ կտա մեկնաբանություններում, ինչպես նաև գրառումներում նկարներ ներառել համացանցից։"
insert_images_comments_q: "Կարո՞ղ եմ նկար ավելացնել մեկնաբանության մեջ։"
insert_images_q: "Ինչպե՞ս նկար ներառեմ գրառումների մեջ։"
post_location_a: "Սեղմիր գնդասեղի պատկերիկի վրա, որ գրառում անելու դաշտում տեսախցիկի կողքն է։ Կարող ես փոխել քո տեղակայությունը, հնարավոր է ուզենաս միայն քաղաքը ներառել ամբողջական հասցեի փոխարեն։"
@@ -471,14 +466,6 @@ hy:
title: "Փակ գրառումներ"
who_sees_post_a: "Միայն դիասպորա*յի մուտք գործած օգտատերերը, ում ընդգրկել ես փակ գրառման խմբ(եր)ում, կարող են տեսնել այն։"
who_sees_post_q: "Երբ գրառում եմ անում որևէ խմբի համար (այսինքն՝ փակ գրառում եմ անում), ո՞վ կարող է այն տեսնել։"
- private_profiles:
- title: "Անձնական էջերի մասին"
- whats_in_profile_a: "Կենսագրությունը, գտնվելու վայրը, սեռը եւ ծննդյան ամսաթիվը․ էդ ամեն ինչը պարտադիր չեն լրացման համար (կամավոր են էլի լրիվ ;Ճ)։ Այսինքն՝ լրիվ ազատ ես դրանք լրացնելու կամ չլրացնելու, կամ լրացնելու էդտեղ ցանկացած ցնդաբանություն։ Մուտք գործած օգտատերերը, ում հետ դու կիսվում ես, միակ մարդիկ են, ով կարող են դա տեսնել։ Նրանք նաեւ տեսնում են այն գրառումները, որ կատարել ես այն խմբ(եր)ի համար, որտեղ կան իրենք։ Երբ նրանք գալիս են քո անձնական էջ, տեսնում են այդ գրառումները եւ հրապարակայինները իրար խառնած։"
- whats_in_profile_q: "Ի՞նչ կա իմ անձնական էջում։"
- who_sees_profile_a: "Ցանկացած մուտք գործած օգտատեր, ում հետ կիսվում ես (այսինքն՝ ավելացրել ես խմբերիցդ մեկում)։ Այնուամենայնիվ, մարդիկ, ով հետեւում են քեզ, բայց ում դու չես հետեւում, կարող են տեսնել միայն քո հրապարակային տվյալները։"
- who_sees_profile_q: "Ո՞վ է տեսնում իմ անձնական էջը։"
- who_sees_updates_a: "Քո խմբերում եղած ցանկացած ոք տեսնում է քո անձնական էջի փոփոխությունները։ "
- who_sees_updates_q: "Ո՞վ է տեսնում իմ անձնական էջի թարմացումները։"
public_posts:
can_comment_reshare_like_a: "Ցանկացած մուտք գործած դիասպորա*յի օգտատեր կարող է մեկնաբանել, տարածել կամ հավանել քո հրապարակային գրառումը։"
can_comment_reshare_like_q: "Ո՞վ կարող է մեկնաբանել, հավանել կամ տարածել իմ հրապարակային գրառումները։"
@@ -491,18 +478,6 @@ hy:
title: "Հրապարակային գրառումներ"
who_sees_post_a: "Համացանցից օգտվող ցանկացած մարդ պոտենցիալ կարող է տեսնել հրապարակային գրառումը, այնպես որ զգոն եղիր հրապարակային գրառում անելուց։ ;Ճ"
who_sees_post_q: "Երբ հրապարակային գրառում եմ անում, ո՞վ կարող է տեսնել այն։"
- public_profiles:
- title: "Հրապարակային էջերի մասին"
- what_do_tags_do_a: |-
- Հիմնականում արևի տակ տաքանում են ։Ճ
- Իսկ եթե լուրջ, դրանք օգնում են մարդկանց ճանաչել քեզ։ Ինչպես նաև քո նկարը կհայտնվի այդ պիտակի էջում մյուս բոլոր մարդկանց հետ, ովքեր նշել են իրենց այդ պիտակով։
- what_do_tags_do_q: "Ի՞նչ գործառույթ են կատարում իմ հրապարակային էջի պիտակները։"
- whats_in_profile_a: "Քո հրապարակային էջը քո անունն է, օգտանունը, հինգ պիտակները, որ նշել ես քեզ նկարագրելու համար եւ նկարդ, եթե իհարկե լրացրել ես սրանք։ Բոլոր այս դաշտերը պարտադիր չեն․ դու ազատ ես ընտրելու՝ տրամադրել այդ տեղեկությունը, թե ոչ։ Բացի դրանից հրապարակային էջդ ներառում է նաեւ քո հրապարակային գրառումները։"
- whats_in_profile_q: "Ո՞ր ինֆորմացիան է կազմում իմ հրապարակային էջը։"
- who_sees_profile_a: "Ցանկացած դիասպորա*յի մուտք գործած օգտատեր, ինչպես նաեւ մնացյալ համացանցը կարող է տեսնել այն։ Ցանկացած էջ ունի ուղիղ հղում դեպի իրեն եւ այդպիսով կարող է անմիջականորեն հղվել արտաքին կայքերից։ Այն նաեւ կարող է ինդեքսավորվել որոնողական համակարգերի կողմից։"
- who_sees_profile_q: "Ո՞վ է տեսնում իմ հրապարակային էջը։"
- who_sees_updates_a: "Ցանկացած ոք կարող է տեսնել փոփոխությունները, եթե այցելի քո էջ։"
- who_sees_updates_q: "Ո՞վ է տեսնում իմ հրապարակային էջի թարմացումները։"
resharing_posts:
reshare_private_post_aspects_a: "Ոչ, փակ գրառումը ընդհանրապես անհնար է տարածել։ Սա գրառողի մտադրությունները հարգելու համար է, ով որոշել է կիսվել միայն սահամանափակ թվով մարդկանց հետ։"
reshare_private_post_aspects_q: "Կարո՞ղ եմ տարածել փակ գրառումը ընտրված խմբերի համար։"
@@ -642,6 +617,7 @@ hy:
mark_read: "Նշել որպես նայած"
mark_unread: "Նշել որպես չկարդացված"
mentioned: "Նշել են գրառման մեջ"
+ mentioned_in_comment: "Նշել են մեկնաբանության մեջ"
no_notifications: "Դեռ ոչ մի ծանուցում չունես։"
notifications: "Ծանուցումներ"
reshared: "Տարածել են"
@@ -664,6 +640,12 @@ hy:
one: "%{actors} նշել է քեզ ջնջված գրառման մեջ։"
other: "%{actors} նշել են քեզ ջնջված գրառման մեջ։"
zero: "%{actors} նշել է քեզ ջնջված գրառման մեջ։"
+ mentioned_in_comment:
+ one: "%{actors} նշել է քեզ %{post_link} գրառման <a href='%{comment_path}'>մեկնաբանության</a> մեջ։"
+ other: "%{actors} նշել են քեզ %{post_link} գռարռման <a href='%{comment_path}'>մեկնաբանության</a> մեջ։"
+ mentioned_in_comment_deleted:
+ one: "%{actors} նշել է քեզ ջնջված մեկնաբանության մեջ։"
+ other: "%{actors} նշել են քեզ ջնջված մեկնաբանության մեջ։"
private_message:
one: "%{actors} քեզ հաղորդագրություն է ուղարկել։"
other: "%{actors} քեզ հաղորդագրություն են ուղարկել։"
diff --git a/config/locales/diaspora/ia.yml b/config/locales/diaspora/ia.yml
index 286dd0af4..d63d89763 100644
--- a/config/locales/diaspora/ia.yml
+++ b/config/locales/diaspora/ia.yml
@@ -409,7 +409,6 @@ ia:
mentions:
how_to_mention_a: "Scribe le signo \"@\" e comencia a scriber su nomine. Un menu disrolante deberea apparer que permitte seliger le nomine plus facilemente. Nota ben que il es solmente possibile mentionar personas que tu ha addite a un aspecto."
how_to_mention_q: "Como mentionar un persona quando io scribe un entrata?"
- mention_in_comment_a: "No, actualmente non."
mention_in_comment_q: "Pote io mentionar qualcuno in un commento?"
see_mentions_a: "Si, clicca sur \"@Mentiones\" in le columna sinistre in tu pagina principal."
see_mentions_q: "Existe un maniera de vider le entratas in que on me ha mentionate?"
@@ -445,11 +444,7 @@ ia:
format_text_q: "Como pote io formatar le texto in mi entratas (grasse, italic, etc.)?"
hide_posts_a: "Si tu puncta le mouse verso le parte superior de un entrata, un × appare al dextra. Clicca sur illo pro celar le entrata e silentiar le notificationes sur illo. Tu pote ancora vider le entrata si tu visita le pagina de profilo del persona qui lo ha inviate."
hide_posts_q: "Como cela io un entrata?"
- image_text: "texto de imagine"
- image_url: "URL de imagine"
insert_images_a: "Clicca sur le micre icone de camera pro inserer un imagine in un entrata. Preme le icone de camera de novo pro adder un altere photo, o tu pote seliger plure photos a incargar insimul."
- insert_images_comments_a1: "Non es possibile incargar imagines in commentos, ma le sequente codice Markdown"
- insert_images_comments_a2: "pote esser usate pro inserer imagines ab le web in commentos e in entratas."
insert_images_comments_q: "Pote io inserer imagines in commentos?"
insert_images_q: "Como inserer imagines in entratas?"
post_location_a: "Clicca sur le icone de spinula al latere del camera in le quadro de publication. Isto insere tu position geographic ab OpenStreetMap. Tu pote modificar tu position, per exemplo, si tu vole divulgar solmente le citate e non le adresse stratal exacte."
@@ -478,14 +473,6 @@ ia:
title: "Entratas private"
who_sees_post_a: "Solmente le usatores qui ha aperite session in disaspora* e que tu habeva placiate in ille aspecto ante de inviar le entrata private pote vider lo."
who_sees_post_q: "Quando io invia un message a un aspecto (i.e. un entrata private), qui potera vider lo?"
- private_profiles:
- title: "Profilos private"
- whats_in_profile_a: "Tu profilo private contine tu biographia, loco, sexo e data de nascentia, si tu ha completate iste sectiones. Tote iste information es optional; a te le decision de fornir lo o non. Le usatores qui ha aperite session e que tu ha addite a un de tu aspectos es le unic personas qui pote vider tu profilo private. Quando illes visita tu pagina de profilo, illes videra tamben le entratas private inviate al aspecto(s) in que illes es, miscite con tu entratas public."
- whats_in_profile_q: "Que es in mi profilo private?"
- who_sees_profile_a: "Omne usator qui ha aperite session e con qui tu divide cosas (i.e. que tu ha addite a un de tu aspectos) pote vider tu profilo private. Nonobstante, le personas qui te seque, ma que tu non seque, videra solmente tu information public."
- who_sees_profile_q: "Qui vide mi profilo private?"
- who_sees_updates_a: "Omne persona in tu aspectos vide le cambiamentos in tu profilo private. "
- who_sees_updates_q: "Qui vide le actualisationes in mi profilo private?"
public_posts:
can_comment_reshare_like_a: "Omne usator qui ha aperite session in diaspora* pote commentar, repeter o appreciar tu entrata public."
can_comment_reshare_like_q: "Qui pote commentar, repeter o appreciar mi entrata public?"
@@ -498,16 +485,6 @@ ia:
title: "Entratas public"
who_sees_post_a: "Qualcunque usator de internet poterea vider un entrata que tu marca como public, dunque, assecura te que tu vole vermente que tu message sia public. Isto es un excellente maniera de attinger le mundo."
who_sees_post_q: "Quando io invia qualcosa publicamente, qui pote vider lo?"
- public_profiles:
- title: "Profilos public"
- what_do_tags_do_a: "Illes adjuta le gente a cognoscer te. Tu imagine de profilo apparera etiam in le latere sinistre de iste paginas de etiquetta, con illos del alteres qui los ha in lor profilos public."
- what_do_tags_do_q: "Que face le etiquettas in mi profilo public?"
- whats_in_profile_a: "Le profilo public contine tu nomine, le cinque etiquettas que tu ha eligite pro describer te, e tu photo, si ti ha completate iste sectiones. Tote iste information es facultative; a te le decision de fornir lo o non. Tu pote render iste information de profilo tanto personal o tanto anonyme como tu vole. Tu pagina de profilo monstra etiam le entratas public que tu ha inviate."
- whats_in_profile_q: "Que es in mi profilo public?"
- who_sees_profile_a: "Omne usator de diapora* e del internet in general pote vider lo. Cata profilo ha un adresse URL directe, de sorta que on pote inserer ligamines a illo in sitos exterior. Le motores de recerca del web pote indexar lo."
- who_sees_profile_q: "Qui vide mi profilo public?"
- who_sees_updates_a: "Omnes pote vider le cambiamentos si illes visita tu pagina de profilo."
- who_sees_updates_q: "Qui vide le actualisationes in mi profilo public?"
resharing_posts:
reshare_private_post_aspects_a: "No, il non es possibile repeter un entrata private. Isto es pro respectar le intentiones del autor original qui lo ha dividite solmente con un gruppo particular de personas."
reshare_private_post_aspects_q: "Pote io repeter un entrata private solmente a certe aspectos?"
@@ -655,6 +632,7 @@ ia:
mark_read: "Marcar como legite"
mark_unread: "Marcar como non legite"
mentioned: "Mentionate"
+ mentioned_in_comment: "Mentionate in commento"
no_notifications: "Tu non ha ancora notificationes."
notifications: "Notificationes"
reshared: "Repetite"
@@ -677,6 +655,12 @@ ia:
one: "%{actors} te ha mentionate in un entrata delite."
other: "%{actors} te ha mentionate in un entrata delite."
zero: "%{actors} te ha mentionate in un entrata delite."
+ mentioned_in_comment:
+ one: "%{actors} te ha mentionate in un <a href='%{comment_path}'>commento</a> sur le entrata %{post_link}."
+ other: "%{actors} te ha mentionate in un <a href='%{comment_path}'>commento</a> sur le entrata %{post_link}."
+ mentioned_in_comment_deleted:
+ one: "%{actors} te ha mentionate in un commento delite."
+ other: "%{actors} te ha mentionate in un commento delite."
private_message:
one: "%{actors} te ha inviate un message."
other: "%{actors} te ha inviate un message."
@@ -802,6 +786,9 @@ ia:
mentioned:
limited_post: "Tu ha essite mentionate in un entrata limitate."
subject: "%{name} te ha mentionate in diaspora*"
+ mentioned_in_comment:
+ limited_post: "Tu ha essite mentionate in un commento sur un entrata limitate."
+ reply: "Responder o leger iste conversation >"
private_message:
reply_to_or_view: "Responde o lege iste conversation >"
subject: "Il ha un nove message private pro te"
@@ -1165,6 +1152,7 @@ ia:
last_exported_at: "(Ultime actualisation: %{timestamp})"
liked: "un persona apprecia un entrata tue"
mentioned: "un persona te mentiona in un entrata sue"
+ mentioned_in_comment: "tu es mentionate in un commento"
new_password: "Contrasigno nove"
private_message: "tu recipe un message private"
receive_email_notifications: "Reciper notificationes per e-mail quando:"
diff --git a/config/locales/diaspora/is.yml b/config/locales/diaspora/is.yml
index 0f8a68007..0507772ba 100644
--- a/config/locales/diaspora/is.yml
+++ b/config/locales/diaspora/is.yml
@@ -185,8 +185,6 @@ is:
what_is_a_pod_a: "Belgur er miðlari sem keyrir diaspora* hugbúnaðinn og er tengdur diaspora* netinu. \"Belgur\" er samlíking við fræbelgi á plöntum sem innihalda fræ á sama átt og miðlarinn hýsir marga notendur. Það eru margir belgir til. Þú getur bætt við vinum á öðrum belgjum og átt í samskiptum við þá. (Þú getur hugsað belg á svipaðan hátt og tölvupóstþjón: það eru margir opnir belgir sem og lokaðir belgir , þú getur meira að segja hýst þinn eginn belg)."
posts_and_posting:
embed_multimedia_a: "Oftast er hægt að setja URLið (t.d. http://www.youtube.com/watch?v=nnnnnnnnnnn) beint inn í skilaboðin og myndin eða myndbandið verður fellt sjálfkrafa inn í skeytið. Við styðjum meðal annars. YouTube, Vimeo, SoundCloud, Flickr ásamt nokkrum öðrum. diaspora* notar oEmbed til að framkvæma innfellinguna sem gerir það að verkum að nýjar þjónustur eru stöðugt að bætast í hópinn. Mundu að setja alltaf inn fulla slóð inn, ekki stytta hana né bæta aftan við sem og að smá stund getur tekið áður en innfellingin er verður sýnileg."
- private_profiles:
- whats_in_profile_a: "Ferilskráin, staðsetning, kyn og fæðingardagur. Þetta eru allt hlutir sem eru neðst á Síðunni Þinni. Þú ræður hvort þú setur upplýsingar þar inn. Eingöngu einstaklingar sem þú hefur bætt í eina af þínum sýnum, og eru skráðir inn, geta séð þessar upplýsingar. Þegar þeir fara á síðuna þína geta þeir séð þau skeyti sem þú hefur deilt með öllum, sem og þau skeyti sem þú hefur valið að deila með sýnum sem þeir eru í."
invitations:
create:
no_more: "Ekki eru fleiri boðsmiðar."
diff --git a/config/locales/diaspora/it.yml b/config/locales/diaspora/it.yml
index 033ef4613..de46a42df 100644
--- a/config/locales/diaspora/it.yml
+++ b/config/locales/diaspora/it.yml
@@ -276,7 +276,6 @@ it:
mentions:
how_to_mention_a: "Scrivi il carattere \"@\" e inizia a scrivere il nome della persona. Comparirà un menù a tendina da cui potrai scegliere facilmente il contatto corretto. È possibile menzionare solamente persone che hai già aggiunto ad un aspetto."
how_to_mention_q: "Come posso menzionare qualcuno quando scrivo un post?"
- mention_in_comment_a: "No, al momento non è possibile."
mention_in_comment_q: "Posso menzionare qualcuno in un commento?"
see_mentions_a: "Sì, clicca su \"Menzioni\" nella colonna di sinistra nella home page."
see_mentions_q: "C'è un modo per vedere i post dove ho ricevuto una menzione?"
@@ -310,11 +309,7 @@ it:
format_text_q: "Come posso formattare il testo dei miei post (grassetto, corsivo, ecc.)?"
hide_posts_a: "Se sposti il mouse in cima al post, vedrai comparire una X a destra. Cliccandola nasconderai il post e non riceverai più le notifiche che lo riguardano. Potrai vedere il post cercandolo sulla pagina del profilo dell'autore."
hide_posts_q: "Come posso nascondere un post? Come posso smettere di ricevere notifiche da un post che ho commentato?"
- image_text: "Descrizione immagine"
- image_url: "URL immagine"
insert_images_a: "Clicca l'icona a forma di macchina fotografica per inserire un'immagine. Puoi cliccare di nuovo per inserirne un'altra, oppure puoi scegliere di aggiungere più immagini in una volta sola."
- insert_images_comments_a1: "Devi usare il codice markdown seguente"
- insert_images_comments_a2: "così potrai aggiungere immagini non solo ai commenti ma anche ai post."
insert_images_comments_q: "Posso inserire immagini nei commenti?"
insert_images_q: "Come posso inserire immagini nei post?"
size_of_images_a: "No, le dimensioni delle immagini saranno scelte automaticamente per adattarsi al post. Inoltre, il markdown non prevede un modo per indicare le dimensioni desiderate."
@@ -335,14 +330,6 @@ it:
title: "Post privati"
who_sees_post_a: "Solo gli utenti loggati in diaspora* che hai inserito in quell'Aspetto possono vedere i tuoi post privati."
who_sees_post_q: "Quando posto un messaggio ad un Aspetto (es: un messaggio privato), chi può vederlo?"
- private_profiles:
- title: "Profili privati"
- whats_in_profile_a: "Biografia, luogo, sesso e data di nascita. Sono tutti dati della sezione inferiore della pagina editabile del profilo. Tutte queste informazioni sono opzionali (sta a te inserirle o no). Gli utenti registrati che hai aggiunto ai tuoi aspetti sono le sole persone che possono vedere il tuo profilo privato. Essi potranno anche vedere i post privati pertinenti agli aspetti di cui fanno parte, assieme ai post pubblici, quando visitano la pagina del tuo profilo."
- whats_in_profile_q: "Cosa c'è nel mio profilo privato?"
- who_sees_profile_a: "Qualunque utente loggato con cui lo stai condividendo (cioè, lo hai aggiunto ad uno dei tuoi aspetti). Tuttavia, le persone che ti seguono, ma che tu non segui, vedranno solo le tue informazioni pubbliche."
- who_sees_profile_q: "Chi vede il mio profilo privato?"
- who_sees_updates_a: "Chiunque nei tuoi aspetti vede i cambiamenti del tuo profilo privato "
- who_sees_updates_q: "Chi vede gli aggiornamenti del mio profilo privato?"
public_posts:
can_comment_reshare_like_a: "Qualunque utente di diaspora* loggato può commentare, ri-condividere, o mettere mi piace sul tuo post pubblico."
can_comment_reshare_like_q: "Chi può commentare, ri-condividere, o mettere mi piace sul mio post pubblico?"
@@ -355,16 +342,6 @@ it:
title: "Post pubblici"
who_sees_post_a: "Potenzialmente chiunque stia utilizzando internet può vedere un post che hai segnato come pubblico, perciò assicurati di voler rendere per davvero il tuo post pubblico. E' un fantastico modo di allungarsi verso il mondo."
who_sees_post_q: "Quando posto qualcosa pubblicamente, chi può vederla?"
- public_profiles:
- title: "Profili pubblici"
- what_do_tags_do_a: "Aiutano le persone a conoscerti meglio. L'immagine del tuo profilo apparirà anch'essa a sinistra di quelle particolari pagine di tag, insieme con chiunque altro le abbia nel loro profilo pubblico."
- what_do_tags_do_q: "Cosa fanno le tag nel mio profilo pubblico?"
- whats_in_profile_a: "Il tuo nome, le cinque tag che hai scelto per descriverti, e la tua immagine di profilo. Sono le cose nella sezione superiore della pagina modificabile del profilo. Puoi rendere queste informazioni di profilo quanto anonime o identificabili desideri. Le tue pagine di profilo mostrano anche qualunque post pubblico che hai creato."
- whats_in_profile_q: "Cosa c'è nel mio profilo pubblico"
- who_sees_profile_a: "Qualunque utente loggato in diaspora*, così come il più ampio internet, può vederlo. Ogni profilo ha una URL diretta, perciò potrebbe essere linkata direttamente da siti esterni. Potrebbe essere indicizzata da motori di ricerca."
- who_sees_profile_q: "Chi vede il mio profilo pubblico?"
- who_sees_updates_a: "Chiunque visiti la tua pagina del profilo può vedere i cambiamenti."
- who_sees_updates_q: "Chi vede gli aggiornamenti del mio profilo pubblico?"
resharing_posts:
reshare_private_post_aspects_a: "No, non è possibile condividere un post privato. Ciò per rispettare le intenzioni di chi lo ha originalmente condiviso, il quale lo ha condiviso solamente con un gruppo particolare di persone."
reshare_private_post_aspects_q: "Posso condividere un post privato con solo certi aspetti?"
diff --git a/config/locales/diaspora/ja.yml b/config/locales/diaspora/ja.yml
index 181808479..5aa9d70f1 100644
--- a/config/locales/diaspora/ja.yml
+++ b/config/locales/diaspora/ja.yml
@@ -58,6 +58,8 @@ ja:
fetching_diaspora_version: "最新のダイアスポラ* バージョンを判断しています..."
pod_status: "ポッド ステータス"
pods:
+ pod_desktop_link: "デスクトップ ビュー"
+ pod_desktop_view: "このページは、モバイル ビューには対応していません。%{desktop_link} に切り替えてください。"
pod_network: "ポッド ネットワーク"
stats:
2weeks: "2 週間"
@@ -222,6 +224,8 @@ ja:
here_to_help: "ここがダイアスポラ*のコミュニティです!"
mail_podmin: "ポッド管理者メール"
need_help: "ヘルプが必要ですか?"
+ support_forum: "%{support_forum} に参加することも可能です。"
+ support_forum_link: "サポート フォーラム"
tag_bug: "#bug"
tag_feature: "#feature"
tag_question: "#question"
@@ -263,6 +267,13 @@ ja:
heading: "お気に入り"
post_something: "ダイアスポラに投稿"
cancel: "取消"
+ color_themes:
+ dark: "ダーク"
+ dark_green: "ダークグリーン"
+ egyptian_blue: "エジプトブルー"
+ magenta: "マゼンタ"
+ original: "オリジナルグレー"
+ original_white: "オリジナルの白い背景"
comments:
create:
error: "コメントに失敗しました。"
@@ -370,9 +381,11 @@ ja:
add_contact_roster_q: "ダイアスポラ*で誰かとチャットする方法は?"
contacts_page: "連絡先ページ"
title: "チャット"
+ community_guidelines: "コミュニティー・ガイドライン"
faq: "よくある質問"
foundation_website: "ダイアスポラ*財団のウェブサイト"
getting_help:
+ get_support_a_discourse: "問い合わせに関連する既存のディスカッションを検索するか、%{discourse} プラットフォームで新しいスレッドを開きます"
get_support_a_faq: "Wikiで%{faq}ページをお読みください"
get_support_a_hashtag: "ダイアスポラ*の公開投稿で %{question} ハッシュタグを使用して質問してください"
get_support_a_irc: "%{irc}で参加してください (ライブチャット)"
@@ -402,7 +415,7 @@ ja:
mentions:
how_to_mention_a: "「@」記号を入力して、彼らの名前の入力を始めます。より簡単に選択できるように、ドロップダウンメニューが表示されます。アスペクトに追加したユーザーにのみメンションすることが可能であることに注意してください。"
how_to_mention_q: "投稿を作るときに、誰かにメンションする方法は?"
- mention_in_comment_a: "いいえ、現在はできません。"
+ mention_in_comment_a: "バージョン 0.7.0.0 から、そう! 投稿の中でやっているのと同じように “@” と入力して名前を入力し始めると、コメントで誰かにメンションすることができます。 公開されていない投稿にコメントするときは、その投稿で既にやりとりしているユーザーのみコメントすることができることにご注意ください。"
mention_in_comment_q: "コメントの誰かにメンションすることはできますか?"
see_mentions_a: "はい、あなたのホームページの左側の列で「@メンション」をクリックします。"
see_mentions_q: "私がメンションされた投稿を参照する方法はありますか?"
@@ -438,11 +451,8 @@ ja:
format_text_q: "自分の投稿内のテキストの書式 (太字、斜体など) を設定する方法は?"
hide_posts_a: "投稿の先頭にマウスを移動すると、X が右側に表示されます。それをクリックすると、投稿を非表示にして、それに関する通知をミュートします。それを投稿した人のプロフィールページを訪問すると、まだ投稿を見ることができます。"
hide_posts_q: "投稿を非表示にする方法は?"
- image_text: "画像テキスト"
- image_url: "画像 URL"
insert_images_a: "小さなカメラアイコンをクリックして、投稿に画像を挿入します。もう一度カメラアイコンを押して別の写真を追加したり、複数の写真を選択して一度にアップロードすることができます。"
- insert_images_comments_a1: "コメントに、画像をアップロードすることはできませんが、次のマークダウンコード"
- insert_images_comments_a2: "を使用して、コメントならびに投稿にウェブから画像を挿入することができます。"
+ insert_images_comments_a: "投稿と同様に、Markdown を使用して、ウェブから画像をコメントに挿入できます。 ただし、コメントにコンピュータから画像を直接アップロードすることはできません。 画像ホスティングサービスにアップロードして、その後公開者の上にある画像ボタンを使用して挿入します。"
insert_images_comments_q: "コメントに画像を挿入することはできますか?"
insert_images_q: "投稿に画像を挿入する方法は?"
post_location_a: "公開者のカメラの横のピンアイコンをクリックします。これにより、OpenStreetMap からあなたの場所を挿入します。あなたの場所を編集することができます - あなたがいる都市ではなく、特定の住所を含めることができます。"
@@ -471,14 +481,14 @@ ja:
title: "非公開の投稿"
who_sees_post_a: "非公開の投稿を行う前にそのアスペクトに配置されていた、ログインしているダイアスポラ*ユーザーのみがそれを見ることができます。"
who_sees_post_q: "アスペクトにメッセージを投稿すると (例 非公開の投稿)、誰がそれを見ることができますか?"
- private_profiles:
- title: "非公開プロフィール"
- whats_in_profile_a: "すべてのセクションを完了している場合、あなたの非公開プロフィールには、略歴、所在地、性別、誕生日が含まれています。この情報はすべてオプションです - それを提供するかどうかはあなた次第です。あなたのアスペクトに追加したログインユーザーだけが、あなたの非公開プロフィールを見ることができます。彼らがあなたのプロフィールページにアクセスすると、彼らが含まれているアスペクトに対して行われた非公開の投稿も、あなたの公開の投稿に混じって表示されます。"
- whats_in_profile_q: "私の非公開プロフィールには何がありますか?"
- who_sees_profile_a: "あなたとシェアしているすべてのログインしたユーザー (あなたのアスペクトの一つに彼らを追加しているという意味)。しかし、あなたをフォローしていても、あなたがフォローしていない人は、あなたの公開情報が表示されるだけです。"
- who_sees_profile_q: "誰が私の非公開プロフィールを見ますか?"
- who_sees_updates_a: "あなたのアスペクトにいる誰もが、あなたの非公開プロフィールへの変更を見ています。 "
- who_sees_updates_q: "私の非公開プロフィールへの更新を誰が見ますか?"
+ profile:
+ title: "プロフィール"
+ what_do_tags_do_a: "タグは人々があなたを知るのに役立ちます。 あなたのプロフィール画像は、それらのタグのストリームページの左側に、基本プロフィールにそのタグを持つ他のユーザーとともに表示されます。"
+ what_do_tags_do_q: "基本プロフィールのタグは何をしますか?"
+ whats_in_profile_a: "プロフィールは、基本プロファイルと拡張プロファイルの2つの部分に分かれています。 基本プロフィールには名前、あなた自身を説明するために選択した5つのタグ、あなたの写真が含まれています。 拡張プロフィールには、バイオグラフィー、場所、性別、誕生日が表示されます。 この情報はすべて任意です。提供するかどうかはあなた次第です。このプロフィール情報は、あなたが好きなように個人または匿名で作ることができます。 拡張プロフィールは、プロフィールページの左側の列、プロフィール写真の下に表示されます。"
+ whats_in_profile_q: "私のプロフィールには何がありますか?"
+ who_sees_profile_a: "基本プロフィール (名前、プロフィール画像、#タグ) は公開されます。 拡張プロフィールはデフォルトでは非公開ですが、必要に応じてすべて公開アクセスにできます。 あなたが拡張プロフィールを非公開にした場合、共有している相手 (つまり、あなたのアスペクトの1つに追加したことの意味) のみが見ることができます。 他の人には公開情報のみが表示されます。 公開したプロフィール情報は、ウェブを使用している誰でも閲覧でき、検索エンジンでインデックスに登録されることができます"
+ who_sees_profile_q: "誰が私の公開プロフィールを見ますか?"
public_posts:
can_comment_reshare_like_a: "すべてのログインしているダイアスポラ*ユーザーがコメントしたり、リシェアしたり、いいね!をすることができます。"
can_comment_reshare_like_q: "誰が、私の公開の投稿をコメントしたり、リシェア、いいね!することができますか?"
@@ -491,16 +501,6 @@ ja:
title: "公開の投稿"
who_sees_post_a: "インターネットを使っている誰もがあなたが公開としてマークした投稿を参照する可能性があるので、あなたの投稿を本当に公開にしたいかを確認してください。世界に手を差し伸べる素晴らしい方法です。"
who_sees_post_q: "公開で何かを投稿すると、誰がそれを見ることができますか?"
- public_profiles:
- title: "公開プロフィール"
- what_do_tags_do_a: "人々があなたのことを知るのに役立ちます。これら特定のタグページの左側に、公開プロフィールでそれらを持っている他の誰かと一緒に、あなたのプロフィール写真も表示されます。"
- what_do_tags_do_q: "公開プロフィール上のタグは何をしますか?"
- whats_in_profile_a: "すべてのセクションを完了している場合、公開プロフィールには、あなたの名前、あなた自身を説明するために選ぶ 5 つのタグ、あなたの写真が含まれています。この情報はすべてオプションです - それを提供するかどうかはあなた次第です。あなたが好きなように特定可能または匿名で、このプロフィール情報を作ることができます。あなたのプロフィールページは、あなたが行ったすべての公開の投稿も表示しています。"
- whats_in_profile_q: "私の公開プロフィールには何がありますか?"
- who_sees_profile_a: "すべてのログインしたダイアスポラ*ユーザーだけでなく、より広くインターネットから見ることができます。それぞれのプロフィールは、直接 URL があるので、外部サイトから直接リンクすることができます。これは、検索エンジンによってインデックスされることもあります。"
- who_sees_profile_q: "誰が私の公開プロフィールを見ていますか?"
- who_sees_updates_a: "あなたのプロフィールページにアクセスすると、誰でも更新を見ることができます。"
- who_sees_updates_q: "誰が私の公開プロフィールへの更新を見ていますか?"
resharing_posts:
reshare_private_post_aspects_a: "いいえ。非公開の投稿をリシェアすることはできません。これが、特定のグループの人々とのみそれをシェアした、元の投稿者の意向を尊重することです。"
reshare_private_post_aspects_q: "非公開の投稿を、選択したアスペクトにリシェアすることはできますか?"
@@ -599,6 +599,7 @@ ja:
application:
back_to_top: "トップに戻る"
be_excellent: "お互いに素晴らしい関係でありましょう! ♥"
+ discourse: "プロジェクトのディスカッションとサポート"
powered_by: "POWERED BY DIASPORA*"
public_feed: "%{name}さんの公開ダイアスポラフィード"
source_package: "ソースコードのパッケージをダウンロードする"
@@ -643,6 +644,7 @@ ja:
mark_read: "既読にする"
mark_unread: "未読にする"
mentioned: "メンションされました"
+ mentioned_in_comment: "コメントでメンションしました"
no_notifications: "まだ通知は何もありません"
notifications: "通知"
reshared: "リシェアしました"
@@ -661,6 +663,10 @@ ja:
mentioned_deleted:
other: "%{actors}さんが削除された投稿であなたにメンションしました。"
zero: "%{actors}さんが削除された投稿であなたにメンションしました。"
+ mentioned_in_comment:
+ other: "%{actors} が、投稿 %{post_link} に <a href='%{comment_path}'>コメント</a> でメンションしました。"
+ mentioned_in_comment_deleted:
+ other: "%{actors} が、削除したコメントでメンションしました。"
private_message:
other: "%{actors}さんが、あなたにメッセージを送信しました。"
zero: "%{actors}さんが、あなたにメッセージを送信しました。"
@@ -780,6 +786,9 @@ ja:
mentioned:
limited_post: "あなたは限定公開の投稿でメンションされました。"
subject: "%{name}さんはダイアスポラ*であなたをメンションしました。"
+ mentioned_in_comment:
+ limited_post: "限定公開の投稿にコメントでメンションされました。"
+ reply: "この会話に返信、または表示 >"
private_message:
reply_to_or_view: "この会話に返信、または表示 >"
subject: "あなたに新しい非公開メッセージがあります"
@@ -1057,6 +1066,8 @@ ja:
streams:
activity:
title: "マイ アクティビティ"
+ admin:
+ title: "管理"
aspects:
all: "すべてのアスペクト"
title: "マイ アスペクト"
@@ -1141,6 +1152,7 @@ ja:
last_exported_at: "(最終更新 %{timestamp})"
liked: "あなたの投稿をいいね!したとき"
mentioned: "投稿に自分がメンションされたとき"
+ mentioned_in_comment: "コメントでメンションされました"
new_password: "新しいパスワード"
private_message: "非公開メッセージが届いたとき"
receive_email_notifications: "通知メールの送信設定"
diff --git a/config/locales/diaspora/ko.yml b/config/locales/diaspora/ko.yml
index f805c64f2..95d2372a7 100644
--- a/config/locales/diaspora/ko.yml
+++ b/config/locales/diaspora/ko.yml
@@ -223,8 +223,6 @@ ko:
title: "기타"
private_posts:
title: "혼자 보는 글"
- private_profiles:
- title: "개인 프로필"
public_posts:
title: "공개 게시물"
sharing:
diff --git a/config/locales/diaspora/ml.yml b/config/locales/diaspora/ml.yml
index 71b71fc2d..359df14a5 100644
--- a/config/locales/diaspora/ml.yml
+++ b/config/locales/diaspora/ml.yml
@@ -255,7 +255,6 @@ ml:
markdown: "മാര്‍ക്ക്ഡൌണ്‍"
mentions:
how_to_mention_q: "ഒരു പോസ്റ്റ് ഉണ്ടാക്കുമ്പോള്‍ എങ്ങനെ ഒരാളെ സൂചിപ്പിക്കാം?"
- mention_in_comment_a: "ഇല്ല, ഇപ്പോഴില്ല."
mention_in_comment_q: "അഭിപ്രായത്തില്‍ ഒരാളെ സൂചിപ്പിക്കാന്‍ പറ്റുമോ?"
see_mentions_a: "പൂമുഖത്തിന്റെ ഇടതുവശത്തെ \"സൂചനകള്‍\" നോക്കു."
see_mentions_q: "എന്നെ സൂചിപ്പിച്ച പോസ്റ്റുകള്‍ കാണാന്‍ വഴിയുണ്ടോ?"
@@ -285,10 +284,6 @@ ml:
embed_multimedia_q: "ഞാന്‍ എങ്ങനെ വീഡിയോ, ഓഡിയോ, അല്ലെങ്കില്‍ മറ്റു മള്‍ട്ടിമീഡിയ വിവരങ്ങള്‍ കുറിപ്പിലെക്കു ഉറപ്പിക്കും?"
format_text_q: "എനിക്ക് എന്റെ കുറിപ്പുകളിലെ അക്ഷരങ്ങള്‍ എങ്ങനെ മാറ്റം വരുത്താം(കട്ടിയെഴുത്ത്,ചെരിവെഴുത്ത്‌, തുടങ്ങിയവ.)?"
hide_posts_q: "എങ്ങനെ ഒരു കുറിപ്പ് മറയ്ക്കാം.?/ എങ്ങനെ ഞാന്‍ അഭിപ്രായം രേഖപ്പെടുതിയ ഒരു കുറിപ്പിനെ കുറിച്ചുള്ള അറിയിപ്പുകള്‍ ലഭിക്കുന്നത് നിര്‍ത്തലാക്കാം?"
- image_text: "അടികുറുപ്പ്"
- image_url: "ചിത്രത്തിന്റെ വിലാസം."
- insert_images_comments_a1: "താഴെയുള്ള മാര്‍ക്ക്ഡൌണ്‍ കോഡ്"
- insert_images_comments_a2: "കുറിപ്പുകളില്‍ എന്നപോലെ അഭിപ്രായവും ചിത്രമായി വെബില്‍ നീന്നു ചേര്‍ക്കാവുന്നതാണു."
insert_images_comments_q: "അഭിപ്രായം രേഖപ്പെടുത്തുമ്പോള്‍ ചിത്രങ്ങളും ഉള്‍പ്പെടുത്താമോ?"
insert_images_q: "ചിത്രങ്ങൾ എപ്രകാരം പോസ്റ്റിൽ ഉൾപ്പെടുത്താം?"
size_of_images_a: "ഇല്ല. ചിത്രങ്ങള്‍ സ്ട്രീമിലേക്ക് കൊള്ളിക്കുന്നതിനായി തനിയെ വലിപ്പം മാറ്റും. മാര്‍ക്ക്ഡൌണില്‍ വലിപ്പം പറയാനുള്ള കോഡില്ല"
@@ -306,12 +301,6 @@ ml:
title: "സ്വകാര്യ പോസ്റ്റുകള്‍"
who_sees_post_a: "ആ പരിചയത്തില്‍ ഉള്ള ഡയസ്പോറയില്‍ പ്രവേശിച്ചിരിക്കുന്ന ഉപയോക്താക്കള്‍ക്കു മാത്രമേ താങ്കളുടെ സ്വകാര്യ കുറിപ്പുകള്‍ കാണാന്‍ കഴിയു."
who_sees_post_q: "ഞാന്‍ ഒരു ഭാവത്തിലേക്കു സന്ദേശം പോസ്റ്റ് ചെയ്തത് (i.e., സ്വകാര്യ കുറിപ്പുകള്‍), ആര്‍ക്കെല്ലാം കാണാന്‍ കഴിയും?"
- private_profiles:
- title: "സ്വകാര്യ പ്രൊഫൈലുകൾ"
- whats_in_profile_q: "എന്റെ സ്വകാര്യ പ്രൊഫൈലിൽ എന്തെല്ലാം ഉൾപ്പെടുന്നു?"
- who_sees_profile_q: "ആര്‍ക്കെല്ലാം എന്റെ സ്വകാര്യ പ്രൊഫൈല്‍ കാണാന്‍ കഴിയും?"
- who_sees_updates_a: "താങ്കളുടെ പരിചയത്തില്‍ ഉള്ളവര്‍ക്കെല്ലാം താങ്കളുടെ സ്വകാര്യ പ്രൊഫൈലിലെ മാറ്റങ്ങള്‍ കാണാന്‍ കഴിയും. "
- who_sees_updates_q: "ആർക്കെല്ലാം എന്റെ സ്വകാര്യ പ്രൊഫൈലിലെ മാറ്റങ്ങള്‍ കാണാന്‍ കഴിയും?"
public_posts:
can_comment_reshare_like_a: "എല്ലാ പ്രവേശിച്ചിരിക്കുന്ന ഡയസ്പോറ* ഉപയോക്താക്കള്‍ക്കും അഭിപ്രായം, ഇഷ്ട്ടപ്പെടല്‍, വീണ്ടും പങ്കിടല്‍ തുടങ്ങിയവ ചെയ്യാനാകും"
can_comment_reshare_like_q: "എന്റെ പൊതു കുറിപ്പില്‍ അര്‍ക്കാക്കെ ഇഷ്ട്ടപ്പെടാന്‍, അഭിപ്രായം പറയാന്‍, വീണ്ടും പങ്കിടാന്‍ പറ്റും?"
@@ -319,13 +308,6 @@ ml:
title: "പൊതുവായ കുറിപ്പുകൾ"
who_sees_post_a: "ഇന്റെര്‍നെറ്റ് ഉപയോഗിക്കുന്ന ഏതൊരാള്‍ക്കും നിങ്ങളുടെ പൊതു കുറിപ്പ് കാണാന്‍ പറ്റും. അതുകൊണ്ട് കുറിപ്പ് പൊതുവാക്കണോ എന്ന് ശരിക്ക് ഉറപ്പാക്കുക. അത് എല്ലാവരിലേക്കും എത്താന്‍ വളരെ നല്ല ഒരു വഴിയാണ്"
who_sees_post_q: "ഞാനെന്തെങ്കിലും പൊതുവായി കൂറിക്കുമ്പോള്‍ ആര്‍ക്കൊക്കെ കാണാന്‍ പറ്റും?"
- public_profiles:
- title: "പൊതുവായ പ്രൊഫൈലുകൾ"
- what_do_tags_do_q: "എന്റെ പൊതു പ്രൊഫൈലിലുള്ള ടാഗുകള്‍ എന്താ ചെയ്യുന്നത്?"
- whats_in_profile_q: "എന്റെ പൊതു പ്രൊഫൈലില്‍ എന്താണുള്ളത്?"
- who_sees_profile_q: "എന്റെ പൊതു പ്രൊഫൈല്‍ ആരൊക്കെ കാണും?"
- who_sees_updates_a: "താങ്കളുടെ പ്രൊഫൈല്‍ സന്ദര്‍ശിക്കുന്ന ആര്‍ക്കും മാറ്റങ്ങള്‍ കാണാം"
- who_sees_updates_q: "എന്റെ പൊതു പ്രാഫൈലിലെ പുതുക്കലുകള്‍ ആര്‍ക്കൊക്കെ കാണാന്‍ പറ്റും?"
resharing_posts:
reshare_private_post_aspects_q: "ചില പരിചയങ്ങള്‍ക്ക് മാത്രമായി സ്വകാര്യ പോസ്റ്റ് പങ്കിടാന്‍ പറ്റുമോ?"
reshare_public_post_aspects_q: "പൊതു കുറിപ്പുകള്‍ പ്രത്യേക പരിചയത്തിലായി മാത്രം പങ്കിടാന്‍ പറ്റുമോ?"
diff --git a/config/locales/diaspora/nb.yml b/config/locales/diaspora/nb.yml
index 5369d045d..6fa91721d 100644
--- a/config/locales/diaspora/nb.yml
+++ b/config/locales/diaspora/nb.yml
@@ -333,7 +333,6 @@ nb:
mentions:
how_to_mention_a: "«»"
how_to_mention_q: "Hvordan kan jeg omtale noen når jeg gjør et innlegg?"
- mention_in_comment_a: "Nei, ikke for tiden."
mention_in_comment_q: "Kan jeg omtale noen i en kommentar?"
see_mentions_a: "Ja, klikk på «Omtale» i venstre kolonne på hjemmesiden din."
see_mentions_q: "Er det en måte å se innleggene der jeg har blitt omtale?"
@@ -369,11 +368,7 @@ nb:
format_text_q: "Hvordan kan jeg formatere teksten i mine innlegg (fet, kursiv, etc.)?"
hide_posts_a: "Hvis du holder musepekeren ved toppen av en post, vises en X til høyre. Klikk den for å skjule posten og mute beskjeder om den. Du kan fremdeles se posten hvis du besøker profilsiden til personen som postet den."
hide_posts_q: "Hvordan skjuler jeg en post? / Hvordan kan jeg slutte å få beskjeder om en post jeg har kommentert på?"
- image_text: "bildetekst"
- image_url: "bilde url"
insert_images_a: "Klikk på det lille kameraikonet for å sette inn et bilde i en post. Klikk på fotoikonet igjen for å legge til enda et bilde, eller du kan merke flere bilder å laste opp på en gang."
- insert_images_comments_a1: "Følgende Markdown kode"
- insert_images_comments_a2: "kan brukes til å sette inn bilder fra nettet inn kommentarer og innlegg."
insert_images_comments_q: "Kan jeg sett inn bilder i kommentarer?"
insert_images_q: "Hvordan setter jeg inn bilder til innlegg?"
post_location_a: "Klikk på knappenålsikonet ved siden av kameraet der du legger til bilder. Dette vil legge til plassering fra OpenStreetMap. Du kan selv endre plasseringen - det kan være at du kun ønsker å inkludere byen du er i heller enn den eksakte adressen."
@@ -402,14 +397,6 @@ nb:
title: "Private innlegg"
who_sees_post_a: "Kun innloggede diaspora* brukere du har plassert i det aspektet kan se din private innlegg."
who_sees_post_q: "Når jeg poster en melding til et aspekt (dvs. en privat post), hvem kan se den?"
- private_profiles:
- title: "Private profiler"
- whats_in_profile_a: "Biografi, lokalisering, kjønn, og fødselsdag. Det er de greiene i nederste del av siden for redigering av profilen. All denne informasjonen er valgfri - det er opp til deg hvorvidt du fyller den inn. Innloggete brukere som du har lagt til dine aspekter er de eneste menneskene som kan se din private profil. De vil også se de private postene som er postet til aspektet/aspektene de er i, blandet inn med dine offentlige poster, når de besøker din profilside."
- whats_in_profile_q: "Hva er i offentlige profilen min"
- who_sees_profile_a: "En hvilken som helst innlogget bruker som du deler med (altså som du har lagt til et av dine aspekter). Imidlertid, mennesker som følger deg, som som du ikke følger, vil bare se din offentlige informasjon."
- who_sees_profile_q: "Hvem ser offentlige profilen min?"
- who_sees_updates_a: "Noen i aspektene ser endringer på din private profil. "
- who_sees_updates_q: "Hvem ser oppdateringer til private profilen min?"
public_posts:
can_comment_reshare_like_a: "Enhver innloggede diaspora* bruker kan kommentere, videredele, eller liker din offentlige innlegg."
can_comment_reshare_like_q: "Hvem kan kommentere, videredele, eller liker min offentlige innlegg?"
@@ -422,16 +409,6 @@ nb:
title: "Offentlige innlegg"
who_sees_post_a: "Enhver som bruker internett kan potensielt se en post du merker som offentlig, så vær sikker på at du virkelig ønsker å gjøre posten din offentlig. Det er en kjempefin måte å nå ut til verden på."
who_sees_post_q: "Når jeg legger ut noe offentlig, som kan se det?"
- public_profiles:
- title: "Offentlige profiler"
- what_do_tags_do_a: "De hjelper andre med å bli kjent med deg. Profilbildet ditt vil dessuten vises til venstre i sidene for de tag-ene, sammen med andre som har disse i sin offentlige profil."
- what_do_tags_do_q: "Hva gjør taggene på offentlige profilen min?"
- whats_in_profile_a: "Navnet ditt, de fem tag-ene du valgte for å beskrive deg selv, og bildet ditt. Det er de greiene i øverste seksjon i siden for profilredigering. Du kan gjøre denne profilinformasjonen så identifiserbar eller anonym som du vil. Profilsiden din viser også eventuelle offentlige poster som du har laget."
- whats_in_profile_q: "Hva er i offentlige profilen min"
- who_sees_profile_a: "Enhver innlogget diaspora*-bruker, og også resten av internett, kan se den. Hver profil har en direkte URL, så den kan linkes til direkte fra andre nettsteder. Den kan indekseres av søkemotorer."
- who_sees_profile_q: "Hvem ser offentlige profilen min?"
- who_sees_updates_a: "Alle kan se endringer hvis de besøker profilen din."
- who_sees_updates_q: "Hvem ser oppdateringer til offentlige profilen min?"
resharing_posts:
reshare_private_post_aspects_a: "Nei, det er ikke mulig å videredele en privat post. Sånn er det for å respektere intensjonene til den opprinnelige posteren som kun delte den med en bestemt gruppe personer."
reshare_private_post_aspects_q: "Kan jeg videredele et privat innlegg med kun bestemte aspekter?"
diff --git a/config/locales/diaspora/nds.yml b/config/locales/diaspora/nds.yml
index ca3a2bd4d..c16f37530 100644
--- a/config/locales/diaspora/nds.yml
+++ b/config/locales/diaspora/nds.yml
@@ -298,7 +298,6 @@ nds:
markdown: "Markdown"
mentions:
how_to_mention_q: "Wie kann ik wen erwähnen, wenn ik een Bidrag schriev?"
- mention_in_comment_a: "Nee, grood nich."
mention_in_comment_q: "Kann ik wen in een Kommentar erwähnen?"
see_mentions_a: "Ja, klick in de linke Spalte von diene Startsiet op „@Erwähnungen”."
see_mentions_q: "Gift dat eene Mööglichkeit, de Bidräg to seen, in de ik erwähnt worn bin?"
@@ -321,10 +320,6 @@ nds:
embed_multimedia_q: "Wie bau ik een Video, Toon oder annern Multimedia-Inhalt in miene Bidräg in?"
format_text_q: "Wie kann ik den Text in miene Bidräg formatieren (fett, kursiv und so wieder)?"
hide_posts_q: "Wie verstek ik een Bidrag?"
- image_text: "Bildtext"
- image_url: "Bildadress"
- insert_images_comments_a1: "Du kannst keene Bilder in Kommentare hochloden, aber du kannst den folgenden Markdown-Code"
- insert_images_comments_a2: "bruken üm Bilder ut’n Internet sowohl in Kommentare as uk in Bidräg intobringen."
insert_images_comments_q: "Kan ik Bilder in Kommentare inbringen?"
insert_images_q: "Wie kann ik Bilder in miene Bidräg inbringen?"
size_of_images_a: "Nee. De Grött von Bilder ward automatisch so ännert, dat se in den Stream oder de Inkelbidragsansicht rinpasst. Markdown het keenen Code, um de Grött von een Bild antogeben."
@@ -342,14 +337,6 @@ nds:
title: "Private Bidräg"
who_sees_post_a: "Nur anmeldte Bruker von diaspora*, de du in den Aspekt rindoon haast, bevör du den Bidrag schreeben hest, künnt em sehn."
who_sees_post_q: "Wenn ik een Bidrag an een Aspekt schriev (t.B. een privaten Bidrag), wer kann em sehn?"
- private_profiles:
- title: "Private Profile"
- whats_in_profile_a: "In dien privates Profil sind diene Beschriebung, dien Ort, dien Geschlecht und dien Geburtsdag, falls du disse Felder utfüllt hest. Alle disse Informationen sind freewillig – Dat ligt in diene Hand, op du jüm bereetstellst. Anmeldte Bruker, de du to diene Aspekte dortaudoon hest, sind de eenzigen Lüüd, de dien privates Profil sehn künnt. Wenn se diene Profilsiet beseukt, ward se neben diene öffentlichen Bidräg uk diene privaten Bidräg sehn, de du an de Aspekte schreeben hest, in de du jüm insortiert hest."
- whats_in_profile_q: "Wat is in mien privates Profil?"
- who_sees_profile_a: "Jede anmeldte Bruker, mit den du deelst (dat heet, de du to een von diene Aspekte dortaudoon hest). Lüüd, de di folgt ohne dat du jüm folgst, ward aber nur diene öffentlichen Informationen sehn."
- who_sees_profile_q: "Wer sütt mien privates Profil?"
- who_sees_updates_a: "Jeder in diene Aspekte sütt Ännerungen an dien privates Profil. "
- who_sees_updates_q: "Wer sütt Ännerungen an mien privates Profil?"
public_posts:
can_comment_reshare_like_a: "Jede anmeldte Bruker von diaspora* kann diene öffentlichen Bidräg kommentieren, widerseggen oder Gefallen an em bekunden."
can_comment_reshare_like_q: "Wer kann mien öffentlichen Bidrag kommentieren, widerseggen oder Gefallen an em bekunden?"
@@ -358,13 +345,6 @@ nds:
title: "Öffentliche Bidräg"
who_sees_post_a: "Grundsätzlich kann jeder, de dat Internet brukt, een Bidrag sehn, den du as öffentlich markiert hest, also weest die sicher, dat dien Bidrag wirklich öffentlich ween schall. Dat is eene tolle Mööglichkeit, de wide Welt to erreichen."
who_sees_post_q: "Wer sütt dat, wenn ik wat öffentlich schriev?"
- public_profiles:
- title: "Öffentliche Profile"
- what_do_tags_do_q: "Wat mokt de Tags op mien öffentliches Profil?"
- whats_in_profile_q: "Wat is in mien öffentliches Profil?"
- who_sees_profile_q: "Wer sütt mien öffentliches Profil?"
- who_sees_updates_a: "Jeder kann Ännerungen sehn, wen he diene Profilsiet besöcht."
- who_sees_updates_q: "Wer sütt Ännerungen an mien öffentliches Profil?"
resharing_posts:
reshare_private_post_aspects_q: "Kan ik een privaten Bidrag an bestimmte Aspekte widerseggen?"
reshare_public_post_aspects_q: "Kan ik een öffentlichen Bidrag an bestimmte Aspekte widerseggen?"
diff --git a/config/locales/diaspora/nl.yml b/config/locales/diaspora/nl.yml
index 1304f79c9..17f63ac06 100644
--- a/config/locales/diaspora/nl.yml
+++ b/config/locales/diaspora/nl.yml
@@ -410,7 +410,6 @@ nl:
mentions:
how_to_mention_a: "Type het \"@\"-teken en begin met het typen van de naam. Een uitklaplijst toont relevante namen waar je makkelijk uit kunt kiezen. Dit kan alleen voor mensen die je in een aspect hebt opgenomen."
how_to_mention_q: "Hoe kan ik iemand in een bericht vermelden?"
- mention_in_comment_a: "Nee, momenteel niet."
mention_in_comment_q: "Kan ik iemand vermelden in een reactie?"
see_mentions_a: "Ja, klik op \"@Mij\" in de linkerkolom op je startpagina."
see_mentions_q: "Kan ik de berichten zien waarin ik zelf ben vemeld?"
@@ -446,11 +445,7 @@ nl:
format_text_q: "Hoe kan ik de tekst in mijn berichten opmaken (vet, schuin etc.)?"
hide_posts_a: "Als je met de muis aan de bovenkant van een bericht staat, verschijnt er een X rechts ervan. Klik daarop om het bericht te verbergen en om notificaties erover te onderdrukken. Je kunt het bericht nog wel zien op de profielpagina van de persoon die het geplaatst had."
hide_posts_q: "Hoe verberg ik een bericht?"
- image_text: "afbeeldingstekst"
- image_url: "afbeeldingsURL"
insert_images_a: "Klik op het kleine camera-pictogram om een afbeelding op te nemen. Je kunt nog een keer op de camera klikken om nog een afbeelding op te nemen, of je kunt verschillende afbeeldingen in één keer selecteren om te uploaden."
- insert_images_comments_a1: "Je kunt geen afbeeldingen toevoegen aan reacties, maar de volgende Markdown code"
- insert_images_comments_a2: "kan worden gebruikt om afbeeldingen van het internet in reacties en berichten op te nemen."
insert_images_comments_q: "Kan ik afbeeldingen plaatsen in reacties?"
insert_images_q: "Hoe plaats ik een afbeelding in een bericht?"
post_location_a: "Klik op het punaise pictogram naast de camaera in het invoerveld. Hiermee voeg je de locatie via OpenStreetMap toe. Je kunt de locatie wijzigen, want misschien wil je liever alleen de plaatsnaam in plaats van het hele adres opgeven."
@@ -481,14 +476,6 @@ nl:
title: "Privéberichten"
who_sees_post_a: "Alleen de in diaspora* ingelogde gebruikers die jij in dat aspect hebt zitten voordat je het besloten bericht plaatste, kunnen het zien."
who_sees_post_q: "Als ik een bericht plaats voor een aspect (bijvoorbeeld een privébericht), wie kan dat dan zien?"
- private_profiles:
- title: "Privéprofielen"
- whats_in_profile_a: "Je privé profielpagina bevat je biografie, locatie, geslacht en geboortedatum als je dat hebt ingevuld.Al deze informatie is optioneel, je bepaalt zelf wat je invult. Ingelogde gebruikers die je in een van je aspecten hebt geplaatst, zijn de enige personen die je privéprofiel kunnen zien. Ze zien ook de besloten berichten die je plaatst voor de aspecten waar ze lid van zijn, samen met je openbare berichten als ze jouw profielpagina bezoeken."
- whats_in_profile_q: "Wat staat er in mijn privéprofiel?"
- who_sees_profile_a: "Iedere ingelogde gebruiker met wie jij deelt (oftewel die jij in een aspect hebt geplaatst) kan het zien. Maar mensen die jou volgen, terwijl jij ze niet volgt, zien alleen je openbare informatie."
- who_sees_profile_q: "Wie kan mijn privéprofiel zien?"
- who_sees_updates_a: "Iedereen in jouw aspecten kan de wijzigingen van je privéprofiel zien. "
- who_sees_updates_q: "Wie ziet de wijzigingen van mijn privéprofiel?"
public_posts:
can_comment_reshare_like_a: "Iedere in diaspora* ingelogde gebruiker kan op je openbare berichten reageren, ze leuk vinden of ze doorgeven."
can_comment_reshare_like_q: "Wie kan reageren op mijn openbare berichten, ze leuk vinden of ze doorgeven?"
@@ -501,16 +488,6 @@ nl:
title: "Openbare berichten"
who_sees_post_a: "In beginsel kan iedereen op het internet je berichten lezen als je ze als openbaar markeert. Dus let wel even op als je openbare berichten plaatst. Het is een heel mooie manier om de wereld te informeren."
who_sees_post_q: "Wie kan mijn openbare berichten zien?"
- public_profiles:
- title: "Openbare profielen"
- what_do_tags_do_a: "Ze helpen om mensen jou te leren kennen. Je profielfoto verschijnt ook links op de tagpagina's, samen met die van andere personen die die tag in hun openbare profiel hebben opgenomen."
- what_do_tags_do_q: "Wat is het nut van de tags op mijn openbare profielpagina?"
- whats_in_profile_a: "Je openbare profiel bevat je naam, vijf tags die je zelf kiest en je profielfoto, als je dat hebt opgegeven, alles is optioneel - je bepaalt zelf wat je op wilt geven. Je kunt de informatie zo identificeerbaar of zo anoniem maken als je zelf wilt. Je profielpagina toont ook al je openbare berichten."
- whats_in_profile_q: "Wat staat er in mijn openbare profiel?"
- who_sees_profile_a: "Iedere ingelogde diaspora* gebruiker, maar eigenlijk iedereen op het internet, kan je openbare profiel zien. Elk profiel heeft een direct URL, waardoor ernaar gelinkt kan worden vanaf externe sites. Ook zoekmachines zouden het kunnen indexeren."
- who_sees_profile_q: "Wie kan mijn openbare profiel zien?"
- who_sees_updates_a: "Iedereen kan de wijzigingen zien als ze je profielpagina bezoeken."
- who_sees_updates_q: "Wie ziet de wijzigingen aan mijn openbare profiel?"
resharing_posts:
reshare_private_post_aspects_a: "Nee, je kunt een besloten bericht niet doorgeven. Dat kan niet omdat we de intenties van de originele plaatser, die het alleen met bepaalde groepen wilde delen, respecteren."
reshare_private_post_aspects_q: "Kan ik een besloten bericht delen met specifieke aspecten?"
diff --git a/config/locales/diaspora/oc.yml b/config/locales/diaspora/oc.yml
index 2b623b040..111d0cf1e 100644
--- a/config/locales/diaspora/oc.yml
+++ b/config/locales/diaspora/oc.yml
@@ -30,11 +30,11 @@ oc:
poll_participation:
attributes:
poll:
- already_participated: "Avètz ja paticipat a aquel sondatge !"
+ already_participated: "Avètz ja paticipat a aquel sondatge !"
reshare:
attributes:
root_guid:
- taken: "Es tròp crane non ? Avètz ja partejat aquesta publicacion !"
+ taken: "Es tròp crane non ? Avètz ja partejat aquesta publicacion !"
user:
attributes:
email:
@@ -81,7 +81,7 @@ oc:
one: "%{count} partiment"
other: "%{count} partiments"
zero: "Pas cap de partiment"
- tag_name: "Nom de l'etiqueta : <b>%{name_tag}</b> Nombre : <b>%{count_tag}</b>"
+ tag_name: "Nom de l'etiqueta : %{name_tag} Nombre : %{count_tag}"
usage_statistic: "Estatisticas d'utilizacion"
users:
one: "%{count} utilizaire"
@@ -128,7 +128,7 @@ oc:
weekly_user_stats:
amount_of:
one: "%{count} novèl utilizaire aquesta setmana"
- other: "Nombre de novèls utilizaires aquesta setmana : %{count}"
+ other: "Nombre de novèls utilizaires aquesta setmana : %{count}"
zero: "Pas cap de novèl utilizaire aquesta setmana "
current_server: "La data actuala del servidor es %{date}"
all_aspects: "Totes los aspèctes"
@@ -149,7 +149,7 @@ oc:
contact_developer: "Deuriatz contactar lo desvolopaire de l'aplicacion e inclure lo messatge d'error detalhat seguent :"
could_not_authorize: "L'aplicacion a pas pugut èsser autorizada"
login_required: "D'en primièr, vos cal vos connectar per fin de poder autorizar aquesta aplicacion"
- title: "Ops ! Quicòm a trucat :("
+ title: "Ops ! Quicòm a trucat :("
scopes:
aud:
description: "Aquò dòna la permission aud a l'aplicacion"
@@ -189,7 +189,7 @@ oc:
revoke_autorization: "Revocar"
tos: "Veire las condicions d'utilizacion de l'aplicacion"
are_you_sure: "Sètz segur ?"
- are_you_sure_delete_account: "Sètz segur que volètz tampar vòstre compte ? Aquò se pòt pas anullar !"
+ are_you_sure_delete_account: "Sètz segur que volètz tampar vòstre compte ? Aquò se pòt pas anullar !"
aspect_memberships:
destroy:
failure: "La persona a pas pogut èsser levada de l'aspècte amb succès."
@@ -223,12 +223,12 @@ oc:
donate_liberapay: "Far un don a liberapay"
help:
any_problem: "Avètz agut un problèma ?"
- contact_podmin: "Contactar l'administrator de vòstre pod !"
+ contact_podmin: "Contactar l'administrator de vòstre pod !"
do_you: "Volètz :"
feature_suggestion: "... far una suggestion de %{link} ?"
find_a_bug: "... signalar %{link} ?"
have_a_question: "... pausar una %{link} ?"
- here_to_help: "La comunautat diaspora* es aquí !"
+ here_to_help: "La comunautat diaspora* es aquí !"
mail_podmin: "Corrièl del podmin"
need_help: "Besonh d'ajuda ?"
support_forum: "Podètz tanben contactar lo %{support_forum}."
@@ -237,23 +237,23 @@ oc:
tag_feature: "suggestion"
tag_question: "question"
tutorial_link_text: "Tutorials"
- tutorials_and_wiki: "%{faq}, %{tutorial} e %{wiki} : vos ajudan per vòstres primièrs passes."
+ tutorials_and_wiki: "%{faq}, %{tutorial} e %{wiki} : vos ajudan per vòstres primièrs passes."
introduce_yourself: "Es vòstre flux. Rejonhètz-nos e presentatz-vos."
- keep_pod_running: "Permetètz a %{pod} de foncionar rapidament e ofrissètz una dòsi de cafè mesadièra a nòstres servidors !"
+ keep_pod_running: "Permetètz a %{pod} de foncionar rapidament e ofrissètz una dòsi de cafè mesadièra a nòstres servidors !"
new_here:
- follow: "Seguissètz %{link} e aculhissètz los novèls utilizaires de diaspora* !"
+ follow: "Seguissètz %{link} e aculhissètz los novèls utilizaires de diaspora* !"
learn_more: "Ne saber mai"
title: "Aculhir los novèls venguts"
services:
content: "Podètz connectar aqueles servicis a diaspora* :"
heading: "Connectar de servicis"
- welcome_to_diaspora: "Benvenguda dins diaspora*, %{name} !"
+ welcome_to_diaspora: "Benvenguda dins diaspora*, %{name} !"
no_contacts_message:
community_spotlight: "Actualitat de la comunautat"
invite_link_text: "convidar"
or_spotlight: "O podètz partejar amb %{link}"
try_adding_some_more_contacts: "Podètz recercar o %{invite_link} mai de contactes."
- you_should_add_some_more_contacts: "Vos cal apondre un pauc mai de contactes !"
+ you_should_add_some_more_contacts: "Vos cal apondre un pauc mai de contactes !"
seed:
acquaintances: "Coneissenças"
family: "Familha"
@@ -265,15 +265,22 @@ oc:
blocks:
create:
failure: "Ai pas pogut ignorar aqueste utilizaire. #evasion"
- success: "D'acòrdi, tornaretz pas veire aqueste utilizaire dins vòstre flux. #silenci !"
+ success: "D'acòrdi, tornaretz pas veire aqueste utilizaire dins vòstre flux. #silenci !"
destroy:
failure: "Ai pas pogut quitar d'ignorar aqueste utilizaire. #evasion"
- success: "Vejam çò qu'an a dire ! #digatzbonjorn"
+ success: "Vejam çò qu'an a dire ! #digatzbonjorn"
bookmarklet:
explanation: "Publicatz sus diaspora* d'ont que siá en apondent aqueste ligam => %{link}."
heading: "Publicacion rapida"
post_something: "Publicatz sus diaspora*"
cancel: "Anullar"
+ color_themes:
+ dark: "Escur"
+ dark_green: "Verd escur"
+ egyptian_blue: "Blau egipcian"
+ magenta: "Magenta"
+ original: "Gris d’origina"
+ original_white: "Fons blanc d’origina"
comments:
create:
error: "Fracàs al moment de comentar."
@@ -286,7 +293,7 @@ oc:
all_contacts: "Totes los contactes"
community_spotlight: "Actualitat de la comunautat"
my_contacts: "Mos contactes"
- no_contacts: "Sembla que vos cal apondre mai de contactes !"
+ no_contacts: "Sembla que vos cal apondre mai de contactes !"
no_contacts_in_aspect: "Avètz pas encara de contactes dins aqueste aspècte. Çai-jos i a una lista de vòstre contactes que podètz apondre a aqueste aspècte."
no_contacts_message: "Consultatz %{community_spotlight}"
only_sharing_with_me: "Partejan solament amb ieu"
@@ -338,7 +345,7 @@ oc:
correct_the_following_errors_and_try_again: "Corregissètz las errors seguentas, e tornatz ensajar."
need_javascript: "Aqueste site Internet requerís JavaScript per foncionar coma cal. Se avètz desactivat JavaScript, mercés de l'activar e d'actualizar aquesta pagina."
fill_me_out: "Escriure aicí"
- find_people: "Recercar de personas o de #tags"
+ find_people: "Recercar de personas o de #etiquetas"
help:
account_and_data_management:
close_account_a: "Rensètz-vos en bas de la pagina e clicatz sul boton « Tampar lo compte ». Vòstre senhal vos serà demandat per acabar lo processus. Vos rapelam que se tampatz vòstre compte, ne poiretz <strong>pas mai</strong> tornar crear sus aqueste pod amb aqueste nom d'utilizaire."
@@ -347,7 +354,7 @@ oc:
data_other_podmins_q: "Los administrators dels autres pods pòdon veire mas informacions ?"
data_visible_to_podmin_a: "En un mot: tot. La comunicacion entre los pods es totjorn chifrada (en utilizant SSL e lo pròpri transpòrt chifrat de diaspora*), mai las donadas enregistradas suls pods son pas chifradas.Se volián los administrators de la basa de donada de vòstre pod (sovent la persona en carga del pod) poiriá accedir a totas las donadas de vòstre perfil e a tot çò que publicatz (come es lo cas per lo màger dels sites qu'enregistran las informacions dels utilizaires). Aquò explica perque vos donem la possibilitat de causir sus quin pod vos marcar, pr'amor podètz causir un pod que l'administrator li fisatz vòstras donadas. Executar vòstre pod vos dòna mai de confidencialitat perque auretz lo contraròtle sus la basa de donadas."
data_visible_to_podmin_q: "Quina quantitat de mas informacions l'administrator del pod pòt veire ?"
- download_data_a: "Òc. En dejòs de los paramètres de Compte trobaretz dos botons : un per telecargar vòstras donadas e un per telecargar vòstras fotos."
+ download_data_a: "Òc. En dejós de los paramètres de Compte trobaretz dos botons : un per telecargar vòstras donadas e un per telecargar vòstras fotos."
download_data_q: "Pòdi telecargar una còpia de totas las donadas contengudas dins mon compte ?"
move_pods_a: "Dins lo futur poiretz exportar vòstra grana - seed - d'un pod e l'importar dins un autre, mai pel moment es pas possible. Podètz totjorn dubrir un nòu compte e ajustar vòstres contactes sus aquela nòva grana, e lor demandar de vos ajustar sus lors aspèctes amb vòstra nòva grana."
move_pods_q: "Cossí desplaçar mon compte d'un pod a un autre ?"
@@ -383,9 +390,11 @@ oc:
add_contact_roster_q: "Cossí discutir amb qualqu'un dins diaspora* ?"
contacts_page: "pagina dels contactes"
title: "Chat"
+ community_guidelines: "règlas de comportament de la comunautat"
faq: "FAQ"
foundation_website: "site internet de la fondacion diaspora*"
getting_help:
+ get_support_a_discourse: "Cercar de discutidas ligadas a vòstra demanda o dobrir un novèl subjècte dins nòstra plataforma %{discourse}"
get_support_a_faq: "Legir la pagina %{faq} de nòstre wiki"
get_support_a_hashtag: "Pausatz una question dins un messatge public sus diaspora* en utilizant l'hashtag %{question}"
get_support_a_irc: "Rejonhètz-nos sus %{irc} (Chat instantanèu)"
@@ -394,7 +403,7 @@ oc:
get_support_a_wiki: "Recercatz dins lo %{link}"
get_support_q: "De qué far se ma question a pas de responsa dins la FAQ ? A quines autres endreits pòdi obténer de documentcion ?"
getting_started_a: "Sètz astruc. Ensajatz las %{tutorial_series} sul site de nòstre projècte. Vos ajudarà pas a pas de l'inscripcion cap a las causas basicas que vos cal saber per utilizar diaspora*."
- getting_started_q: "Ajudatz-me ! Ai besonh d'ajuda per debutar !"
+ getting_started_q: "Ajudatz-me ! Ai besonh d'ajuda per debutar !"
title: "Obténer d'ajuda"
getting_started_tutorial: "Seria de tutorials « Mos primièrs passes »"
here: "aicí"
@@ -415,7 +424,7 @@ oc:
mentions:
how_to_mention_a: "Picatz lo signe « @ » e començatz a escriure lor nom. Una lista desrotlanta deuriá aparéisser per vos permetre de los causir mai simplament. Notatz qu'es solament possible de mencionar de mond qu'avètz aponduts a un aspècte."
how_to_mention_q: "Cossí pòdi mencionar qualqu'un quand escrivi un messatge ?"
- mention_in_comment_a: "Non pas, pel moment."
+ mention_in_comment_a: "Dempuèi la version 0.7.0.0 podètz ! Podètz mencionar qualqu’un dins un comentari del meteis biais qu’o fasètz dins una publicacion, n’utilizar “@” e començatz a picar lor nom. Notatz que per las publicacions pas publicas, podètz pas que mencionar qualqu’un qu’a interagit amb la publicacion."
mention_in_comment_q: "Pòdi mencionar qualqu'un dins un comentari ?"
see_mentions_a: "Òc, clicatz sus « @Mencions » dins la colomna d'esquèrra de vòstra pagina d'acuèlh."
see_mentions_q: "I a un biais de veire las publicacions que soi mencionat dedins ?"
@@ -429,40 +438,37 @@ oc:
diaspora_app_q: "Existís una aplicacion diaspora* per Android o iOS ?"
photo_albums_a: "Pas pel moment. Pasmens, podètz veire los imatges mandats d'una persona dins l'onglet Fòtos de lor pagina de perfil."
photo_albums_q: "I a d'albums de fòtos o de vidèos ?"
- subscribe_feed_a: "Òc, mai es pas encara una foncion lustrada e lo format dels resultats es totjorn un pauc brut. S'avètz enveja d'ensajar aquò, anatz sus la pagina de perfil de qualqu'un e clicatz sul boton de flux dins vòstre navigador, o podètz copiar l'URL del perfil (ex. https://nomdelpod.org/mond/unnumero) e pegatz aquò dins un lector de flux. L'adreça del flux semblarà a aquò : https://podname.org/public/username.atom – diaspora* utiliza Atom e non pas RSS."
+ subscribe_feed_a: "Òc, mai es pas encara una foncion lustrada e lo format dels resultats es totjorn un pauc brut. S'avètz enveja d'ensajar aquò, anatz sus la pagina de perfil de qualqu'un e clicatz sul boton de flux dins vòstre navigador, o podètz copiar l'URL del perfil (ex. https://nomdelpod.org/mond/unnumero) e pegatz aquò dins un lector de flux. L'adreça del flux semblarà a aquò : https://podname.org/public/username.atom – diaspora* utiliza Atom e non pas RSS."
subscribe_feed_q: "Me pòdi inscriure als messatges publics d'una persona amb un lector de fluxes ?"
title: "Divèrs"
pods:
- find_people_a: "Se volètz convidar vòstres amics a venir sus diaspora*, utilizatz lo ligam d'invitacion o lo ligam per corrièl. Seguètz d'#etiquetas per conéisser de mond que partejan vòstres interèsses , e ajustatz aqueles que publican de causas que vos interèssan a un aspècte. Cridatz fòrt que sètz #novèlaquí dins una publicacion publica."
+ find_people_a: "Se volètz convidar vòstres amics a venir sus diaspora*, utilizatz lo ligam d’invitacion o lo ligam per corrièl. Seguètz d’#etiquetas per conéisser de mond que partejan vòstres interèsses , e ajustatz aqueles que publican de causas que vos interèssan a un aspècte. Cridatz fòrt que sètz #novèlaquí dins una publicacion publica."
find_people_q: "Veni de rejónher un pod, cossí pòdi trobar de monde per partejar amb eles ?"
title: "Pods"
- use_search_box_a: "Se coneissètz lor ID diaspora* complet (ex. : utilizaire@nomdelpod.org), podètz los trobar en los cercant. Se sètz sul meteis servidor, podètz los trobar sonque amb los noms d'utilizaire. Autrament podètz los cercar amb lor nom de perfil (lo nom que vesètz sus l'ecran). Se una recèrca capita pas lo primièr còp, tornatz ensajar."
+ use_search_box_a: "Se coneissètz lor ID diaspora* complet (ex. : utilizaire@nomdelpod.org), podètz los trobar en los cercant. Se sètz sul meteis servidor, podètz los trobar sonque amb los noms d'utilizaire. Autrament podètz los cercar amb lor nom de perfil (lo nom que vesètz sus l'ecran). Se una recèrca capita pas lo primièr còp, tornatz ensajar."
use_search_box_q: "Cossí me cal utilizar lo camp de recèrca per trobar qualqu'un en particular ?"
- what_is_a_pod_a: "Un pod es un servidor qu’executa lo programa diaspora* e qu’es connectat al malhum diaspora*. « Pod » es una metafòra que fa referéncia a l'anglés, que significa dòlça, perque conten de grans coma lo servidor que conten de comptes d'utilizaires. I a un melon de pods. Podètz apondre d’amics d’autres pods e comunicar amb eles. Cal pas dobrir de compte suls diferents pods ! Cal pas qu’un compte – d’aquel biais podètz pensar un pod coma un fornisseire de corrièls. I a de pods publics, de pods privats, e amb un bocin d’esfòrces podètz aver lo vòstre."
+ what_is_a_pod_a: "Un pod es un servidor qu’executa lo programa diaspora* e qu’es connectat al malhum diaspora*. « Pod » es una metafòra que fa referéncia a l'anglés, que significa dòlça, perque conten de grans coma lo servidor que conten de comptes d'utilizaires. I a un melon de pods. Podètz apondre d’amics d’autres pods e comunicar amb eles. Cal pas dobrir de compte suls diferents pods ! Cal pas qu’un compte – d’aquel biais podètz pensar un pod coma un fornisseire de corrièls. I a de pods publics, de pods privats, e amb un bocin d’esfòrces podètz aver lo vòstre."
what_is_a_pod_q: "Qu'es aquò un pod ?"
posts_and_posting:
char_limit_services_a: "En aquel cas deuriatz restrénher vòstras publicacions al nombre de caractèrs autorizats pel servici (140 per Twitter, 1000 per Tumblr), lo nombre de caractèrs demòran s’aficharà se l’icòna del servici es seleccionada. Podètz pr’aquò escriure de tèxtes mai grands, mai lo tèxte serà talhat e un ligam plaçat cap a la publicacion sus diaspora*."
char_limit_services_q: "Quin es lo limit de caractèrs pels messatges partejats amb un servici qu'a un limit de caractèrs mai pichon ?"
- character_limit_a: "65 535 caractèrs. Son 65 395 caractèrs de mai que Twitter ! :)"
+ character_limit_a: "65 535 caractèrs. Son 65 395 caractèrs de mai que Twitter ! :)"
character_limit_q: "Qual es lo limit de caractèrs per las publicacions ?"
- embed_multimedia_a: "Normalament pas cal pas que pegar l’URL (ex. http://www.youtube.com/watch?v=nnnnnnnnnnn) dins vòstra publicacion e la vidèo o l’àudio serà apondut automaticament. Aqueste site es compatible amb : YouTube, Vimeo, SoundCloud, Flickr e qualques mai. diaspora* emplega oEmbed per aquesta foncionalitat. Cada còp sèm compatibles amb mai sorgas de mèdias. Remembratz-vos de totjorn publicar l’URL completa – pas cap de ligams acorchits – e esperatz un momenton abans d’actualizar la pagina aprèp aver publicat per tal de veire l’ulhada."
+ embed_multimedia_a: "Normalament pas cal pas que pegar l’URL (ex. http://www.youtube.com/watch?v=nnnnnnnnnnn) dins vòstra publicacion e la vidèo o l’àudio serà apondut automaticament. Aqueste site es compatible amb : YouTube, Vimeo, SoundCloud, Flickr e qualques mai. diaspora* emplega oEmbed per aquesta foncionalitat. Cada còp sèm compatibles amb mai sorgas de mèdias. Remembratz-vos de totjorn publicar l’URL completa – pas cap de ligams acorchits – e esperatz un momenton abans d’actualizar la pagina aprèp aver publicat per tal de veire l’ulhada."
embed_multimedia_q: "Cossí pòdi inserir un contengut vidèo, àudio, o multimèdia dins una publicacion ?"
format_text_a: "N'emplegant un sistèma simplifiat apelat %{markdown}. Podètz trapar tota la sintaxi de Markdown %{here}. Lo boton d'apercebut pòt èsser de bona ajuda, permet de veire vòstre messatge coma serà afichat abans de o partejar."
format_text_q: "Cossí pòdi formatar lo tèxte dins as publicacions (gras, italic, etc.) ?"
hide_posts_a: "Se posicionatz la mirga de naut d'una publicacion, una X aprareis a man drecha. Clicatz-la per escondre la publicacion e metre en silenci las notificacions ligadas a aquela. Podètz totjorn veire la publicacion se visitatz lo perfil de la persona que la publiquèt."
hide_posts_q: "Cossí escondi una publicacion ?"
- image_text: "tèxte de l'imatge"
- image_url: "url de l'imatge"
insert_images_a: "Clicatz sus la pichona icòna camerà per inserir un imatge dins una publicacion. Tornatz clicar sus l'icòna per apondre una fòto mai, o ne podètz seleccionar mantun per enviar d'un còp."
- insert_images_comments_a1: "Podètz pas mandar d'imatges dins los comentaris mas lo còdi Markdown seguent"
- insert_images_comments_a2: "aquò pòt èsser utiizat per inserir d'imatges a partir del web dins los comentaris o los messatges."
+ insert_images_comments_a: "Podètz utilisar la sintaxi Markdown per inserir un imatge del web sus un comentari, coma per las publicacions. Pr’aquò, podètz pas enviar un imatge directament dempuèi vòstre ordenador. Mandatz-lo a un servici d’albergament en linha puèi inserissètz l’imatge en utilizar lo boton al dessús de l’editor."
insert_images_comments_q: "Pòdi inserir d'imatges dins un comentari ?"
insert_images_q: "Cossí pòdi inserir d'imatges dins un messatge ?"
post_location_a: "Clicatz dins l'aisina d'edicion l'icòna de l'espilla a costat de la camerà. Aquò inserirà vòstre emplaçament d'OpenStreetMap. Podètz modificar vòstre emplaçament – benlèu que volètz pas qu'indicar la vila ont sètz e non pas l'adreça amb la carrièra."
post_location_q: "Cossí pòdi apondre ma posicion a un messatge ?"
post_notification_a: "Trobaretz l'icòna d'una campana prèp de la X a man drecha de la publicacion. Clicatz-la per activar o desactivar las notificacions per aquesta publicacion."
post_notification_q: "Cossí pòdi activar o desactivar las notificacions per un messatge ?"
- post_poll_a: "Clicatz sus l'icòna graf per generar un sondatge. Picatz una question e almens doas responsas. Doblidetz pas de far vòstre publicacion publica se volètz que tot lo mond pòsca participar a vòstre sondatge."
+ post_poll_a: "Clicatz sus l'icòna graf per generar un sondatge. Picatz una question e almens doas responsas. Oblidetz pas de far vòstre publicacion publica se volètz que tot lo mond pòsca participar a vòstre sondatge."
post_poll_q: "Cossí pòdi apondre un sondatge a mon messatge ?"
post_report_a: "Clicatz l'icòna del triangle d'alèrta amont a man drecha de la publicacion per la senhalar a vòstre podmin. Marcatz la rason del senhalament d'aquela publicacion dins la zòna de tèxte."
post_report_q: "Cossí pòdi senhalar un messatge ofensant ?"
@@ -472,28 +478,28 @@ oc:
stream_full_of_posts_li1: |-
Las publicacions del mond que partejatz, i a doas categorias :
las publicacions publicas e las publicacions limitadas a un aspècte que ne fasètz partit. Per levar aquelas publicacions de vòstre flux d'actualitat, vos cal pas que quitar de partejar amb aquela persona.
- stream_full_of_posts_li2: "Los messatges publics contenon un dels tags que seguissètz. Per los suprimir, daissatz de seguir lo tag."
+ stream_full_of_posts_li2: "Los messatges publics contenon una de las etiquetas que seguissètz. Per los suprimir, quitatz de seguir l’etiqueta."
stream_full_of_posts_li3: "Las publicacions publicas del mond listat dins las actualitat de la comunitat. Pòdon èsser levadas en clicant sus l'opcion « Afichar las novèlas de la comunitat dins la flux ? » dins l'onglet Compte de vòstre Paramètres."
stream_full_of_posts_q: "Perqué mon flux es plen de messatges que provenon de monde que coneissi pas e amb las qualas partegi pas ?"
title: "Publicacions e publicar"
private_posts:
can_comment_a: "Solament los utilizaires de diaspora* connectats qu'avètz plaçats dins aquel aspècte abans de passar la publicacion privada pòdon la comentar o l'aimar."
can_comment_q: "Qual pòt comentar o a qual pòt agradar un messatge privat ?"
- can_reshare_a: "Degun. Las publicacions privadas se pòdon pas tornar partejar. Los utilizaires connectats dins aqueste aspècte pòdon potencialament o copiar e pegar pasmens. Depend de vos se vos fisatz d'aqueste monde !"
+ can_reshare_a: "Degun. Las publicacions privadas se pòdon pas tornar partejar. Los utilizaires connectats dins aqueste aspècte pòdon potencialament o copiar e pegar pasmens. Depend de vos se vos fisatz d'aqueste monde !"
can_reshare_q: "Qual pòt repartejar mos messatges privats ?"
see_comment_a: "Solament lo mond amb qui la publicacion es partejada (lo mond qu'es dins l'aspècte causit per lo prim publicaire) pòdon veire sos comentaris e mencion « m'agrada ». "
see_comment_q: "Quand comenti un messatge privat o que marqui que m'agrada , qual o pòt veire ?"
title: "Publicacions privadas"
who_sees_post_a: "Solament los utilizaires de diaspora* connectats qu'avètz plaçats dins aquel aspècte abans de passar la publicacion privada pòdon la veire."
who_sees_post_q: "Quand mandi un messatge a un aspècte (es a dire un messatge privat), qual o pòt veire ?"
- private_profiles:
- title: "Perfils privats"
- whats_in_profile_a: "Vòstre perfil privat conten vòstra biografia, emplaçament, gendre, e data d’anniversari s’avètz garnit aquelas seccions. Totas aquelas informacions son opcionalas – causissètz o pas de las fornir. Lo mond connectats al site e qu’avètz aponduts a vòstres aspèctes son los solets a poder veire vòstre perfil privat. Quand visitan vòstra pagina de perfil veiràn tanben vòstras publicacions privadas ligadas al(s) aspèctes ont son, mescladas a vòstras publicacions publicas."
- whats_in_profile_q: "Qu'es aquò mon perfil privat ?"
- who_sees_profile_a: "Solament los utilizaires connectats e que partejatz amb eles (vòl dire, qu'avètz apondut a un de vòstres aspèctes). Pasmens, lo mond que vos sèc, mai que seguètz pas, veiràn pas que vòstras informacions publicas."
- who_sees_profile_q: "Qual pòt veire mon perfil privat ?"
- who_sees_updates_a: "Qual que siá dins vòstres aspèctes pòt veire las modificacions de vòstre perdil privat."
- who_sees_updates_q: "Qual pòt veire las mesas a jorn de mon perfil privat ?"
+ profile:
+ title: "Perfil"
+ what_do_tags_do_a: "Ajudan al monde a vos conéisser. Vòstra fotografia de perfil apareisserà a man esquèrra de la pagina d’actualitat d’aquelas etiquetas, demest lo monde que las tenon dins lor perfil de basa."
+ what_do_tags_do_q: "Per que servisson las etiquetas dins mon perfil de basa ?"
+ whats_in_profile_a: "Vòstre perfil es en doas parts : vòstre perfil basic e vòstre perfil espandit. Vòstre perfil basic conten vòstre nom, las cinc etiquetas qu'avètz causidas per vos descriure e vòstra fotografia. Vòstre perfil espandit conten vòstra biografia, vòstre emplaçament, gendre e vòstre aniversari. Totas aquelas informacions son opcionalas – causissètz vosautres meteisses de las donar e causissètz de las far venir tantas identificablas o anonimas, coma o volètz. Vòstre perfil espandit se mòstra en vòstre pagina de perfil a man esquèrra, jos vòstre fotografia."
+ whats_in_profile_q: "Que i a dins mon perfil ?"
+ who_sees_profile_a: "Vòstre perfil basic (nom, fotografia de perfil e #etiquetas) es public. Vòstre perfil espandit es privat per defaut, podètz cambiar la confidencialitat coma vos agrade. Solament lo monde que partejan amb vos (valent a dire : los avètz aponduts a un de vòstres aspèctes) pòdon veire vòstre perfil espandit se lo mantenètz privat. La rèsta del monde veson pas que las informacions de vòstre perfil public. Tota informacion que fasètz publica pòt èsser vista per qual que siá sus Internet, e pòt èsser indexada pels motors de recèrca."
+ who_sees_profile_q: "Qual vei mon perfil public ?"
public_posts:
can_comment_reshare_like_a: "Quin utilizaire connectat a diaspora* que siá, pòt comentar, repartejar vòstre messatge public o marcar que li agrada."
can_comment_reshare_like_q: "Qual pòt comentar, repartejar, o marcar que li agrada mon messatge public ?"
@@ -506,16 +512,6 @@ oc:
title: "Publicacions publicas"
who_sees_post_a: "Qual que siague qu'utiliza internet pòt potencialament veire una publicacion que marcatz publica, doncas asseguratz-vos de voler vertadièrament qu'una publicacion siague publica. Es una manièra de las bonas per aténher de mond."
who_sees_post_q: "Quand publiqui quicòm publicament, qual pòt veire ?"
- public_profiles:
- title: "Perfils publics"
- what_do_tags_do_a: "Ajudan lo mond a vos conéisser. Vòstra fòto de perfil apareisserà tanben a man esquèrra d'aquelas paginas d'etiquetas, entre los demai qu'an tanben aquestas etiquetas dins lors perfil public."
- what_do_tags_do_q: "De qué fan los tags sus mon perfil public ?"
- whats_in_profile_a: "Vòstre perfil public conten vòstre nom, las cinc etiquetas qu'avètz causidas per vos descriure, e vòstras fotografias, s'avètz garnit aquelas seccions. Totas aquelas informacions son opcionalas – causissètz vosautres meteisses de las donar. Podètz far venir aquelas informacions de perfil tan identificablas o anonimas coma volètz. Vòstre perfil mòstra tanben las publicacions publicas qu'avètz fachas."
- whats_in_profile_q: "Qué i a sul meu perfil public ?"
- who_sees_profile_a: "Tot utilizaire connectat a diaspora*, e tot lo grand Internet, pòt veire aquò. Cada perfil ten una URL dirècta que permet d'i anar directament a partir d'autres sites. Los motors de recèrca pòdon l'indexar."
- who_sees_profile_q: "Qual vei mon perfil public ?"
- who_sees_updates_a: "Qual que siá pòt veire aqueles cambiaments en visitant vòstra pagina de perfil."
- who_sees_updates_q: "Qual pòt veire las mesas a jorn de mon perfil public ?"
resharing_posts:
reshare_private_post_aspects_a: "Non, es pas possible de tornar partejar una publicacion privada. Aquò es per respectar las intencions del prim publicaire, que l'a partejada amb un gropon especial de personas."
reshare_private_post_aspects_q: "Pòdi repartejar un messatge privat unicament amb certans aspèctes ?"
@@ -536,7 +532,7 @@ oc:
add_to_aspect_q: "Qué passa quand apondi qualqu'un a un de mos aspèctes, o quand qualqu'un m'apond als seus aspèctes ?"
list_not_sharing_a: "Non pas, mas podètz veire se qualqu'un parteja amb vos en visitant sa pagina de perfil. Se parteja amb vos, lo boton que mòstra lo(s) aspecète(s) ont l'avètz mes serà verd, autrament serà gris."
list_not_sharing_q: "I a una lista del mond qu'ai apondut sus un de mos aspèctes mai que m'an pas apondut de lor costat ?"
- only_sharing_a: "Son lo mond que vos an apondut a lor aspècte, mai que son pas - encara - dins vòstres aspèctes. Dich autrament, partejan amb vos, mai partejatz pas amb eles : podètz o pensar aissí, vos « seguisson ». Se los apondètz a un aspècte, pareisseràn dins aqueste e non pas coma « Partejan solament amb ieu ». Veire çai-jos."
+ only_sharing_a: "Son lo mond que vos an apondut a lor aspècte, mai que son pas - encara - dins vòstres aspèctes. Dich autrament, partejan amb vos, mai partejatz pas amb eles : podètz o pensar aissí, vos « seguisson ». Se los apondètz a un aspècte, pareisseràn dins aqueste e non pas coma « Partejan solament amb ieu ». Veire çai-jos."
only_sharing_q: "Qui son los listats dins « Partejan solament amb ieu » sus ma pagina de contactes ?"
see_old_posts_a: "Non. Poiràn pas que veire las novèlas publicacions dins aqueste aspècte. Pòdon veire vòstras vièlhas publicacions sus vòstra pagina de perfil, e benlèu tanben dins lor flux d'actualitat."
see_old_posts_q: "Quand apondi qualqu'un a un aspècte, pòdon veire mas ancianas publicacions qu'ai ja publicadas a aqueste aspècte ?"
@@ -545,13 +541,13 @@ oc:
title: "Partatge"
tags:
filter_tags_a: "Aquesta foncion es pas directament disponibla dins diaspora*, mai unes %{third_party_tools} son estats escrichs per far o."
- filter_tags_q: "Cossí pòdi filtrar/exclure certans tags de mon flux ?"
+ filter_tags_q: "Cossí pòdi filtrar/exclure certanas etiquetas de mon flux ?"
followed_tags_a: "Aprèp aver cercat una etiqueta podètz clicar sul boton amont de la pagina de las etiquetas per « seguir »aquesta etiqueta. Apareisserà dins vòstre lista d’etiquetas seguidas sul menú a man drecha. En clicant sus una de vòstras etiquetas seguidas aquò vos menarà sus la pagina d’aquesta etiqueta per veire las publicacions recentas que contenon aquesta etiqueta. Clicatz sus #Etiquetas seguidas per veire un flux de publicacions que contenon totes las etiquetas que seguissètz."
- followed_tags_q: "De qué son los \"#Tags Seguits\" e cossí pòdi seguir un tag ?"
- people_tag_page_a: "I a monde qu'an listat aqueste tag per se descriure eles-meteisses dins lor perfil public."
- people_tag_page_q: "Qualas son las personas listadas sus la partida d'esquèrra d'una pagina de tag ?"
+ followed_tags_q: "De qué son las \"#Etiquetas Seguidas\" e cossí pòdi seguir una etiqueta ?"
+ people_tag_page_a: "I a monde qu'an listat aquesta etiqueta per se descriure eles-meteisses dins lor perfil public."
+ people_tag_page_q: "Qualas son las personas listadas sus la partida d'esquèrra d'una pagina d'etiquetas ?"
tags_in_comments_a: "Una etiqueta aponduda a un comentari apareisserà coma un ligam cap a la pagina d'etiquetas correspondenta, mai farà pas aparéisser la publicacion (o comentari) dins aquela pagina. Aquò fonciona pas qu'amb las etiquetas sus las publicacions."
- tags_in_comments_q: "Pòdi inserir de tags dins un comentari o sonque dins de messatges ?"
+ tags_in_comments_q: "Pòdi inserir d'etiquetas dins un comentari o sonque dins de messatges ?"
title: "Etiquetas"
what_are_tags_for_a: "Las etiquetas son un biais de triar una publicacion, sovent un tèma. Cercar una etiqueta ensenha las publicacions, tan publicas coma privadas, amb aquesta etiqueta qu'avètz la permission de veire. Aquò permet al mond qu'es interessat per un tèma de trobar de publicacions ligadas a aquò."
what_are_tags_for_q: "A qué servisson las etiquetas ?"
@@ -576,7 +572,7 @@ oc:
configure_your_pod: "Configuratz vòstre pod"
contact_irc: "nos contactar sus IRC"
contribute: "Contribuissètz"
- contribute_info: "Rendètz diaspora* encara melhor ! Se rencontratz de bugs, %{report_bugs} se vos plai."
+ contribute_info: "Rendètz diaspora* encara melhor ! Se rencontratz de bugs, %{report_bugs} se vos plai."
create_an_account: "Creatz un compte"
create_an_account_info: "%{sign_up_link} per un novèl compte"
faq_for_podmins: "FAQ pels podmins sus nòstre wiki"
@@ -597,8 +593,8 @@ oc:
closed: "Los convits son tampats sus aqueste pod diaspora*."
empty: "Mercés de picar almens una adreça de corrièl."
no_more: "Avètz pas mai de convits."
- note_already_sent: "Las invitacions son ja estadas mandadas a : %{emails}"
- rejected: "Las adreças de corrièr electronic seguentas an rencontrat un problèma : %{emails}"
+ note_already_sent: "Las invitacions son ja estadas mandadas a : %{emails}"
+ rejected: "Las adreças de corrièr electronic seguentas an rencontrat un problèma : %{emails}"
sent: "Los convits son estats mandats a %{emails}"
new:
codes_left:
@@ -606,7 +602,7 @@ oc:
other: "Encara %{count} convits de disponibles amb aqueste còdi."
zero: "Pas mai de convit de disponible amb aqueste còdi."
comma_separated_plz: "Podètz entrar mantuna adreça de corrièl separadas per de virgulas."
- invite_someone_to_join: "Convidar qualqu'un a rejónher diaspora* !"
+ invite_someone_to_join: "Convidar qualqu'un a rejónher diaspora* !"
language: "Lenga"
paste_link: "Partejatz aqueste ligam amb vòstres amics per los convidar dins diaspora*, o mandatz-lor aqueste ligam dirèctament per corrièl."
send_an_invitation: "Mandar un convit"
@@ -614,7 +610,7 @@ oc:
layouts:
application:
back_to_top: "Tornar amont"
- be_excellent: "Siatz benvolent amb cadun !"
+ be_excellent: "Siatz benvolent amb cadun !"
discourse: "Discutidas e assisténcia del projècte"
powered_by: "Propulsat per dispora*"
public_feed: "Flux diaspora* public per %{name}"
@@ -664,6 +660,7 @@ oc:
mark_read: "Marcar coma legit"
mark_unread: "Marcar coma pas legit"
mentioned: "Mencionat dins una publicacion"
+ mentioned_in_comment: "Mencionat dins un comentari"
no_notifications: "Avètz pas encara cap de notificacion."
notifications: "Notificacions"
reshared: "Repartejat"
@@ -686,6 +683,12 @@ oc:
one: "%{actors} vos a mencionat sus una publicacion suprimida."
other: "%{actors} vos an mencionat sus una publicacion suprimida."
zero: "%{actors} vos a mencionat sus una publicacion suprimida."
+ mentioned_in_comment:
+ one: "%{actors} vos a mencionat dins un <a href='%{comment_path}'>comentari</a> a la publicacion %{post_link}."
+ other: "%{actors} vos an mencionat dins un <a href='%{comment_path}'>comentari</a> a la publicacion%{post_link}."
+ mentioned_in_comment_deleted:
+ one: "%{actors} vos a mencionat dins un comentari suprimit."
+ other: "%{actors} vos an mencionat dins un comentari suprimit."
private_message:
one: "%{actors} vos a mandat un messatge."
other: "%{actors} vos an mandat un messatge."
@@ -719,23 +722,23 @@ oc:
body: |-
Adissiatz %{name}, 
- diaspora* a detectat un ensag d’accès a vòstre sesilha que poiriá èsser pas autorizat. Per evitar que vòstras donadas siasguen gastadas sètz estat desconnectat. Vos copetz pas lo cap, vos podètz tornar connectar en seguretat ara. 
+ diaspora* a detectat un ensag d’accès a vòstre sesilha que poiriá èsser pas autorizat. Per evitar que vòstras donadas sián gastadas sètz estat desconnectat. Vos copetz pas lo cap, vos podètz tornar connectar en seguretat ara. 
 
Una demanda es estada facha n’emplegant un geton CSRF incorrècte o absent. Aquò poiriá èsser completament innocent, mai aquò pòt tanben èsser un atac apelat Cross-site request forgery (CSRF). 
 
- Aquò pòt venir de : 
+ Aquò pòt venir de :
 
  - una extension que manipula la demanda o que fa de demanda sens lo geton;
-   - un onglet daissat dubèrt d’una anciana sesilha;
+   - un onglet daissat dubèrt d’una anciana session;
  - un fum d’aisinas extèrnas;
  - un marrit còdi qu’ensaja d'accedir a vòstras donadas. 
 
Per mai informacion subre l’atac CSRF vejatz [%{link}](%{link}). 
 
- Se tenètz vist aqueste messatge, mercés de verificar los punts al dessús, inclús las extensions de qual que siague navigador. 
+ Se tenètz vist aqueste messatge, mercés de verificar los punts al dessús, inclús las extensions de qual que siá navigador. 
 
Mercés, 
- Lo robòt de corrièl a diaspora* !
+ Lo robòt de corrièl a diaspora* !
subject: "Avèm recebut una demanda sens autorizacion de vòstre compte, %{name}"
email_sent_by_diaspora: "Aqueste corrièl es estat mandat per %{pod_name}. Se volètz pas mai de corrièls atal,"
export_email:
@@ -780,27 +783,28 @@ oc:
Lo messatgièr automatic de diaspora*
subject: "I a agut un problèma amb vòstras fòtos, %{name}"
- hello: "Adiu %{name} !"
+ hello: "Adiu %{name} !"
invite:
message: |-
- Bonjorn !
+ Bonjorn !
- %{diaspora_id} vos a convidat a rejónher diaspora* !
+ %{user} vos a convidat a rejónher diaspora* !
Clicatz sul ligam per començar
%{invite_url}[1]
- O podètz apondre %{diaspora_id} amb vòstres contactes se avètz ja un compte.
+ O podètz apondre %{diaspora_id} amb vòstres contactes s’avètz ja un compte.
+
Amistats,
- Lo messatgièr automatic de diaspora* !
+ Lo messatgièr automatic de diaspora* !
- P.S : En cas que coneisseriatz pas (encara) çò qu'es diapora*, aicí[2] i a la responsa !
+ P.S : En cas que coneisseriatz pas (encara) çò qu’es diapora*, aicí[2] i a la responsa !
- [1] : %{invite_url}
- [2] : %{diasporafoundation_url}
+ [1] : %{invite_url}
+ [2] : %{diasporafoundation_url}
invited_you: "%{name} vos a convidat sus diaspora*"
liked:
liked: "A %{name}, li a agradat vòstra publicacion"
@@ -809,23 +813,25 @@ oc:
mentioned:
limited_post: "Sètz estat mencionat dins una publicacion restenta."
subject: "%{name} vos a mencionat sus diaspora*"
+ mentioned_in_comment:
+ limited_post: "Sètz mencionat dins un comentari al accès limitat."
+ reply: "Respondre o veire la conversacion >"
private_message:
reply_to_or_view: "Respondre o afichar aquela conversacion >"
subject: "Avètz un novèl messatge privat"
remove_old_user:
body: |-
Bonjorn,
-
En rason de l'inactivitat de vòstre compte diaspora* %{pod_url}, planhèm de vos informar que lo sistèma l'a identificat coma devent èsser suprimit automaticament. Aquesta procedura se desenclava aprèp un periòde d'inactivitat superior a %{after_days} jorns.
Podètz evitar la pèrda de vòstre compte en vos connectant a aqueste abans %{remove_after}, dins aqueste cas la procedura de supression serà automaticament anullada.
- Aquesta mantenença es efectuada per assegurar als utilizaires actius lo mehor foncionament possible d'aquesta instància de diaspora*. Vos mercejam de vòstra compreneson.
+ Aquesta mantenença es efectuada per assegurar als utilizaires actius lo melhor foncionament possible d'aquesta instància de diaspora*. Vos mercejam de vòstra compreneson.
- Se volètz conservar vòstre compte, identificatz-vos aicí :
+ Se volètz conservar vòstre compte, identificatz-vos aicí : 
%{login_url}
- Esperam vos reveire lèu !
+ Esperam vos reveire lèu !
Lo messatgièr automatic de diaspora*
subject: "Vòstre compte diaspora* es estat senhalat coma devent èsser suprimit en rason de son inactivitat"
@@ -835,16 +841,18 @@ oc:
lo %{type} amb l'identificant %{id} es estat marcat coma ofensant.
+ Rason : %{reason}
+
[%{url}][1]
- Mercé de lo verificar tre que possible !
+ Mercé de lo verificar tre que possible !
Coralament,
Lo messatgièr automatic de diaspora*
- [1]: %{url}
+ [1] : %{url}
subject: "Un novèl %{type} es estat marcat coma ofensant"
type:
comment: "comentari"
@@ -856,7 +864,7 @@ oc:
admin: "Vòstre administrator diaspora*"
subject: "Un messatge subre vòstre compte diaspora*"
started_sharing:
- sharing: "a començat a partejar amb vos !"
+ sharing: "a començat a partejar amb vos !"
subject: "%{name} a començat a partejar amb vos sus diaspora*"
view_profile: "Veire lo perfil de %{name}"
thanks: "Mercé,"
@@ -870,13 +878,13 @@ oc:
couldnt_find_them: "Los trobatz pas ?"
looking_for: "Recercar publicacions marcadas %{tag_link}"
no_one_found: "... e pas cap trobat."
- no_results: "E ben ! Vos cal cercar quicòm."
+ no_results: "E ben ! Vos cal cercar quicòm."
results_for: "Utilizaires que correspondon a %{search_term}"
search_handle: "Utilizatz lor ID diaspora* (nomdutiliaire@pod.tld) per èsser segur de trobar vòstres amics."
searching: "Recèrca en cors, mercés d'esperar..."
- send_invite: "Pas res encara ? Mandatz-lor un convit !"
+ send_invite: "Pas res encara ? Mandatz-lor un convit !"
person:
- thats_you: "Sètz vosautres !"
+ thats_you: "Sètz vosautres !"
profile_sidebar:
bio: "Biografia"
born: "Anniversari"
@@ -884,8 +892,8 @@ oc:
location: "Localizacion"
show:
closed_account: "Aqueste compte es estat tampat"
- does_not_exist: "Aquesta persona existís pas !"
- has_not_shared_with_you_yet: "%{name} a pas encara partejar cap de publicacions amb vos !"
+ does_not_exist: "Aquesta persona existís pas !"
+ has_not_shared_with_you_yet: "%{name} a pas encara partejar cap de publicacions amb vos !"
photos:
create:
integrity_error: "Fracàs al moment de mandar l'imatge.  Sètz segur qu'èra un imatge ?"
@@ -894,7 +902,7 @@ oc:
destroy:
notice: "Fòto suprimida"
new_profile_photo:
- upload: "Mandatz una novèla fòto de perfil !"
+ upload: "Mandatz una novèla fòto de perfil !"
polls:
votes:
one: "%{count} vòte pel moment"
@@ -905,7 +913,7 @@ oc:
title: "Una publicacion de %{name}"
show:
forbidden: "Sètz pas autorizat a far aquò"
- location: "Publicat de : %{location}"
+ location: "Publicat de : %{location}"
photos_by:
one: "Una fòto per %{author}"
other: "%{author} fòtos per %{count}"
@@ -946,7 +954,7 @@ oc:
closed: "Las inscripcions son tampadas sus aqueste pod diaspora*."
create:
success: "Avètz rejunt diaspora*!"
- invalid_invite: "Lo ligam de convit donat es pas mai valid !"
+ invalid_invite: "Lo ligam de convit donat es pas mai valid !"
new:
email: "Adreça electronica"
enter_email: "Picatz vòstra adreça de corrièl"
@@ -964,7 +972,7 @@ oc:
comment_label: "<b>Comentari</b>:<br>%{data}"
confirm_deletion: "Sètz segur que volètz suprimir aqueste element ?"
delete_link: "Suprimir l'element"
- not_found: "<u>La publicacion/comentari es pas estat trobat. Sembla qu'es estat suprimit per l'utilizaire !</u>"
+ not_found: "La publicacion/comentari es pas estat trobat. Sembla qu'es estat suprimit per l'utilizaire !"
post_label: "<b>Publicacion</b>: %{title}"
reason_label: "Rason :"
reported_label: "<b>Senhalat per</b> %{person}"
@@ -1026,7 +1034,7 @@ oc:
by_email: "Convidar de monde per corrièl"
invite_your_friends: "Convidatz vòstres amics"
invites: "Convits"
- share_this: "Partejatz aqueste ligam via corrièl, blog, o malhums socials !"
+ share_this: "Partejatz aqueste ligam via corrièl, blog, o malhums socials !"
public_explain:
atom_feed: "Flux Atom"
control_your_audience: "Contrarotlatz vòstra audiéncia"
@@ -1079,7 +1087,7 @@ oc:
version: "Version"
status_messages:
new:
- mentioning: "Menciona : %{person}"
+ mentioning: "Menciona : %{person}"
too_long: "Avisatz-vos d'escriure un messatge d'estatut de %{count} caractèrs maximum. Compta actualament %{current_length} caractèrs."
stream_helper:
no_more_posts: "Avètz atent la fin d'aqueste flux."
@@ -1116,16 +1124,16 @@ oc:
public:
title: "Activitat publica"
tags:
- title: "Messatges etiquetats : %{tags}"
+ title: "Messatges etiquetats : %{tags}"
tag_followings:
manage:
- no_tags: "Seguissètz pas cap de tag."
- title: "Gerir los tags seguits."
+ no_tags: "Seguissètz pas cap d'etiquetas."
+ title: "Gerir las etiquetas"
tags:
name_too_long: "Vòstre tag deu far mens de %{count} caractèrs ( actualament, %{current_length})"
show:
follow: "Seguir #%{tag}"
- none: "L'etiqueta voida existís pas !"
+ none: "L'etiqueta voida existís pas !"
stop_following: "Quitar de seguir #%{tag}"
tagged_people:
one: "1 persona marcada amb %{tag}"
@@ -1147,16 +1155,16 @@ oc:
change: "Modificar"
change_color_theme: "Cambiar lo tèma de color"
change_email: "Cambiar de corrièl"
- change_language: "Cambiar de lenga"
+ change_language: "Cambiar la lenga"
change_password: "Cambiar lo senhal"
character_minimum_expl: "deu conténer sièis caractèrs al minim"
close_account:
- dont_go: "E, se vos plai, patiscatz pas !"
+ dont_go: "E, se vos plai, patiscatz pas !"
lock_username: "Vòstre nom d'utilizaire serà verrolhat. Poiretz pas crear un novèl compte sus aqueste pod amb lo meteis ID."
locked_out: "Seretz desconnectat e vòstre compte serà inaccessible fins a sa supression."
make_diaspora_better: "Nos agradariá fòrça que demorèssetz e nos ajudèssetz a far un melhor diaspora* puslèu que de nos daissar. Se volètz vertadièrament partir, pasmens, vaquí çò que se va passar :"
mr_wiggles: "Mossur Wiggles serà triste de vos veire partir."
- no_turning_back: "Es pas possible de tornar en arrièr ! Se sètz segur de vos, sasissètz vòstre senhal çaijós."
+ no_turning_back: "Es pas possible de tornar en arrièr ! Se sètz segur de vos, sasissètz vòstre senhal çaijós."
what_we_delete: "Suprimirem totas vòstras publicacions e informacions de perfil tre que possible. Vòstres comentaris sus la publicacion del mond desapareisseràn, mai seràn associats a vòstre ID diaspora* al lòc de vòstre nom."
close_account_text: "Tampar lo compte"
comment_on_post: "qualqu'un comenta vòstra publicacion"
@@ -1174,6 +1182,7 @@ oc:
last_exported_at: "(Darrièra mesa a jorn a %{timestamp})"
liked: "a qualqu'un li a agradat vòstra publicacion"
mentioned: "...se vos menciona dins un messatge."
+ mentioned_in_comment: "sètz mencionat dins un comentari"
new_password: "Senhal novèl"
private_message: "Avètz recebut un messatge privat."
receive_email_notifications: "Recebre una notificacion per corrièl quand :"
@@ -1191,13 +1200,13 @@ oc:
your_email_private: "Vòstre email serà pas jamai vist per d'autres utilizaires"
your_handle: "Vòstre ID diaspora*"
getting_started:
- awesome_take_me_to_diaspora: "Òsca ! Mena-me cap a diaspora*"
+ awesome_take_me_to_diaspora: "Òsca ! Mena-me cap a diaspora*"
community_welcome: "La comunautat diaspora* es contenta de vos aver a bòrd."
connect_to_facebook: "Podèm accelerar un pauc las causas de %{link} sus diaspora*. Aquò botarà vòstre nom e foto, e activar la publicacion multiplataforma."
connect_to_facebook_link: "Connexion amb vòtre compte Facebook en cors"
- hashtag_explanation: "Las etiquetas vos permeton de charrar e seguir vòstres interèsses. Son tanben una bona manièra de trobar de mond novèl sus diaspora*."
+ hashtag_explanation: "Las etiquetas vos permeton de charrar e seguir vòstres interèsses. Son tanben una bona manièra de trobar de mond novèl sus diaspora*."
hashtag_suggestions: "Ensajatz etiquetas coma aquestas #art #filmes #gif, etc."
- well_hello_there: "E ben, adiu monde !"
+ well_hello_there: "E ben, adiu monde !"
what_are_you_in_to: "Qué vos interèssa ?"
who_are_you: "Qual sètz ?"
privacy_settings:
@@ -1207,7 +1216,7 @@ oc:
strip_exif: "Levar dels imatges mandats las metadonadas talas coma luòc de presa, autor o modèl d'aparelh fòto (recomandat)"
title: "Reglatges de confidencialitat"
public:
- does_not_exist: "L'utilizaire %{username} existís pas !"
+ does_not_exist: "L’utilizaire %{username} existís pas !"
update:
color_theme_changed: "Tèma de color cambiat."
color_theme_not_changed: "Una error s'es produita pendent lo cambiament de tèma de color."
diff --git a/config/locales/diaspora/pl.yml b/config/locales/diaspora/pl.yml
index 10dadedea..e32d4f0aa 100644
--- a/config/locales/diaspora/pl.yml
+++ b/config/locales/diaspora/pl.yml
@@ -46,7 +46,7 @@ pl:
taken: "jest już zajęta."
admins:
admin_bar:
- dashboard: "Deska rozdzielcza"
+ dashboard: "Panel"
pages: "Strony"
pod_network: "Sieć poda"
pod_stats: "Statystyki Poda"
@@ -55,7 +55,7 @@ pl:
user_search: "Wyszukiwanie użytkowników"
weekly_user_stats: "Tygodniowe statystyki użytkowników"
dashboard:
- fetching_diaspora_version: "Ustalanie najnowszej wersji diaspory*"
+ fetching_diaspora_version: "Ustalanie najnowszej wersji diaspory*..."
pod_status: "Stan poda"
pods:
pod_desktop_link: "pełna wersja strony"
@@ -63,16 +63,16 @@ pl:
pod_network: "Sieć poda"
stats:
2weeks: "2 tygodnie"
- 50_most: "50 najpopularniejszych znaczników"
+ 50_most: "50 najpopularniejszych tagów"
comments:
few: "%{count} komentarze"
many: "%{count} komentarzy"
one: "%{count} komentarz"
other: "%{count} komentarzy"
zero: "Brak komentarzy"
- current_segment: "Obecny segment ma średnio <b>%{post_yest}</b> wpisów na użytkownika, z <b>%{post_day}</b>."
+ current_segment: "Obecny segment ma średnio %{post_yest} wpisów na użytkownika, z %{post_day}."
daily: "Dziennie"
- display_results: "Wyświetlanie wyników z segmentu <b>%{segment}</b>"
+ display_results: "Wyświetlanie wyników z segmentu %{segment}"
go: "Idź"
month: "Miesiąc"
posts:
@@ -87,7 +87,7 @@ pl:
one: "%{count} udostępnienie"
other: "%{count} udostępnień"
zero: "Nie udostępniono"
- tag_name: "Nazwa znacznika: <b>%{name_tag}</b> Licznik: <b>%{count_tag}</b>"
+ tag_name: "Nazwa tagu: %{name_tag} Licznik: %{count_tag}"
usage_statistic: "Statystyki"
users:
few: "%{count} użytkowników"
@@ -98,10 +98,11 @@ pl:
week: "Tydzień"
user_entry:
account_closed: "konto zamknięte"
- diaspora_handle: "Identyfikator Diaspory"
+ diaspora_handle: "identyfikator w diasporze*"
email: "Email"
guid: "GUID"
id: "ID"
+ invite_token: "Token zaproszenia"
last_seen: "ostatnio widziany"
? "no"
: nie
@@ -119,6 +120,7 @@ pl:
are_you_sure_unlock_account: "Na pewno odblokować to konto?"
close_account: "zamknij konto"
email_to: "Zaproś przez e-mail"
+ invite: "Zaproś"
lock_account: "Zablokuj konto"
under_13: "Wyświetl użytkowników młodszych niż 13 lat."
unlock_account: "Odblokuj konto"
@@ -197,7 +199,7 @@ pl:
aspect_stream:
make_something: "Zrób coś"
stay_updated: "Bądź na bieżąco"
- stay_updated_explanation: "Główny strumień jest wypełniony przez wszystkie Twoje kontakty, znaczniki które obserwujesz i wpisy niektórych bardziej kreatywnych członków społeczności."
+ stay_updated_explanation: "Główny strumień jest wypełniony przez wszystkie Twoje kontakty, tagi które obserwujesz i wpisy niektórych bardziej kreatywnych członków społeczności."
destroy:
failure: "%{name} nie mógł być usunięty."
success: "%{name} został usunięty."
@@ -229,21 +231,21 @@ pl:
tag_question: "pytanie"
tutorial_link_text: "Samouczki"
tutorials_and_wiki: "%{faq}, %{tutorial} i %{wiki}: Pomoc w Twoich pierwszych krokach."
- introduce_yourself: "Oto Twoj strumień. Wskocz do niego i przedstaw się."
+ introduce_yourself: "Oto Twoj strumień. Wskakuj i przedstaw się."
keep_pod_running: "Aby %{pod} działał szybko podaruj serwerom dawkę kofeiny w postaci miesięcznej darowizny!"
new_here:
- follow: "Obserwuj %{link} i powitaj nowych użytkowników diaspory*!"
+ follow: "Obserwuj %{link} i witaj nowych użytkowników diaspory*!"
learn_more: "Dowiedz się więcej"
title: "Powitaj nowych użytkowników"
services:
- content: "Z siecią Diaspora* można połączyć następujące usługi:"
- heading: "Podłącz usługi"
- welcome_to_diaspora: "Witaj w Diasporze, %{name}!"
+ content: "Z siecią diaspora* można połączyć następujące usługi:"
+ heading: "Połącz usługi"
+ welcome_to_diaspora: "Witaj na diasporze*, %{name}!"
no_contacts_message:
community_spotlight: "w centrum uwagi"
- invite_link_text: "Zaproś"
+ invite_link_text: "zaproś"
or_spotlight: "Lub możesz udostępnić z %{link}"
- try_adding_some_more_contacts: "Możesz wyszukać lub zaprosić więcej osób."
+ try_adding_some_more_contacts: "Wyszukaj lub %{invite_link} więcej osób."
you_should_add_some_more_contacts: "Dodaj więcej kontaktów!"
seed:
acquaintances: "Dalsi znajomi"
@@ -258,12 +260,12 @@ pl:
failure: "Nie mogę zignorować tego użytkownika. #unikanie"
success: "Dobra, ten użytkownik nie pojawi się ponownie w Twoim strumieniu. #silencio!"
destroy:
- failure: "Nie mogę przestać ignorować tego użytkownika. #unikanie"
+ failure: "Nie mogę przestać ignorować tego użytkownika. #unikanie"
success: "Zobaczmy co mają do powiedzenia! #powiedzcześć"
bookmarklet:
explanation: "Publikuj w diasporze* z dowolnego miejsca poprzez dodanie tego linku do zakładek => %{link}"
heading: "Bookmarklet"
- post_something: "Opublikuj w Diasporze"
+ post_something: "Opublikuj na diasporze*"
cancel: "Anuluj"
comments:
create:
@@ -329,18 +331,18 @@ pl:
correct_the_following_errors_and_try_again: "Popraw poniższe błędy i spróbuj ponownie."
need_javascript: "Strona do poprawnego działania wymaga obsługi JavaScriptu. Jeśli ją wyłączyłeś, proszę byś ją włączył i odświeżył stronę."
fill_me_out: "Wypełnij mnie"
- find_people: "Znajdź osoby lub #znaczniki"
+ find_people: "Znajdź osoby lub #tagi"
help:
account_and_data_management:
close_account_a: "Przejdź na dół strony z Twoimi ustawieniami i kliknij przycisk Zamknij Konto. Będziesz potrzebować hasła aby zakończyć proces. Pamiętaj jednak, że jeżeli zamkniesz konto, <strong>nigdy</strong> nie będziesz w stanie utworzyć ponownie konta o tej samej nazwie."
close_account_q: "Jak usunę moje konto?"
- data_other_podmins_a: "Od momentu kiedy zaczniesz udostępniać komuś na innym podzie, wszystkie Twoje wpisy, a także Twój profil są zapisane (jako tzw. cache) na jego podzie, i dostępne dla jego administratora. Jeśli skasujesz wpis lub dane ze swojego profilu, są one kasowane na Twoim podzie i żądanie skasowania jest wysyłane do wszystkich podów na których były przechowywane. Zdjęcia są zawsze przechowywane tylko na twoim podzie i tylko łącza do nich są przesyłane do innych podów."
+ data_other_podmins_a: "Od momentu kiedy zaczniesz udostępniać komuś na innym podzie, wszystkie Twoje wpisy, a także Twój profil są zapisane (jako tzw. cache) na jego podzie, i dostępne dla jego administratora. Jeśli skasujesz wpis lub dane ze swojego profilu, są one kasowane na Twoim podzie i żądanie skasowania jest wysyłane do wszystkich podów na których były przechowywane. Zdjęcia są zawsze przechowywane tylko na Twoim podzie i tylko łącza do nich są przesyłane do innych podów."
data_other_podmins_q: "Czy administrator innego poda może zobaczyć moje dane?"
data_visible_to_podmin_a: "Komunikacja między podami jest zawsze szyfrowana (przy użyciu SSL/TLS i własnego szyfrowania diaspory*), ale dane przechowywane na podzie nie są zaszyfrowane. Administrator poda (zwykle jego właściciel) jeśli zechce, ma dostęp do danych Twojego profilu i wszystkiego co udostępniasz. Nie odbiega to od standardowej sytuacji w innych serwisach przechowujących dane użytkowników. Posiadanie własnego poda zwiększa poziom prywatności, ponieważ wtedy sam kontrolujesz dostęp do bazy danych."
data_visible_to_podmin_q: "Ile z moich danych może zobaczyć administrator poda, na którym jestem zarejestrowan@{f:a|m:y|n:y/a}?"
- download_data_a: "Tak. Na dole działu Konto na stronie z Twoimi ustawieniami znajdują się dwa przyciski służące do pobierania danych - jeden dla danych jeden dla zdjęć."
+ download_data_a: "Tak. Na dole karty Konto na stronie z Twoimi ustawieniami znajdują się dwa przyciski służące do pobierania danych – jeden dla danych i jeden dla zdjęć."
download_data_q: "Czy mogę pobrać kopię wszystkich danych z mojego konta?"
- move_pods_a: "W przyszłości będzie można wyeksportować konto z poda i zaimportować je na innym, ale tymczasowo jest to niemożliwe. Zawsze jednak możesz założyć nowe konto, dodać swoje kontakty do jego aspektów i poprosić znajomych żeby dodali do swoich aspektów twoje nowe konto."
+ move_pods_a: "Wersja 0.7.0.0 diaspory* pozwala już na częściową migrację konta: w sekcji \"Konto\" w ustawieniach możesz wyeksportować wszystkie swoje dane. Trzymaj je w bezpiecznym miejscu! W przyszłym wydaniu diaspory* będziesz mógł dokonać pełnej migracji do innego poda, włącznie ze wszystkimi wpisami i kontaktami."
move_pods_q: "Jak przenieść konto z jednego poda na drugi?"
title: "Zarządzanie kontem i danymi"
aspects:
@@ -379,12 +381,12 @@ pl:
get_support_a_hashtag: "Zapytaj o diasporę* w publicznym wpisie używając tagu %{question}"
get_support_a_irc: "Dołącz do nas na %{irc} w rozmowie na żywo"
get_support_a_tutorials: "Sprawdć nasze %{tutorials}"
- get_support_a_website: "Odwiedź naszą %{link}"
+ get_support_a_website: "Odwiedź następującą witrynę: %{link}"
get_support_a_wiki: "Przeszukaj %{link}"
get_support_q: "Co zrobić jeśli nie znajduję odpowiedzi w tym FAQ? Gdzie jeszcze mogę znaleźć wsparcie?"
getting_started_a: "Masz szczęście. Wypróbuj %{tutorial_series} na stronie naszego projektu. Poprowadzą Cię, krok po kroku, przez proces rejestracji i nauczą wszystkich podstaw poruszanie się po diasporze*."
getting_started_q: "Pomocy! Potrzebuję podstawowych rad na początek."
- title: "Uzyskaj pomoc."
+ title: "Uzyskaj pomoc"
getting_started_tutorial: "Serię samouczków \"Pierwsze kroki\""
here: "tutaj"
irc: "IRC"
@@ -404,7 +406,6 @@ pl:
mentions:
how_to_mention_a: "Wprowadź znak \"@\", a po nim zacznij wpisywać imię osoby. Pojawi się menu, które pozwoli Ci wybrać tą osobę. Pamiętaj, że w ten sposób wspomnisz tylko o osobach, które dodałeś do któregoś z aspektów."
how_to_mention_q: "Jak wspomnieć o kimś we wpisie?"
- mention_in_comment_a: "Aktualnie nie."
mention_in_comment_q: "Czy mogę wspomnieć o kimś w komentarzu?"
see_mentions_a: "Tak, kliknij \"Wzmianki\" po lewej stronie Twojej strony głównej."
see_mentions_q: "Czy mogę jakoś zobaczyć wpisy, w których zostałem wspomniany?"
@@ -428,26 +429,22 @@ pl:
use_search_box_a: "Jeśli znasz jej pełen identyfikator (typu nazwauzytkownika@jakispod.org), znajdziesz ją wpisując w pole ten identyfikator. Jeśli jesteście na tym samym podzie, możesz wyszukiwać po samej nazwie użytkownika. Można też spróbować wyszukiwać według nazwy ekranowej (np. imię i nazwisko). Jeśli wyszukiwanie nie uda się za pierwszym razem, spróbuj ponownie."
use_search_box_q: "Jak korzystać z pola wyszukiwania, żeby znaleźć konkretną osobę?"
what_is_a_pod_a: "Pod to serwer, na którym uruchomiona jest aplikacja diaspory*, połączony z siecią diaspora*. \"Pod\" z angielskiego to miejsce w roślinie, w którym znajdują się nasiona. Istnieje wiele podów w sieci. Możesz mieć znajomych na innych podach i komunikować się z nimi. diaspora* jest pod tym względem podobna do systemu e-mailowego. Istnieją pody publiczne, pody prywatne a niewielkim nakładem pracy możesz nawet założyć własny pod."
- what_is_a_pod_q: "Czym jest \"pod\"?"
+ what_is_a_pod_q: "Czym jest pod?"
posts_and_posting:
- char_limit_services_a: "W takim przypadku twój wpis jest ograniczony do niższego limitu znaków (140 dla Twittera; 1000 dla Tumblr'a), a ilość znaków jaka została ci do wykorzystania jest pokazana kiedy ikona połączonego serwisu jest podświetlona. Wpis możesz nadal wysłać do połączonego serwisu jeśli jest dłuższy niż limit znaków, ale będzie tam dostępny w obciętej formie z odnośnikiem do postu na diasporze*."
+ char_limit_services_a: "W takim przypadku twój wpis jest ograniczony do niższego limitu znaków (140 dla Twittera; 1000 dla Tumblr'a), a ilość znaków jaka została Ci do wykorzystania jest pokazana kiedy ikona połączonego serwisu jest podświetlona. Wpis możesz nadal wysłać do połączonego serwisu jeśli jest dłuższy niż limit znaków, ale będzie tam dostępny w obciętej formie z odnośnikiem do postu na diasporze*."
char_limit_services_q: "Jaki jest limit znaków dla wpisów dodawanych przez połączone serwisy z mniejszym limitem znaków?"
character_limit_a: "65 535 znaków. To o 65 395 więcej niż jest dostępne na Twitterze! ;)"
character_limit_q: "Jaki jest limit znaków dla wpisu?"
- embed_multimedia_a: "Zazwyczaj możesz po prostu wkleić URL (np. http://www.youtube.com/watch?v=nnnnnnnnnnn ) do swojego wpisu, a wideo lub muzyka zostanie w niego automatycznie włączona. Niektóre wspierane strony to: YouTube, Vimeo, SoundCloud, Flickr i kilka innych. diaspora* używa oEmbed do udostępnienia tej funkcjonalności. Nieustannie dodajemy wsparcie dla nowych stron. Pamiętaj aby zawsze wklejać proste, pełne odnośniki: nie skracaj linków; nie dodawaj żadnych operatorów po bazowym URLu. Po dodaniu wpisu musisz chwilę poczekać aż podgląd będzie dostępny."
+ embed_multimedia_a: "Zazwyczaj możesz po prostu wkleić URL (np. http://www.youtube.com/watch?v=nnnnnnnnnnn ) do swojego wpisu, a wideo lub muzyka zostanie w niego automatycznie włączona. Niektóre wspierane strony to: YouTube, Vimeo, SoundCloud, Flickr i kilka innych. diaspora* używa oEmbed do udostępnienia tej funkcji. Nieustannie dodajemy wsparcie dla nowych stron. Pamiętaj aby zawsze wklejać proste, pełne odnośniki: nie skracaj linków; nie dodawaj żadnych operatorów po bazowym URL-u. Po dodaniu wpisu musisz chwilę poczekać aż podgląd będzie dostępny."
embed_multimedia_q: "Jak mogę osadzić wideo, audio lub inną treść mutltimedialną we wpisie?"
- format_text_a: "Używając uproszczonego systemu nazywanego %{markdown}. Pełną składnię Markdown możesz znaleźć %{here}. Przycisk podglądu jest tutaj bardzo przydatny - możesz dzięki niemu sprawdzić jak będzie wyglądać twój wpis zanim go udostępnisz."
+ format_text_a: "diaspora* używa prostego systemu zwanego %{markdown}. Edytor posiada przyciski ułatwiające formatowanie tekstu. Jeśli chcesz robić to ręcznie, więcej informacji na temat Markdown znajdziesz %{here}. Dzięki karcie Podglądu możesz jeszcze przed wysłaniem zobaczyć jak wiadomość będzie wyglądała. Miej na uwadze, że nie ma możliwości edytowania wpisów, więc staraj się by wszystko wyglądało perfekcyjnie zanim Udostępnisz wpis."
format_text_q: "Jak mogę formatować tekst w moich wpisach (pogrubiać go, dodać kursywę itp.)?"
hide_posts_a: "Jeśli nakierujesz kursor na górę wpisu, po prawej stronie pojawi się X. Kliknij go aby ukryć ten wpis i wyciszyć powiadomienia dotyczące go. Wciąż będziesz mógł zobaczyć ten wpis jeśli przejdziesz na stronę profilową osoby, która go udostępniła."
hide_posts_q: "Jak ukryć wpis? / Jak wyłączyć powiadomienia na temat wpisu skomentowanego przeze mnie?"
- image_text: "tekst obrazka"
- image_url: "adres url obrazka"
insert_images_a: "Kliknij ikonę aparatu aby dodać zdjęcie do wpisu. Kliknij ikonę jeszcze raz aby dodać kolejne zdjęcie, lub zaznacz kilka plików aby dodać je jednocześnie."
- insert_images_comments_a1: "Nie możesz dodać obrazów do komentarzy, ale możesz użyć poniższy kod Markdown aby dodać już istniejące obrazy z dowolnego miejsca w Sieci:"
- insert_images_comments_a2: "może być użyty do wstawiania obrazków z Internetu w komentarzach i wpisach."
insert_images_comments_q: "Czy mogę do komentarzy dodać zdięcia?"
insert_images_q: "Jak mogę dodać do wpisów zdięcia?"
- post_location_a: "Kliknij ikonę szpilki obok ikony aparatu. To doda twoją lokalizację z OpenStreetMap. Możesz też edytować tą lokalizację – na przykład możesz ograniczyć precyzję lokalizacji tylko do miasta, nie konkretnej ulicy."
+ post_location_a: "Kliknij ikonę szpilki obok ikony aparatu. To doda Twoją lokalizację z OpenStreetMap. Możesz też edytować tę lokalizację – na przykład możesz ograniczyć precyzję lokalizacji tylko do miasta, nie konkretnej ulicy."
post_location_q: "Jak dodać lokalizację do wpisu?"
post_notification_a: "Koło X w prawym górnym rogu wpisu znajdziesz ikonę dzwonka. Kliknij ją aby włączyć bądź wyłączyć powiadomienia."
post_notification_q: "Jak włączyć albo wyłączyć powiadomienia o wpisie?"
@@ -459,8 +456,8 @@ pl:
size_of_images_q: "Czy mogę dostosować wymiary obrazków we wpisach lub komentarzach?"
stream_full_of_posts_a1: "Twój strumień składa się z trzech rodzajów wpisów:"
stream_full_of_posts_li1: "Wpisów od ludzi, z którymi się dzielisz, które występują w dwóch odmianach: publicznych i ograniczonych (udostępnionych jedynie poszczególnym aspektom). Aby usunąć te wpisy ze swojego strumienia wystarczy przestać dzielić się z daną osobą."
- stream_full_of_posts_li2: "Wpisy publiczne zawierające jeden z tagów, które obserwujesz. Aby usunąć je przestać obserwować dany tag."
- stream_full_of_posts_li3: "Publiczne wpisy ludzi znajdujących się w centrum uwagi. Te wpisy mogą być usunięte przez odznaczenie opcji \"Pokaż centrum uwagi w strumieniu\" w zakładce Konto w twoich Ustawieniach."
+ stream_full_of_posts_li2: "Wpisy publiczne zawierające jeden z tagów, które obserwujesz. Aby usunąć je przestań obserwować dany tag."
+ stream_full_of_posts_li3: "Publiczne wpisy ludzi znajdujących się w centrum uwagi. Te wpisy mogą być usunięte przez odznaczenie opcji \"Pokaż centrum uwagi w strumieniu\" w zakładce Konto w Twoich Ustawieniach."
stream_full_of_posts_q: "Dlaczego mój strumień jest pełen wpisów od ludzi, których nie znam i z którymi się nie dzielę?"
title: "Wpisy i udostępnianie"
private_posts:
@@ -473,40 +470,27 @@ pl:
title: "Wpisy prywatne"
who_sees_post_a: "Jedynie zalogowani użytkownicy diaspory*, którzy znajdowali się w tym aspekcie podczas udostępnienia prywatnego wpisu mogą go zobaczyć."
who_sees_post_q: "Kiedy udostępniam wpis w ramach określonego aspektu (t.j. udostępniam wpis prywatny) kto może go zobaczyć?"
- private_profiles:
- title: "Profile prywatne"
- whats_in_profile_a: "Biografia, lokalizacja, płeć i data urodzin. To co znajduje się w dolnej części edytora profilu. Każda z tych informacji jest opcjonalna – to czy je wypełnisz zalezy wyłącznie od ciebie. Zalogowani użytkownicy, których dodałeś do swoich aspektów są jedynymi ludźmi, którzy mają dostęp do tych informacji. Widzą oni również twoje prywatne wpisy udostępnione w aspektach, w których się znajdują podczas przeglądania twojego profilu."
- whats_in_profile_q: "Co znajduje się w moim prywatnym profilu?"
- who_sees_profile_a: "Każdy zalogowany użytkownik, z którym się dzielisz (t.j. znajdujący się w jednym z twoich aspektów). Ludzie, którzy cię obserwują, ale których ty nie obserwujesz mogą zobaczyć jedynie twoje publicznie dostępne informacje."
- who_sees_profile_q: "Kto może zobaczyć mój prywatny profil?"
- who_sees_updates_a: "Każdy kto znajduje się w twoich aspektach widzi zmiany w twoim profilu. "
- who_sees_updates_q: "Kto widzi aktualizacje w moim prywatnym profilu?"
+ profile:
+ title: "Profil"
+ what_do_tags_do_q: "Do czego służą tagi w moim profilu podstawowym?"
+ whats_in_profile_q: "Co znajduje się w moim profilu?"
+ who_sees_profile_q: "Kto widzi mój profil?"
public_posts:
- can_comment_reshare_like_a: "Każdy zalogowany użytkownik diaspory* może komentować, przekazywać i lubić twoje publiczne wpisy."
+ can_comment_reshare_like_a: "Każdy zalogowany użytkownik diaspory* może komentować, przekazywać i lubić Twoje publiczne wpisy. Jedynym wyjątkiem są osoby które ignorujesz: nie mogą one lubić ani komentować Twoich wpisów."
can_comment_reshare_like_q: "Kto może komentować, przekazać i polubić mój publiczny wpis?"
- deselect_aspect_posting_a: "Odznaczenie aspektów nie wpływa na publiczne wpisy. W dalszym ciągu będą one widoczne w strumieniach wszystkich twoich kontaktów. Aby udostępnić wpis jedynie wybranym aspektom musisz wybrać te aspekty korzystając z przycisku pod polem udostępniania."
+ deselect_aspect_posting_a: "Odznaczenie aspektów nie wpływa na publiczne wpisy. W dalszym ciągu będą one widoczne w strumieniach wszystkich Twoich kontaktów. Aby udostępnić wpis jedynie wybranym aspektom musisz wybrać te aspekty korzystając z przycisku pod polem udostępniania."
deselect_aspect_posting_q: "Co się dzieje jeśli odznaczę jeden lub więcej aspektów kiedy udostępniam publiczny wpis?"
- find_public_post_a: "Twoje publiczne wpisy pojawią się w strumieniu każdego kto cię obserwuje. Jeśli dodasz #tag do swojego publicznego wpisu, każdy kto obserwuje ten tag również znajdzie twój wpis w swoim strumieniu. Każdy wpis ma również unikalny URL, który każdy może zobaczyć nawet jeśli nie jest zalogowany - w ten sposób do wpisów można się odnosić bezpośrednio z Twittera, blogów itp. Publiczne wpisy mogą być również indeksowane przez wyszukiwarki."
+ find_public_post_a: "Twoje publiczne wpisy pojawią się w strumieniu każdego kto Cię obserwuje. Jeśli dodasz #tag do swojego publicznego wpisu, każdy kto obserwuje ten tag również znajdzie Twój wpis w swoim strumieniu. Każdy wpis ma również unikalny URL, który każdy może zobaczyć nawet jeśli nie jest zalogowany – w ten sposób do wpisów można się odnosić bezpośrednio z Twittera, blogów itp. Publiczne wpisy mogą być również indeksowane przez wyszukiwarki."
find_public_post_q: "Jak inni ludzie mogą znaleźć mój publiczny wpis?"
- see_comment_reshare_like_a: "Każdy zalogowany użytkownik diaspory* i każdy użytkownik Internetu. Komentarze, przekazania i polubienia publicznych wpisów są także publiczne."
+ see_comment_reshare_like_a: "Każdy zalogowany użytkownik diaspory* i każdy użytkownik Internetu może zobaczyć Twoją aktywność w publicznych wpisach. Komentarze, przekazania i polubienia publicznych wpisów są publiczne."
see_comment_reshare_like_q: "Kiedy komentuję, przekazuję lub lubię publiczny wpis, kto może to zobaczyć?"
title: "Wpisy publiczne"
- who_sees_post_a: "Każdy użytkownik Internetu może zobaczyć twój publiczny wpis więc zawsze zastanów się czy chcesz udostępnić go publicznie. Jest to jednak świetny sposób na to żeby dać się poznać."
+ who_sees_post_a: "Każdy użytkownik Internetu może zobaczyć Twój publiczny wpis, więc zawsze zastanów się czy chcesz udostępnić go publicznie. Jest to jednak świetny sposób na to żeby dać się poznać."
who_sees_post_q: "Kiedy udostępniam wpis publiczny, kto może go zobaczyć?"
- public_profiles:
- title: "Profile publiczne"
- what_do_tags_do_a: "Pozwalają one ludziom zorientować się kim jesteś. Twoje zdjęcie pojawi się również z lewej strony stron tych konkretnych tagów, wraz ze zdjęciami innych ludzi, którzy dodali je do swoich publicznych profili."
- what_do_tags_do_q: "O co chodzi z tagami w moim publicznym profilu?"
- whats_in_profile_a: "W publicznym profilu znajduje się Twoje imię, pięć tagów jakimi się opisałeś i zdjęcie. Te rzeczy znajdują się w górnej sekcji edytora profilu. Możesz tu podać informacje, które pozwolą na identyfikację ciebie lub takie, które pozwolą ci zachować anonimowość. Twój publiczny profil zawiera również wszystkie twoje publiczne wpisy."
- whats_in_profile_q: "Co znajduje się w moim publicznym profilu?"
- who_sees_profile_a: "Każdy zalogowany użytkownik diaspory* jak również każdy użytkownik Internetu. Każdy profil ma swój bezpośredni URL więc mogą się do niego odnosić zewnętrzne strony. Może on być również indeksowany przez wyszukiwarki."
- who_sees_profile_q: "Kto widzi mój publiczny profil?"
- who_sees_updates_a: "Każdy może zobaczyć zmiany w twoim publicznym profilu jeśli odwiedzi twoją stronę profilową."
- who_sees_updates_q: "Kto widzi aktualizacje mojego publicznego profilu?"
resharing_posts:
reshare_private_post_aspects_a: "Nie. Przekazywanie ograniczonych wpisów nie jest możliwe. Jest to środek mający służyć respektowaniu intencji oryginalnego udostępniającego, który podzielił się nim jedynie z wybraną grupą ludzi."
reshare_private_post_aspects_q: "Czy mogę przekazać prywatny wpis jedynie wybranym aspektom?"
- reshare_public_post_aspects_a: "Nie. Kiedy przekazujesz publiczny wpis automatycznie staje się on jednym z twoich publicznych wpisów. Aby przekazać go jedynie wybranym aspektom skopiuj jego zawartość i udostępnij jako nowy wpis."
+ reshare_public_post_aspects_a: "Nie. Kiedy przekazujesz publiczny wpis automatycznie staje się on jednym z Twoich publicznych wpisów. Aby przekazać go jedynie wybranym aspektom skopiuj jego zawartość i udostępnij jako nowy wpis."
reshare_public_post_aspects_q: "Czy mogę przekazać publiczny wpis jedynie określonym aspektom?"
title: "Przekazywanie wpisów"
sharing:
@@ -521,26 +505,26 @@ pl:
add_to_aspect_li7: "Ania pojawi się w kategorii \"Jedynie mi udostępniają\" na stronie z kontaktami Bartka."
add_to_aspect_li8: "Amy będzie także mogła @wspomnieć Bena w wpisie."
add_to_aspect_q: "Co się dzieje kiedy dodaję kogoś do jednego z moich aspektów? Lub kiedy ktoś dodaje mnie do swoich aspektów?"
- list_not_sharing_a: "Nie, ale możesz sprawdzić czy ktoś ci udostępnia odwiedzając jego stronę profilową. Jeśli dana osoba ci udostępnia, pasek pod jej zdjęciem będzie zielony, a jeśli nie - będzie on szary."
+ list_not_sharing_a: "Nie, ale możesz sprawdzić czy ktoś Ci udostępnia odwiedzając jego stronę profilową. Jeśli dana osoba Ci udostępnia, obok jej ID będzie się znajdować zielony ptaszek. Jeśli nie, szary okrąg."
list_not_sharing_q: "Czy jest dostępna lista osób, które dodałem do moich aspektów, ale które nie udostępniają mi?"
- only_sharing_a: "Są to ludzie, którzy dodali cię do swoich aspektów, ale których ty (jeszcze) nie dodałeś do żadnego ze swoich aspektów. Innymi słowy, ci, którzy udostępniają tobie, ale którym nie udostępniasz ty (zgodnie z udostępnianiem asymetrycznym). Jeśli dodasz kogoś z tej listy do jakiegoś swojego aspektu zniknie on z tej kategorii, a pojawi się w danym aspekcie. Sprawdź powyżej."
+ only_sharing_a: "Są to ludzie, którzy dodali cię do swoich aspektów, ale których Ty (jeszcze) nie dodałeś do żadnego ze swoich aspektów. Innymi słowy, ci, którzy udostępniają Tobie, ale którym nie udostępniasz Ty (zgodnie z udostępnianiem asymetrycznym). Jeśli dodasz kogoś z tej listy do jakiegoś swojego aspektu zniknie on z tej kategorii, a pojawi się w danym aspekcie. Sprawdź powyżej."
only_sharing_q: "Kim są ludzie pokazani w kategorii \"Jedynie mi udostępniają\" na mojej stronie z kontaktami?"
- see_old_posts_a: "Nie. Ta osoba będzie widziała jedynie nowe wpisy udostępniane w tym aspekcie. Ta osoba (i wszyscy inni) może zobaczyć twoje stare publiczne wpisy na twojej stronie profilowej."
+ see_old_posts_a: "Nie. Ta osoba będzie widziała jedynie nowe wpisy udostępniane w tym aspekcie. Ta osoba (i wszyscy inni) może zobaczyć Twoje stare publiczne wpisy na Twojej stronie profilowej."
see_old_posts_q: "Jeśli dodam kogoś do aspektu czy może on zobaczyć wpisy, które udostępniłem w tym aspekcie zanim zacząłem mu udostępniać?"
sharing_notification_a: "Otrzymasz powiadomienia za każdym razem gdy ktoś zacznie udostępniać wpisy tobie."
sharing_notification_q: "Kiedy dowiem się gdy ktoś zacznie udostępniać mi wpisy?"
title: "Udostępnianie"
tags:
- filter_tags_a: "Ta funkcjonalność nie jest jeszcze dostępna bezpośrednio w diasporze*, ale istnieją pewne %{third_party_tools} które mogą ją zapewnić."
+ filter_tags_a: "Ta funkcja nie jest jeszcze dostępna bezpośrednio w diasporze*, ale istnieją pewne %{third_party_tools} które mogą ją zapewnić."
filter_tags_q: "Czy mogę filtrować/wyrzucić określone tagi z mojego strumienia?"
- followed_tags_a: "Po wyszukaniu tagu kliknij w przycisk na szczycie strony aby zacząć \"obserwować\" dany tag. Pojawi się on wtedy na twojej liście obserwowanych tagów po lewej stronie. Kliknięcie na jeden z obserwowanych tagów przeniesie cię na stronę danego tagu, gdzie możesz zobaczyć najnowsze wpisy, które go zawierają. Kliknij na #Obserwowane Tagi aby zobaczyć strumień wpisów zawierających jeden tagów, które obserwujesz. "
+ followed_tags_a: "Po wyszukaniu tagu kliknij w przycisk na szczycie strony aby zacząć \"obserwować\" dany tag. Pojawi się on wtedy na Twojej liście obserwowanych tagów po lewej stronie. Kliknięcie na jeden z obserwowanych tagów przeniesie Cię na stronę danego tagu, gdzie możesz zobaczyć najnowsze wpisy, które go zawierają. Kliknij na #Obserwowane Tagi aby zobaczyć strumień wpisów zawierających jeden tagów, które obserwujesz. Wpisy zawierające obserwowane tagi znajdą się także w Twoim strumieniu."
followed_tags_q: "Czym są \"#Obserwowane Tagi\" i jak mogę obserwować tag?"
people_tag_page_a: "To są ludzie, którzy wybrali ten tag aby opisać siebie w ich publicznych profilach."
people_tag_page_q: "Kim są ludzie pokazani po lewej stronie strony tagu?"
tags_in_comments_a: "Tag dodany do komentarza zostanie pokazany jako link to strony tego tagu, ale nie sprawi, że skomentowany wpis się na niej znajdzie. Grupowanie działa wyłącznie dla wpisów."
tags_in_comments_q: "Czy mogę dodawać tagi do komentarzy czy tylko do wpisów?"
title: "Tagi"
- what_are_tags_for_a: "Tagi są sposobem na grupowanie wpisów, zazwyczaj ze względu na tematykę. Wyszukiwanie konkretnego tagu pokaże ci wszystkie wpisy zawierające dany tag (zarówno prywatne jak i publiczne). Pozwala to ludziom odnaleźć publiczne wpisy dotyczące spraw, które ich interesują"
+ what_are_tags_for_a: "Tagi są sposobem na grupowanie wpisów, zazwyczaj ze względu na tematykę. Wyszukiwanie konkretnego tagu pokaże ci wszystkie wpisy zawierające dany tag (zarówno prywatne jak i publiczne). Pozwala to ludziom odnaleźć publiczne wpisy dotyczące spraw, które ich interesują."
what_are_tags_for_q: "Do czego służą tagi?"
third_party_tools: "Narzędzia innych dostawców"
title_header: "Pomoc"
@@ -560,6 +544,7 @@ pl:
contribute: "Współtwórz"
create_an_account: "Stwórz konto"
headline: "Witaj, przyjacielu."
+ make_yourself_an_admin: "Zostań administratorem"
update_your_pod: "Zaktualizuj swój pod"
invitation_codes:
already_logged_in: "%{inviter} zaprosił Cię na ten pod, ale jesteś już zalogowany."
@@ -570,7 +555,7 @@ pl:
empty: "Podaj przynajmniej jeden adres e-mail."
no_more: "Nie masz więcej zaproszeń."
note_already_sent: "Zaproszenia zostały już wysłane do: %{emails}"
- rejected: "Następujące adresy e-mail okazały się problematyczne:"
+ rejected: "Następujące adresy e-mail okazały się problematyczne: %{emails}"
sent: "Zaproszenia zostały wysłane do: %{emails}"
new:
codes_left:
@@ -580,7 +565,7 @@ pl:
other: "%{count} zaproszeń na ten kod"
zero: "Brak zaproszeń na ten kod"
comma_separated_plz: "Można wprowadzić wiele adresów e-mail oddzielonych przecinkami."
- invite_someone_to_join: "Zaproś kogoś do Diaspory!"
+ invite_someone_to_join: "Zaproś kogoś do diaspory*!"
language: "Język"
paste_link: "Udostępnij to łącze znajomym, aby zaprosić ich do Diaspory* lub wyślij je do nich przez e-mail."
send_an_invitation: "Wyślij zaproszenie"
@@ -588,6 +573,8 @@ pl:
layouts:
application:
back_to_top: "Powrót na górę"
+ be_excellent: "Bądźcie dla siebie nawzajem cudowni! ♥"
+ discourse: "Dyskusje na temat projektu i wsparcie"
powered_by: "Działa na oprogramowaniu diaspora*"
public_feed: "Publiczny kanał diaspory* użytkownika %{name}"
source_package: "Pobierz archiwum z kodem źródłowym"
@@ -649,7 +636,7 @@ pl:
reshared: "Przekazali dalej"
show_all: "pokaż wszystkie"
show_unread: "pokaż nieprzeczytane"
- started_sharing: "Zaczęli ci udostępniać"
+ started_sharing: "Zaczęli Ci udostępniać"
liked:
few: "%{actors} polubili/ły Twój wpis %{post_link}."
many: "%{actors} polubili/ły Twój wpis %{post_link}."
@@ -701,7 +688,7 @@ pl:
notifier:
a_limited_post_comment: "Pojawił się nowy komentarz w ograniczonym wpisie na diasporze*. Zapoznaj się z nim."
a_post_you_shared: "wpis."
- a_private_message: "Masz nową wiadomość w diaspora*"
+ a_private_message: "Otrzymałeś nową prywatną wiadomość na diasporze*"
also_commented:
limited_subject: "Pojawił się nowy komentarz do wpisu, który komentowałeś"
click_here: "Kliknij tutaj"
@@ -729,7 +716,7 @@ pl:
Napotkaliśmy na problem podczas przetwarzania Twoich prywatnych danych do pobrania.
Spróbuj ponownie!
- Na razie!
+ Przepraszamy,
Automat e-mailowy diaspory*.
subject: "Przykro nam, %{name}, ale wystąpił problem z Twoimi danymi"
@@ -745,26 +732,28 @@ pl:
subject: "%{name}, twoje zdjęcia są gotowe do pobrania."
export_photos_failure_email:
body: |-
- Witaj %{name}
+ Cześć %{name},
- Wystąpił problem podczas przetwarzania twoich zdjęć do pobrania.
- Proszę spróbuj ponownie!
+ Napotkaliśmy problem podczas przetwarzania Twoich zdjęć do pobrania.
+ Spróbuj ponownie!
- Przepraszam,
+ Przepraszamy,
- Emailowy robot diaspory*
+ Automat e-mailowy diaspory*.
subject: "%{name}, wystąpił problem z twoimi zdjęciami"
hello: "Cześć %{name}!"
invite:
message: |-
Cześć!
- Zaproszono Cię do diaspory*!
+ %{user} zaprosił(a) Cię do diaspory*!
Kliknij ten link, aby rozpocząć rejestrację
[%{invite_url}][1]
+ Jeżeli posiadasz już konto możesz dodać %{diaspora_id} do swoich kontaktów.
+
Z poważaniem
@@ -853,7 +842,7 @@ pl:
gender: "Płeć"
location: "Lokalizacja"
show:
- closed_account: "Te konto zostało zamknięte."
+ closed_account: "To konto zostało zamknięte."
does_not_exist: "Osoba nie istnieje!"
has_not_shared_with_you_yet: "%{name} nie udostępnia Ci jeszcze żadnych wpisów!"
photos:
@@ -865,11 +854,18 @@ pl:
notice: "Usunięto zdjęcie."
new_profile_photo:
upload: "Prześlij nowe zdjęcie profilowe!"
+ polls:
+ votes:
+ few: "jak dotąd %{count} głosy"
+ many: "jak dotąd %{count} głosów"
+ one: "jak dotąd %{count} głos"
+ other: "jak dotąd %{count} głosy"
+ zero: "jak dotąd %{count} głosów"
posts:
presenter:
title: "Wpis od %{name}"
show:
- forbidden: "Nie masz pozwolenia by to zrobić."
+ forbidden: "Nie masz pozwolenia by to zrobić"
location: "Wysłano z: %{location}"
photos_by:
few: "%{count} zdjęcia od %{author}"
@@ -882,11 +878,11 @@ pl:
profile: "Profil"
profiles:
edit:
- allow_search: "Pozwól innym użytkownikom diaspory* na wyszukanie ciebie"
+ allow_search: "Pozwól innym użytkownikom diaspory* na wyszukanie Ciebie"
basic: "Mój podstawowy profil"
basic_hint: "Wszystkie elementy Twojego profilu są opcjonalne. Twój podstawowy profil zawsze będzie publicznie dostępny."
extended: "Mój rozszerzony profil"
- extended_hint: "Użyj przełącznika by ustawić widoczność Twojego rozszerzonego profilu. Publiczna oznacza, że będzie widoczny dla każdego z internecie, ograniczona, że tylko dla osób z którymi dzielisz się na Diasporze."
+ extended_hint: "Użyj przełącznika by ustawić widoczność Twojego rozszerzonego profilu. Publiczny oznacza, że będzie widoczny dla każdego w internecie, ograniczony, że tylko dla osób z którymi dzielisz się na diasporze*."
extended_visibility_text: "Widoczność Twojego rozszerzonego profilu:"
first_name: "Imię"
last_name: "Nazwisko"
@@ -916,7 +912,7 @@ pl:
invalid_invite: "Podane łącze do zaproszenia jest nieważne!"
new:
email: "E-mail"
- enter_email: "Wpisz adres e-mail"
+ enter_email: "Wpisz Twój adres e-mail"
enter_password: "Podaj hasło (maks. 6 znaków)"
enter_password_again: "Wprowadź ponownie to samo hasło"
enter_username: "Wybierz nazwę użytkownika (możliwe litery, cyfry i podkreślniki)"
@@ -968,8 +964,8 @@ pl:
no_services_available: "Ten pod nie udostępnia żadnych usług."
not_logged_in: "Nie zalogowany."
really_disconnect: "Odłączyć %{service}?"
- services_explanation: "Podłączenie usług umożliwia jednoczesne publikowanie w nich wpisów, które udostępniasz w sieci Diaspora*."
- title: "Zarządzaj podłączonymi usługami"
+ services_explanation: "Połączenie usług umożliwia jednoczesne publikowanie w nich wpisów, które udostępniasz na diasporze*."
+ title: "Zarządzaj połączonymi usługami"
provider:
facebook: "Facebook"
tumblr: "Tumblr"
@@ -987,7 +983,7 @@ pl:
other: "W %{count} aspektach"
zero: "Dodaj kontakt"
invitations:
- by_email: "Przez e-mail"
+ by_email: "Zaproś ludzi przez e-mail"
invite_your_friends: "Zaproś swoich znajomych"
invites: "Zaproszenia"
share_this: "Udostępnij to łącze przez e-mail, na blogu lub w sieci społecznościowej!"
@@ -996,11 +992,11 @@ pl:
control_your_audience: "Dostosuj swoją publiczność"
logged_in: "Zalogowano do %{service}"
manage: "Zarządzaj powiązanymi usługami"
- new_user_welcome_message: "Używaj #znaczników, aby opisywać swoje wpisy i znajdować osoby o podobnych zainteresowaniach. Zawołaj ciekawych ludzi dzięki @wzmiankom"
+ new_user_welcome_message: "Używaj #tagów, aby opisywać swoje wpisy i znajdować osoby o podobnych zainteresowaniach. Zawołaj ciekawych ludzi dzięki @wzmiankom"
outside: "Wiadomości publiczne będą widoczne także dla użytkowników spoza diaspory*."
share: "Podziel się"
title: "Konfiguracja połączonych usług"
- visibility_dropdown: "Użyj tej listy rozwijalnej, aby zmienić widoczność swojego wpisu. (Proponujemy, aby ten pierwszy był publiczny.)"
+ visibility_dropdown: "Użyj tej listy rozwijalnej, aby zmienić widoczność swojego wpisu. (Proponujemy, aby ten pierwszy był publiczny.)"
publisher:
discard_post: "Porzuć wpis"
formatWithMarkdown: "Możesz użyć %{markdown_link} aby sformatować swój wpis"
@@ -1030,7 +1026,7 @@ pl:
active_users_halfyear: "Aktywni użytkownicy w półroczu"
active_users_monthly: "Aktywni użytkownicy miesięcznie"
closed: "Zamknięte"
- disabled: "Nie dostępne"
+ disabled: "Niedostępne"
enabled: "Dostępne"
local_comments: "Lokalne komentarze"
local_posts: "Lokalne wpisy"
@@ -1063,11 +1059,11 @@ pl:
title: "Skomentowane wpisy"
community_spotlight_stream: "W centrum uwagi społeczności"
followed_tag:
- add_a_tag: "Dodaj znacznik"
- all: "Wszystkie znaczniki"
+ add_a_tag: "Dodaj tag"
+ all: "Wszystkie tagi"
follow: "Obserwuj"
- title: "#Obserwowane znaczniki"
- followed_tags_stream: "#Obserwowane znaczniki"
+ title: "#Obserwowane tagi"
+ followed_tags_stream: "#Obserwowane tagi"
like_stream:
title: "Strumień polubionych"
liked:
@@ -1089,7 +1085,7 @@ pl:
name_too_long: "Proszę skróć nazwę taga do mniej niż %{count} znaków. Obecnie zawiera %{current_length} znaków."
show:
follow: "Obserwuj #%{tag}"
- none: "Pusty znacznik nie istnieje!"
+ none: "Pusty tag nie istnieje!"
stop_following: "Przestań obserwować #%{tag}"
tagged_people:
few: "%{count} osoby otagowane %{tag}"
@@ -1109,7 +1105,7 @@ pl:
edit:
also_commented: "...ktoś skomentuje wpis mający mój komentarz"
auto_follow_aspect: "Aspekt dla automatycznie dodanych użytkowników:"
- auto_follow_back: "Automatycznie zacznij udostępniać gdy ktoś zaczyna udostępniać mnie"
+ auto_follow_back: "Automatycznie zacznij udostępniać gdy ktoś zaczyna mi udostępniać"
change: "Zmień"
change_color_theme: "Zmień wariant kolorystyczny"
change_email: "Zmiana adresu e-mail"
@@ -1149,20 +1145,20 @@ pl:
request_export_update: "Odśwież dane mojego profilu"
reshared: "...ktoś przekazał dalej mój wpis"
show_community_spotlight: "Wyświetlić wyróżnionych użytkowników w Strumieniu?"
- show_getting_started: "Ponownie włącz - Pierwsze kroki"
+ show_getting_started: "Ponownie włącz \"pierwsze kroki\""
someone_reported: "ktoś wysłał zgłoszenie"
started_sharing: "...ktoś zaczął mi udostępniać wpisy"
stream_preferences: "Ustawienia Strumienia"
your_email: "Adres e-mail"
your_email_private: "Twój email zawsze pozostanie niewidoczny dla innych użytkowników"
- your_handle: "Twój Identyfikator Diaspory"
+ your_handle: "Twój identyfikator w diasporze*"
getting_started:
awesome_take_me_to_diaspora: "Świetnie! Zabierz mnie na diasporę*"
community_welcome: "Społeczność diaspory* cieszy się, że ​​jesteś z nami!"
connect_to_facebook: "Możemy nieco przyśpieszyć poprzez %{link} do diaspory*. To spowoduje pobranie Twojej nazwy, zdjęcia i włączy równoczesne publikowanie wpisów w obu serwisach."
connect_to_facebook_link: "Podpięcie konta na Facebooku"
- hashtag_explanation: "Znaczniki pozwalają łatwo odnaleźć interesujące Cię tematy. Są także świetnym sposobem na nawiązywanie znajomości na diasporze*."
- hashtag_suggestions: "Spróbuj obserwować znaczniki takie jak #sztuka, #filmy, #gif, itd."
+ hashtag_explanation: "Tagi pozwalają łatwo odnaleźć interesujące Cię tematy. Są także świetnym sposobem na nawiązywanie znajomości na diasporze*."
+ hashtag_suggestions: "Spróbuj obserwować tagi takie jak #sztuka, #filmy, #gif, itd."
well_hello_there: "No, witam!"
what_are_you_in_to: "Czym się interesujesz?"
who_are_you: "Kim jesteś?"
diff --git a/config/locales/diaspora/pt-BR.yml b/config/locales/diaspora/pt-BR.yml
index 947eb9e68..4a8032ead 100644
--- a/config/locales/diaspora/pt-BR.yml
+++ b/config/locales/diaspora/pt-BR.yml
@@ -274,6 +274,13 @@ pt-BR:
heading: "Favoritos"
post_something: "Publicar em diaspora*"
cancel: "Cancelar"
+ color_themes:
+ dark: "Escuro"
+ dark_green: "Verde-escuro"
+ egyptian_blue: "Azul egípcio"
+ magenta: "Magenta"
+ original: "Cinza original"
+ original_white: "Fundo branco original"
comments:
create:
error: "Falha ao comentar."
@@ -349,7 +356,7 @@ pt-BR:
data_visible_to_podmin_q: "Quanta informação minha quem administra meu servidor pode ver?"
download_data_a: "Sim. Na aba Conta da sua página de configurações, role para baixo. Você encontrará dois botões: um para baixar seus dados e outro para baixar suas fotos."
download_data_q: "Posso baixar uma cópia de todos os meus dados contidos em minha semente (conta)?"
- move_pods_a: "No futuro você será capaz de exportar sua conta de um servidor e importá-la para outro, mas no momento isto não é possível. Você sempre poderá abrir uma nova conta e adicionar seus contactos aos aspectos nessa nova conta, e pedir-lhes para adicionar a sua nova conta aos aspectos deles."
+ move_pods_a: "A versão 0.7.0.0 da diaspora* disponibiliza a primeira etapa de migração de conta: agora, você pode exportar todos os dados da seção \"Conta\" das suas configurações de usuário. Guarde seus dados em segurança! Um próximo lançamento possibilitará a migração da conta inteira, inclusive publicações e contatos, para outro pod."
move_pods_q: "Como eu movo minha semente (conta) de um servidor para outro?"
title: "Gerenciamento de conta e de dados"
aspects:
@@ -357,7 +364,7 @@ pt-BR:
change_aspect_of_post_q: "Uma vez que eu publiquei alguma coisa, posso mudar o(s) aspecto(s) que pode(m) ver isto?"
contacts_know_aspect_a: "Não. Eles não podem ver o nome do aspecto em nenhuma circunstância."
contacts_know_aspect_q: "Meus contactos sabem em que aspectos eu os coloquei?"
- contacts_visible_a: "Se você marcar esta opção, então os contatos incluídos no aspecto vão poder ver uns aos outros na sua página de perfil, na aba \"Contatos\". É melhor marcar esta opção somente se todos os contatos no aspecto se conhecerem – por exemplo, se o aspecto reunir as pessoas de um clube ou sociedade à qual você pertence. O nome do aspecto vai continuar invisível para eles."
+ contacts_visible_a: "Se você marcar esta opção, os contatos incluídos no aspecto vão poder ver uns aos outros na sua página de perfil, na aba \"Contatos\". (No momento, a aba \"Contatos\" está visível apenas para os contatos que estão no mesmo pod que você.) É melhor marcar esta opção somente se todos os contatos no aspecto se conhecerem – por exemplo, se o aspecto tiver sido criado para reunir membros de um clube ou sociedade à qual você pertence. O nome do aspecto vai continuar invisível para eles."
contacts_visible_q: "O que significa \"tornar contatos desse aspecto visíveis entre si\"?"
delete_aspect_a: "Na página inicial, clique em \"Meus aspectos\", na barra lateral, e clique no ícone de lápis ao lado do aspecto indesejado, ou abra a página dos seus contatos e selecione o aspecto. Aí, clique no ícone de lixeira no canto superior direito da página."
delete_aspect_q: "Como eu apago um aspecto?"
@@ -384,6 +391,7 @@ pt-BR:
faq: "FAQ"
foundation_website: "site da Fundação Diaspora"
getting_help:
+ get_support_a_discourse: "Busque discussões existentes relacionadas à sua dúvida ou abra um novo tópico na nossa plataforma %{discourse}"
get_support_a_faq: "Leia nossa %{faq} na wiki"
get_support_a_hashtag: "Peça ajuda à comunidade: publique sua pergunta com a hashtag %{question}"
get_support_a_irc: "Junte-se a nós no %{irc} (chat ao vivo)"
@@ -413,7 +421,6 @@ pt-BR:
mentions:
how_to_mention_a: "Digite o símbolo \"@\" e comece a escrever o nome da pessoa. Um menu suspenso deve aparecer para facilitar a seleção. Repare que só é possível mencionar pessoas adicionadas a algum aspecto seu."
how_to_mention_q: "Como eu menciono alguém quando estou fazendo uma pubicação?"
- mention_in_comment_a: "Não, atualmente não."
mention_in_comment_q: "Posso mencionar alguém em um comentário?"
see_mentions_a: "Sim. Clique em \"@Menções\" na sua página inicial, na coluna à esquerda."
see_mentions_q: "Existe uma maneira de ver as publicações nas quais eu tenha sido mencionado?"
@@ -434,7 +441,7 @@ pt-BR:
find_people_a: "Se quiser convidar seus amigos para a diaspora*, use o link de convite ou o link de e-mail na barra lateral. Siga #tags para descobrir pessoas que compartilhem de seus interesses e adicione a algum aspecto aquelas que chamarem a sua atenção. Conte para todo mundo que você é #novata ou #novato em um post público."
find_people_q: "Eu acabei de me associar ao pod, como eu posso encontrar pessoas com quem eu possa compartilhar?"
title: "Pods"
- use_search_box_a: "Se você sabe a diaspora* ID completa dessas pessoas (nomedeusuario@nomedopod.org, p. ex.), você pode encontrá-las buscando diretamente pelas IDs. Se vocês estão no mesmo servidor, basta buscar pelo nome de usuário. Uma alternativa é buscar pelo nome de perfil (o que aparece na tela). Se uma busca não funcionar da primeira vez, tente novamente."
+ use_search_box_a: "Você pode encontrar pessoas buscando o nome de usuário ou de exibição (que é mostrado no perfil). Se não der certo, busque a diaspora* ID completa (nomedeusuario@nomedopod.org). Uma pesquisa pode não retornar resultados de primeira por causa de um atraso na rede. Tente novamente."
use_search_box_q: "Como eu utilizo a caixa de busca para encontrar pessoas em particular?"
what_is_a_pod_a: "Um pod é um servidor executando o software diaspora* e conectado à rede diaspora*. \"Pod\", inglês para \"vagem\", é uma metáfora das vagens que contêm as sementes das plantas, da mesma maneira que um servidor contém contas de usuários. Existem diversos pods. Você pode adicionar amigos de outros servidores e se comunicar com eles. Não é preciso abrir conta em mais de um – nesse sentido, um pod se parece com um provedor de e-mails. Há servidores públicos, privados e, com um pouco de esforço, você pode até abrir o seu próprio pod."
what_is_a_pod_q: "O que é um pod?"
@@ -445,15 +452,12 @@ pt-BR:
character_limit_q: "Qual é o limite de caracteres para publicações?"
embed_multimedia_a: "Geralmente, basta colar a URL (ex. http://www.youtube.com/watch?v=nnnnnnnnn) na publicação que o vídeo ou áudio será incorporado automaticamente, usando oEmbed. São compatíveis YouTube, Vimeo, SoundCloud e Flickr, entre outros; novos sites estão sempre sendo acrescentados à lista. Lembre-se de sempre publicar links simples e completos – nada de links encurtados ou caracteres depois da URL base – e esperar um pouco antes de atualizar a página depois de publicar para pré-visualizar."
embed_multimedia_q: "Como eu posso incorporar um vídeo, áudio, ou outro conteúdo multimídia em uma publicação?"
- format_text_a: "Utilizando um sistema simplificado chamado %{markdown}. Você pode encontrar a sintaxe completa %{here}. O botão de pré-visualização é muito útil aqui, pois você pode ver como sua mensagem parecerá antes de compartilhá-la."
+ format_text_a: "A diaspora* usa um sistema simplificado chamado %{markdown}. O editor tem botões para facilitar a formatação do texto. Se quiser formatar sua publicação manualmente, consulte a sintaxe do Markdown completa %{here}. A aba de pré-visualização serve para ver como um post vai ficar antes de compartilhá-lo. Lembre-se que você não poderá editá-lo depois de publicar, então use a pré-visualização para ter certeza de que está perfeito antes de clicar em Compartilhar!"
format_text_q: "Como eu posso formatar o texto em minhas publicações (negrito, itálico, etc.)?"
hide_posts_a: "Se você apontar seu mouse para a parte superior da publicação, um X aparece à direita. Clique nele para ocultar a publicação e desligar as notificações sobre esta publicação. Você ainda pode ver a publicação se você visitar a página de perfil da pessoa que publicou."
hide_posts_q: "Como faço para ocultar uma publicação?"
- image_text: "texto da imagem"
- image_url: "URL da imagem"
insert_images_a: "Clique no pequeno ícone de câmera para inserir uma imagem na publicação. Pressione o ícone novamente para adicionar outra foto. Você também pode selecionar múltiplas fotos para carregá-las de uma vez só."
- insert_images_comments_a1: "Não é possível fazer upload de imagens para comentários, mas o seguinte código Markdown"
- insert_images_comments_a2: "pode ser usado para inserir imagens da web aos comentários assim como às publicações."
+ insert_images_comments_a: "Você pode usar Markdown para inserir imagens da web em comentários da mesma forma que em publicações, mas não carregar imagens armazenadas no seu computador diretamente para um comentário. Primeiro faça upload do arquivo para um serviço de hospedagem de imagens e depois insira-o usando o botão de imagem que fica sobre o editor."
insert_images_comments_q: "Posso inserir imagens em comentários?"
insert_images_q: "Como eu insiro imagens às publicações?"
post_location_a: "Clique no ícone de pino ao lado da câmera na caixa de texto. Sua localização será extraída do OpenStreetMap. Você pode editá-la – é possível informar apenas a cidade onde você está, sem o nome da rua."
@@ -482,14 +486,10 @@ pt-BR:
title: "Publicações de acesso privado"
who_sees_post_a: "Somente os usuários da diaspora* logados e colocados por você nesse aspecto antes da publicação privada ser feita podem vê-la."
who_sees_post_q: "Quando eu publico uma mensagem em um aspecto (por ex., uma publicação privada), quem pode vê-la?"
- private_profiles:
- title: "Perfis privados"
- whats_in_profile_a: "Seu perfil privado contém informações como biografia, localização, sexo e data de nascimento. Todas são opcionais – você decide se vai fornecê-las ou não. Apenas pessoas autenticadas com quem você compartilha podem ver seu perfil privado, bem como as publicações privadas destinadas aos aspectos aos quais pertencem. As publicações privadas aparecem para elas na sua página de perfil, misturadas às públicas."
- whats_in_profile_q: "O que faz parte do meu perfil privado?"
- who_sees_profile_a: "Qualquer usuário logado com quem você esteja compartilhando (significa que você os adicionou a um de seus aspectos). De qualquer modo, pessoas seguem você, mas aqueles que você não segue, somente verão sua informação pública."
- who_sees_profile_q: "Quem vê meu perfil privado?"
- who_sees_updates_a: "Qualquer pessoa nos seus aspectos vê mudanças no seu perfil privado. "
- who_sees_updates_q: "Quem vê atualizações do meu perfil privado?"
+ profile:
+ title: "Perfil"
+ whats_in_profile_q: "O que aparece no meu perfil?"
+ who_sees_profile_q: "Quem vê meu perfil?"
public_posts:
can_comment_reshare_like_a: "Qualquer usuário logado em diaspora* pode comentar, recompartilhar, ou curtir sua publicação pública."
can_comment_reshare_like_q: "Quem pode comentar, recompartilhar, ou curtir minha publicação no modo público?"
@@ -502,16 +502,6 @@ pt-BR:
title: "Publicações de acesso público"
who_sees_post_a: "Qualquer internauta pode ver uma publicação marcada como pública, então tenha certeza antes de enviá-la. Lembre-se: essa é uma ótima maneira de compartilhar suas ideias com o mundo."
who_sees_post_q: "Quando eu publico alguma coisa no modo público, quem pode ver?"
- public_profiles:
- title: "Perfis públicos"
- what_do_tags_do_a: "Elas ajudam pessoas a conhecer você. Sua foto de perfil aparecerá do lado esquerdo das páginas de tags particulares, junto com alguém mais que tenha essas tags em seus perfis públicos."
- what_do_tags_do_q: "Para que servem as tags no meu perfil público?"
- whats_in_profile_a: "O seu perfil público tem seu nome, as cinco tags que você escolheu para se descrever e a sua foto, se esses campos tiverem sido preenchidos. Todas essas informações são opcionais – você decide dá-las ou não. Você pode tornar suas informações de perfil identificáveis ou anônimas, como preferir. A sua página de perfil também mostra todas as publicações públicas feitas por você."
- whats_in_profile_q: "O que faz parte do meu perfil público?"
- who_sees_profile_a: "Qualquer usuário logado em diaspora*, assim como toda a internet, podem vê-lo. Cada perfil tem um URL direto, então ele pode ter uma ligação direta a partir de sites externos. O perfil público pode ser indexado por mecanismos de busca."
- who_sees_profile_q: "Quem vê o meu perfil público?"
- who_sees_updates_a: "Quaisquer pessoas podem ver mudanças se elas visitam sua página de perfil."
- who_sees_updates_q: "Quem vê atualizações do meu perfil público?"
resharing_posts:
reshare_private_post_aspects_a: "Não, não é possível recompartilhar uma publicação privada. A razão é o respeito pelas intenções do publicador original, que compartilhou a publicação apenas com um grupo particular de pessoas."
reshare_private_post_aspects_q: "Posso recompartilhar uma publicação privada somente com certos aspectos?"
@@ -662,7 +652,8 @@ pt-BR:
mark_all_shown_as_read: "marcar tudo como lido"
mark_read: "Marcar como lido"
mark_unread: "Marcar como não lida"
- mentioned: "Mencionados"
+ mentioned: "Mencionados na publicação"
+ mentioned_in_comment: "Mencionados no comentário"
no_notifications: "Você ainda não tem notificações."
notifications: "Notificações"
reshared: "Recompartilhou"
@@ -683,6 +674,12 @@ pt-BR:
mentioned_deleted:
one: "%{actors} mencionou você em uma publicação deletada."
other: "%{actors} mencionaram você em uma publicação deletada."
+ mentioned_in_comment:
+ one: "%{actors} mencionou você em um <a href='%{comment_path}'>comentário</a>à publicação %{post_link}."
+ other: "%{actors} mencionaram você em um <a href='%{comment_path}'>comentário</a>à publicação %{post_link}."
+ mentioned_in_comment_deleted:
+ one: "%{actors} mencionou você em um comentário deletado."
+ other: "%{actors} mencionaram você em um comentário deletado."
private_message:
one: "%{actors} te enviou uma mensagem."
other: "%{actors} te enviaram uma mensagem."
@@ -779,7 +776,7 @@ pt-BR:
message: |-
Oi, tudo bem?
- %{diaspora_id} convidou você para se juntar à diaspora*!
+ %{user} convidou você para se juntar à diaspora*!
Clique neste link para começar:
@@ -804,6 +801,9 @@ pt-BR:
mentioned:
limited_post: "Você foi mencionado em uma publicação privada."
subject: "%{name} mencionou você em Diaspora*"
+ mentioned_in_comment:
+ limited_post: "Mencionaram você em um comentário a uma publicação limitada."
+ reply: "Responder ou ver esta conversa >"
private_message:
reply_to_or_view: "Responder ou visualizar esta conversa >"
subject: "Há uma nova mensagem privada para você"
@@ -1169,6 +1169,7 @@ pt-BR:
last_exported_at: "(Atualizado pela última vez às %{timestamp})"
liked: "alguém curtir uma publicação sua"
mentioned: "mencionarem você em uma publicação"
+ mentioned_in_comment: "mencionaram você em um comentário"
new_password: "Nova senha"
private_message: "você receber uma mensagem privada"
receive_email_notifications: "Receber notificações por email quando:"
diff --git a/config/locales/diaspora/pt-PT.yml b/config/locales/diaspora/pt-PT.yml
index 3a37506f6..1a9e0217c 100644
--- a/config/locales/diaspora/pt-PT.yml
+++ b/config/locales/diaspora/pt-PT.yml
@@ -268,7 +268,6 @@ pt-PT:
mentions:
how_to_mention_a: "Insira o sinal \"@\" e comece a digitar o seu nome. Deverá aparecer uma lista de comandos para o deixar selecioná-los mais facilmente. Note que só é possível mencionar pessoas que adicionou num aspeto."
how_to_mention_q: "Como é que menciono alguém quando coloco uma publicação?"
- mention_in_comment_a: "Atualmente, não."
mention_in_comment_q: "Posso mencionar alguém num comentário?"
see_mentions_a: "Sim, clique em \"Menções\" na coluna à esquerda na sua página inicial."
see_mentions_q: "Existe alguma maneira para ver as publicações nas quais eu tenha sido mencionado?"
@@ -296,11 +295,7 @@ pt-PT:
format_text_q: "Como é que eu formato o texto nas minhas publicações (negrito, itálico, etc.)?"
hide_posts_a: "Se apontar o seu rato no topo de uma publicação, aparece um X à direita. Clique-o para ocultar a publicação e cancelar as notificações sobre a mesma. Ainda pode continuar a ver a publicação se visitar a página de perfil da pessoas que a publicou."
hide_posts_q: "Como é que eu oculto uma publicação? Como é que eu deixo de receber notificações sobre uma publicação com o meu comentário?"
- image_text: "texto da imagem"
- image_url: "url da imagem"
insert_images_a: "Clique no ícone da câmara para inserir uma imagem numa publicação. Clique novamente no ícone da fotografia para adicionar outra fotografia, ou pode selecionar múltiplas fotografias para as enviar de uma vez."
- insert_images_comments_a1: "O código seguinte \"Mardown\""
- insert_images_comments_a2: "pode ser utilizado para inserir imagens da web para os comentários, bem como, nas publicações."
insert_images_comments_q: "Eu posso inserir imagens nos comentários?"
insert_images_q: "Como é que eu insiro imagens nas publicações?"
size_of_images_a: "Não. As imagens são redimensionadas automaticamente para se ajustarem ao fluxo. A redução não tem um código para especificar o tamanho de uma imagem."
@@ -321,14 +316,6 @@ pt-PT:
title: "Publicações Privadas"
who_sees_post_a: "Apenas os utilizadores logados em diaspora* que associou a esse grupo podem ver a sua publicação privada."
who_sees_post_q: "Quando eu publico uma mensagem num aspeto (ex.:, uma publicação privada), quem a pode ver?"
- private_profiles:
- title: "Perfis Privados"
- whats_in_profile_a: "Biografia, localização, sexo, e data de nascimento. É o que aparece na parte de baixo da página de edição do perfil. Toda esta informação é opcional - depende de você preencher ou não. Os utilizadores logados que você tenha adicionado aos seus grupos são as únicas pessoas que podem ver o seu perfil privado. Eles também verão as publicações privadas feitas no(s) grupos(s) em que os colocou, misturadas com as publicações públicas feitas por si, quando visitarem a sua página de perfil."
- whats_in_profile_q: "O que faz parte do meu perfil privado?"
- who_sees_profile_a: "Qualquer utilizador logado com quem você esteja a compartilhar (significa que você os adicionou a um dos seus grupos). De qualquer forma, as pessoas que o seguem mas que você não segue, verão apenas a sua informação pública."
- who_sees_profile_q: "Quem vê o meu perfil privado?"
- who_sees_updates_a: "Qualquer pessoa nos seus aspetos, vê as alterações do seu perfil privado. "
- who_sees_updates_q: "Quem vê as atualizações ao meu perfil privado?"
public_posts:
can_comment_reshare_like_a: "Qualquer utilizador do diaspora* com sessão iniciada, pode comentar, compartilhar ou gostar de uma publicação pública."
can_comment_reshare_like_q: "Quem pode comentar, recompartilhar, ou gostar na minha publicação pública?"
@@ -339,12 +326,6 @@ pt-PT:
title: "Publicações Públicas"
who_sees_post_a: "Qualquer pessoa que utilize a internet pode potencialmente ver uma publicação marcada por si como pública, por isso assegure-se de que realmente quer que ela seja pública. É uma ótima forma de apelar ao mundo lá fora."
who_sees_post_q: "Quando eu publico qualquer coisa publicamente, quem é que pode ver?"
- public_profiles:
- title: "Perfis públicos"
- whats_in_profile_q: "O que está no meu perfil público"
- who_sees_profile_q: "Quem vê o meu perfil público?"
- who_sees_updates_a: "Qualquer pessoa pode ver alterações, se visitarem a página do seu perfil."
- who_sees_updates_q: "Quem vê as atualizações ao meu perfil público?"
resharing_posts:
reshare_private_post_aspects_q: "Eu posso voltar a compartilhar uma publicação privada só com alguns aspetos?"
reshare_public_post_aspects_q: "Eu posso voltar a compartilhar uma publicação pública só com alguns aspetos?"
diff --git a/config/locales/diaspora/ru.yml b/config/locales/diaspora/ru.yml
index 0306aafa0..3d303f989 100644
--- a/config/locales/diaspora/ru.yml
+++ b/config/locales/diaspora/ru.yml
@@ -366,7 +366,6 @@ ru:
mentions:
how_to_mention_a: "Напишите знак \"@\" и начните набирать имя. Появится меню с выбором подходящих пользователей. Заметьте, что упоминать пользователя можно только, если вы добавили его в свои аспекты."
how_to_mention_q: "Как мне упомянуть кого-нибудь, когда я создаю запись?"
- mention_in_comment_a: "Пока нет."
mention_in_comment_q: "Могу ли я упомянуть кого-нибудь в комментарии?"
see_mentions_a: "Да. Нажмите кнопку \"@Упоминания\" в боковой колонке на вашей странице."
see_mentions_q: "Есть ли способ увидеть список записей, в которых я упомянут?"
@@ -402,11 +401,7 @@ ru:
format_text_q: "Как мне оформить текст моих записей (полужирный, курсив и т.д.)?"
hide_posts_a: "Если вы наведёте мышью на запись, справа вверху появится крестик. Нажмите на него. Вы всё равно сможете видеть запись и комментарии, если зайдёте на страницу к автору этой записи."
hide_posts_q: "Как мне скрыть запись и перестать получать уведомления о комментариях к ней?"
- image_text: "всплывающий текст"
- image_url: "Адрес изображения"
insert_images_a: "Нажмите пиктограмму фотокамеры и укажите нужное изображение для загрузки с вашего компьютера. Если же вы хотите вставить изображение из интернета, вы можете воспользоваться синтаксисом Мarkdown."
- insert_images_comments_a1: "Следующий код Markdown"
- insert_images_comments_a2: "может быть использован как для комментариев, так и для записей."
insert_images_comments_q: "Могу ли я добавить изображения в комментарии?"
insert_images_q: "Как мне добавить в запись изображение?"
post_location_a: "Нажмите на значёк-булавку, рядом с камерой в форме оформления записи. Это добавит ваше местоположение согласно OpenStreetMap. Вы можете подправить получившийся адрес, например оставить только город, без указания улицы."
@@ -435,14 +430,6 @@ ru:
title: "Приватные записи"
who_sees_post_a: "Только залогиненные пользователи диаспоры*, которые были добавлены в данный аспект."
who_sees_post_q: "Когда я создаю запись для аспекта (т.н. приватная запись), кто её сможет видеть?"
- private_profiles:
- title: "Приватные профили"
- whats_in_profile_a: "Биографию, местоположение, пол и день рождения. Если, конечно, вы указали эту информацию в настройках своего профиля. Страницу увидят только пользователи, которых вы добавили в свои аспекты, которые также увидят в ленте помимо публичных записей, те приватные записи, которыми вы поделились с этими аспектами."
- whats_in_profile_q: "Что содержит страница приватного профиля?"
- who_sees_profile_a: "Любой залогиненный пользователь диаспоры, которого вы добавили в свои аспекты. Тем не менее, люди, которые добавили вас, но которых не добавили вы будут видеть только публичную информацию."
- who_sees_profile_q: "Кто может видеть мой приватный профиль?"
- who_sees_updates_a: "Любой пользователь из ваших аспектов. "
- who_sees_updates_q: "Кто увидит обновления в моём приватном профиле?"
public_posts:
can_comment_reshare_like_a: "Любой зарегистрированный пользователь диаспоры."
can_comment_reshare_like_q: "Кто может комментировать мои публичные записи, делиться или отмечать как понравившиеся?"
@@ -455,16 +442,6 @@ ru:
title: "Публичные записи"
who_sees_post_a: "Все интернет пользователи могут увидеть запись, которую вы сделали публичной. Так что проверьте - действительно ли вы хотите этого. С другой стороны, это неплохой способ поделиться со всем миром."
who_sees_post_q: "Кто может видеть мои публичные записи?"
- public_profiles:
- title: "Публичные профили"
- what_do_tags_do_a: "Они помогают людям понять чем вы интересуетесь. Ваша фотография и имя появятся на странице метки слева в списке среди других людей, использовавших эту метку в их публичных профилях."
- what_do_tags_do_q: "Для чего нужны метки в моём публичном профиле?"
- whats_in_profile_a: "Ваше имя, пять меток, которые вы выбрали, чтобы описать себя, аватара и лента ваших публичных записей. Вы можете сделать эту информацию настолько личной или настолько анонимной, насколько захотите."
- whats_in_profile_q: "Что содержит страница публичного профиля?"
- who_sees_profile_a: "Любой пользователь сети Internet. Для каждого профиля есть прямая ссылка, которую можно указывать на внешних сайтах. Также публичные профили индексируются поисковыми системами."
- who_sees_profile_q: "Кто может увидеть мой публичный профиль?"
- who_sees_updates_a: "Любой пользователь сети Internet, посещающий вашу страницу."
- who_sees_updates_q: "Кто видит обновления в моём публичном профиле?"
resharing_posts:
reshare_private_post_aspects_a: "Нет. Эта функция отсутствует из уважения к желаниям автора записи, который поделился ей только с ограниченным кругом людей."
reshare_private_post_aspects_q: "Могу ли я поделиться приватной записью?"
diff --git a/config/locales/diaspora/sc.yml b/config/locales/diaspora/sc.yml
index 16a0998b2..cdafc3c40 100644
--- a/config/locales/diaspora/sc.yml
+++ b/config/locales/diaspora/sc.yml
@@ -7,6 +7,7 @@
sc:
_applications: "Aplicatziones"
_contacts: "Cuntatos"
+ _help: "Agiudu"
_services: "Servìtzios"
account: "Contu"
activerecord:
@@ -20,6 +21,14 @@ sc:
attributes:
diaspora_handle:
taken: "est giai istadu pigadu."
+ poll:
+ attributes:
+ poll_answers:
+ not_enough_poll_answers: "Non bi sunt optziones bastantes pro su sondàgiu."
+ poll_participation:
+ attributes:
+ poll:
+ already_participated: "As giai leadu parte a custu sondàgiu!"
reshare:
attributes:
root_guid:
@@ -33,6 +42,62 @@ sc:
username:
invalid: "no est bàlidu. Est possìbile impreare petzi lìteras, nùmeros, e underscores."
taken: "est giai istadu pigadu."
+ admins:
+ admin_bar:
+ pages: "Pàginas"
+ pod_stats: "Istatìsticas de su pod"
+ report: "Sinnalatziones"
+ sidekiq_monitor: "Monitor Sidekiq"
+ user_search: "Chirca impreadore"
+ weekly_user_stats: "Istatìsticas de sa chida pro s'impreadore"
+ stats:
+ 2weeks: "2 chidas"
+ 50_most: "Sas 50 etichetas prus popolares"
+ comments:
+ one: "%{count} cummentu"
+ other: "%{count} cummentos"
+ zero: "%{count} cummentos"
+ current_segment: "S'intervallu atuale tenet una mèdia de %{post_yest} publicatziones pro impreadore, dae su %{post_day}"
+ daily: "Cada die"
+ display_results: "Ammustrende sos risultados pro s'intervallu %{segment}"
+ go: "Bae"
+ month: "Mese"
+ posts:
+ one: "%{count} publicatzione"
+ other: "%{count} publicatziones"
+ zero: "%{count} publicatziones"
+ shares:
+ one: "%{count} cumpartzidura"
+ other: "%{count} cumpartziduras"
+ zero: "%{count} cumpartziduras"
+ tag_name: "Nùmene eticheta: %{name_tag} Impreada: %{count_tag} bortas"
+ usage_statistic: "Istatìsticas de impreu"
+ users:
+ one: "%{count} impreadore"
+ other: "%{count} impreadores"
+ zero: "%{count} impreadores"
+ week: "Chida"
+ user_search:
+ add_invites: "Annaghe invitos"
+ are_you_sure: "Seguru ses de chèrrere serrare su contu?"
+ close_account: "Serra su contu"
+ email_to: "Indiritzos de p. eletrònica a ue imbiare sos invitos"
+ under_13: "Ammustra sos impreadores chi tenent de mancu de 13 annos (Children's Online Privacy Protection Act)"
+ users:
+ one: "%{count} impreadore agatadu"
+ other: "%{count} impreadores agatados"
+ zero: "%{count} impreadores agatados"
+ view_profile: "Abbista profilu"
+ you_currently:
+ one: "In custu momentu tenes un'invitu disponìbile %{link}"
+ other: "In custu momentu tenes %{count} invitos disponìbiles %{link}"
+ zero: "In custu momentu non tenes prus invitos disponìbiles %{link}"
+ weekly_user_stats:
+ amount_of:
+ one: "Nùmeru de impreadores noos custa chida: %{count}"
+ other: "Nùmeru de impreadores noos custa chida: %{count}"
+ zero: "Nùmeru de impreadores noos custa chida: nissunu"
+ current_server: "Sa data atuale de su server est %{date}"
all_aspects: "Totu sas caras"
are_you_sure: "Seguru ses?"
are_you_sure_delete_account: "Seguru ses de bòlere serrare su contu tuo? Custu non podet èssere annuddadu!"
@@ -48,6 +113,7 @@ sc:
aspect_listings:
add_an_aspect: "+ Annanghe una cara"
aspect_stream:
+ make_something: "Crea carchi cosa"
stay_updated: "Abarra agiornadu"
stay_updated_explanation: "In su flussu tuo bi sunt totu sos cuntatos tuos, sas etichetas chi sighis e sas publicatziones de sos membros prus creativos de sa comunidade."
destroy:
@@ -64,17 +130,23 @@ sc:
donate: "Dona"
donate_liberapay: "Agiuda a liberapay"
help:
+ any_problem: "Tenes unu problema?"
+ contact_podmin: "Cuntata s'amministradore de su pod tuo!"
do_you: "Boles..."
feature_suggestion: "propònnere una %{link}?"
find_a_bug: "sinnalare un'%{link}?"
have_a_question: "fàghere una %{link}?"
here_to_help: "Sa comunidade de diaspora* est inoghe!"
+ mail_podmin: "Indiritzu de su podmin"
need_help: "Tenes bisòngiu de agiudu?"
support_forum_link: "forum de suportu"
tag_bug: "errore"
tag_feature: "funtzionalidade"
tag_question: "pregunta"
- introduce_yourself: "Custu est su flussu tuo. Brinca in intro e presenta·ti."
+ tutorial_link_text: "Ghias"
+ tutorials_and_wiki: "%{faq}, %{tutorial} e %{wiki}: un'agiudu pro sos primos passos tuos"
+ introduce_yourself: "Custu est su flussu tuo. Brinca a intro e presenta·ti."
+ keep_pod_running: "Mantènne %{pod} lestru e agiuda a comporare servers cun una donatzione mensile!"
new_here:
follow: "Sighi %{link} e saluda sos impitadores noos de diaspora*!"
learn_more: "Àteras informatziones"
@@ -86,7 +158,7 @@ sc:
no_contacts_message:
community_spotlight: "Prus de importu in sa comunidade"
or_spotlight: "O podes cumpartzire cun %{link}"
- try_adding_some_more_contacts: "Podes chircare o invitare àteros cuntatos."
+ try_adding_some_more_contacts: "Podes chircare o %{invite_link} àteros cuntatos."
you_should_add_some_more_contacts: "Dias dèpere annànghere carchi cuntatu in prus!"
seed:
acquaintances: "Connoschentes"
@@ -96,6 +168,13 @@ sc:
update:
failure: "Sa cara tua, %{name}, tenet unu nùmene tropu longu pro èssere sarbada."
success: "Sa cara tua, %{name}, est istada modificada."
+ blocks:
+ create:
+ failure: "Non potzo ignorare cussu impreadore. #evasione"
+ success: "AB, no as prus a bìdere cussu impreadore in su flussu tuo. #mudu!"
+ destroy:
+ failure: "Non potzo acabare de ignorare cussu impreadore. #evasione"
+ success: "Bidimus ite tenent de nàrrere! #narasalude"
bookmarklet:
explanation: "Pùblica in diaspora* dae totue annanghende %{link} a sos preferidos tuos."
post_something: "Pùblica in diaspora*"
@@ -116,18 +195,23 @@ sc:
title: "Cuntatos"
spotlight:
community_spotlight: "In evidèntzia in sa comunidade"
+ suggest_member: "Cussìgia unu membru"
conversations:
create:
fail: "Messàgiu non vàlidu"
sent: "Messàgiu imbiadu"
index:
+ conversations_inbox: "Arresonos – Càscia de sas lìteras"
inbox: "Casella de posta"
+ new_conversation: "Arresonu nou"
no_messages: "Perunu messàgiu"
new:
send: "Imbia"
sending: "Imbiende..."
subject: "Sugetu"
to: "A"
+ new_conversation:
+ fail: "Messàgiu non vàlidu"
show:
delete: "Iscantzella s'arresonu"
reply: "Risponde"
@@ -144,20 +228,200 @@ sc:
correct_the_following_errors_and_try_again: "Currege custos errore e torra a proare."
fill_me_out: "Iscrie inoghe"
find_people: "Agata pessonas o #etichetas"
+ help:
+ account_and_data_management:
+ close_account_a: "Bae a su fundu de sa pàgina de sas impostatziones tuas e incarca su butone \"Iscantzella su contu\". T'at a èssere pedidu de insertare sa crae de intrada tua pro acabare su protzessu. Ammenta·ti chi, si as a iscantzellare su contu tuo, non t'as a pòdere <strong>mai prus</strong> torrare a registrare cun su matèssi nùmene in cussu pod."
+ close_account_q: "Comente potzo iscantzellare su contu meu?"
+ data_other_podmins_a: "Cando incumintzas a cumpartzire cun calicunu in un'àteru pod totu sas publicatziones chi cumpartzis cun issos e una còpia de sos datos de su profilu tuo benit sarvada (in sa cache) in sos pods issoro. Cando iscantzellas una publicatzione o sos datos de su profilu benint iscantzellados dae unu pod una rechesta est imbia a sos àteros pods in ue bi sunt còpias sarvadas. Sas immàgines tuas non sunt mai sarvadas in pods chi non siat su tuo; petzi ligàmenes a sas immàgines benint imbiados a sos àteros pods."
+ data_other_podmins_q: "Sos amministradores de sos àteros pods podent bìdere sos datos meos?"
+ data_visible_to_podmin_a: "In sustàntzia: totus. Sa comunicatzione intre sos pods est semper criptada (impreende sos sistemas de criptàgiu SSL e de diaspora) ma sos datos sarvados in sos pods non lu sunt. Si cheret, su gestore de sa base de sos datos (database), chi est de sòlitu su chi tenet su pod, podet atzèdere a sos datos de su profilu tuo e a totu su chi as publicadu (comente sutzedit cun belle totus sos sitos web chi sarvant datos de sos utentes). Custa est sa resone proite ti damus sa possibilidade de isseberare in cale pod ti cheres registrare, ca gasi nde podes isseberare unu chi tenet un'amministradore de su cale di fidas. Tènnere unu pod pròpriu est galu mègius pro sa privadesa tua, ca gasi a tènnere atzessu a sa base de sos datos ses petzi tue."
+ data_visible_to_podmin_q: "Cantos de sos datos meos podent èssere bidos dae s'amministradore de su pod?"
+ download_data_a: "Eja. In fundu a s'ischeda pro su contu de sas impostatziones tuas as a agatare duos butones: unu pro iscarrigare sos datos tuos e un'àteru pro iscarrigare sas fotografias tuas."
+ download_data_q: "Potzo iscarrigare una còpia de totu sos datos chi bi sunt in su contu meu?"
+ move_pods_a: "Sa versione0.7.0.0 de diaspora* frunit su primu passu de su tramudòngiu de contu: como podes esportare totu sos datos tuos dae sa setzione \"Contu\" in sas impostatziones de s'impreadore. Mantene seguros sos datos tuos! In sas versiones imbenientes as a pòdere tramudare su contu intreu tuo, cun sas publicatziones e sos cuntatos, in un'àteru pod."
+ move_pods_q: "Comente potzo mòere su contu meu dae unu pod a s'àteru?"
+ title: "Gestione contu e datos"
+ aspects:
+ change_aspect_of_post_a: "Nono, ma podes semper fàghere una publicatzione noa cun su matessi cuntenutu publichende·la in una cara diferente."
+ change_aspect_of_post_q: "A pustis de àere publicadu carchi cosa, potzo cambiare sa cara(as) chi la podent bìdere?"
+ contacts_know_aspect_a: "Nono. Non podent bìdere sos nùmenes de sas caras, mai."
+ contacts_know_aspect_q: "Sos cuntatos meos ischint in cale caras los apo postos?"
+ contacts_visible_a: "Si as a isseberare custa optzione sos cuntatos dae cussa cara ant a pòdere bìdere sos àteros chi bi sunt in intro, in s'ischeda \"Cuntatos\" in sa pàgina de su profilu tuo. (Pro como, petzi sos cuntatos chi sunt in su matessi pod tuo ant a pòdere bìdere s'ischeda \"Cuntatos\" in su profilu tuo.) Est mègius a isseberare custa optziones petzi si sos cuntatos in cussa cara si connoschent unu cun s'àteru, pro esèmpiu si sa cara est pro unu tzìrculu o una sotziedade in sa cale bi ses in intro tue. In cada manera no ant pòdere bìdere su matessi su nùmene de sa cara."
+ contacts_visible_q: "Ite cheret nàrrere \"permìtere a sos cuntatos in custa cara de si bìdere unu cun s'àteru\"?"
+ delete_aspect_a: "Incarca \"Caras meas\" in sa barra laterale dae sa vista de su flussu e a pustis incarca in s'icona de sa matita a curtzu de sa cara chi cheres iscantzellare, o bae s sa pàgina de sos cuntatos tuos e ischerta sa cara chi t'interessat. Apustis incarca in s'icona de su botu de s'arga a pitzu de sa pàgina, a destra."
+ delete_aspect_q: "Comente potzo iscantzellare una cara?"
+ person_multiple_aspects_a: "Eja. Bae a sa pàgina de sos cuntatos tua e incarca in \"Cuntatos meos\". Pro cada cuntatu podes impreare su menù a destra pro los annànghere (o los bogare) dae totu sas caras chi boles. O los podes annànghere a una cara noa (o los bogare dae una) fintzas incarchende in su butone de s'ischertadore de caras in sa pàgina de su profilu issoro. O, fintzas, podes mòere su puntadore in subra de su nùmene issoro cando lu bides in su flussu, e una ventanedda at a aparire. As a pòdere cambiare sas caras in ue sunt dae ue."
+ person_multiple_aspects_q: "Potzo annànghere una persone a prus de una cara?"
+ post_multiple_aspects_a: "Eja. Cando ses creande una publicatzione imprea su butone de sas caras pro ischertare o de-ischertare caras. \"Totus sas caras\" est s'impostatzione predefinida. Sa publicatzione tua at a èssere visìbile a totu sas caras chi as a ischertare. Podes fintzas ischertare sas caras in ue boles publicare in sa barra laterale. Cando pùblicas, sa cara(as) chi as isseberadu in sa lista a manca ant a èssere ischertadas automaticamente in s'ischertadore cando as a incumintzare a fàghere una publicatzione noa."
+ post_multiple_aspects_q: "Potzo publicare cuntenutos in prus de una cara a sa borta?"
+ remove_notification_a: "Nono. E no ant a retzire una notìfica nemmancu si los as a annànghere a àteras caras, cando ses giai cumpartzinde cun issos."
+ remove_notification_q: "Si apo a bogare calicunu dae una cara, o dae totu sas caras, ant a retzire una notìfica de sa cosa?"
+ rename_aspect_a: "Incarca \"Caras meas\" in sa barra laterale dae sa vista d e su flussu e incarca in s'icona de sa matita a curtzu de sa cara chi cheres cambiare de nùmene, o bae a sa pàgina Cuntatos tua e issèbera sa cara chi boles. A pustis incarca in 'icona de editatzione a curtzu de su nùmene in pitzu de custa pàgina, càmbia su nùmene e incarca \"Agiorna\"."
+ rename_aspect_q: "Comente potzo cambiare su nùmene a una cara?"
+ restrict_posts_i_see_a: "Eja. Incarca \"Caras meas\" in sa barra laterale e, a pustis, incarca in una cara in sa lista pro l'ischertare o bogare s'ischertada. Petzi sas publicatziones dae sas persones in sas caras insertadas ant a aparire in su flussu tuo."
+ restrict_posts_i_see_q: "Potzo limitare sas publicatziones a petzi sos chi sunt in caras isseberadas?"
+ title: "Caras"
+ what_is_an_aspect_a: "Sas caras sunt una manera de agrupare sos cuntatos tuos in diaspora*. Si mutint \"caras\" ca sunt comente sas caras diferentes chi mostras a su mundu in momentos diferenetes. Diat pòdere èssere chie ses in su traballu, chie ses pro sa famìlia tua, o chie ses pro sos amigos tuos in unu grupu de su cale faghes parte."
+ what_is_an_aspect_q: "Ite est una cara?"
+ who_sees_post_a: "Cando faghes una publicatzione limitada cussa at a èssere visìbile pro sas persones chi as postu in cussa cara (o in cussas caras, si est fata in prus caras) in antis de fàghere sa publicatzione. Sos cuntatos chi non tenes in cussas caras no ant a pòdere bìdere cussa publicatzione. Sas publicatziones limitadas no ant a èssere mai visìbiles a chie non tenes in una de sas caras tuas."
+ who_sees_post_q: "Cando pùblico in un'aspetu, chie lu bidet?"
+ community_guidelines: "normas de sa comunidade"
+ foundation_website: "situ web de sa fundatzione diaspora*"
+ getting_help:
+ get_support_a_hashtag: "Pedi publicamente in diaspora* impreende s'eticheta %{question}"
+ get_support_a_irc: "Intra in %{irc} (tzarrada in direta) cun nois"
+ get_support_a_tutorials: "Abbista·ti sas %{tutorials} nostras"
+ get_support_a_website: "Bìsita su %{link} nostru"
+ get_support_a_wiki: "Chirca su %{link}"
+ get_support_q: "E si sa dimanda mea non b'est in custas FAQ? In ue potzo andare a pedire agiudu?"
+ getting_started_a: "Ses fortunadu. Proa sas %{tutorial_series} in su situ de su progetu nostru. T'at a agiudare passu pro passu cun su protzessu de registratzione e t'at a insegnare totu sas cosas de base chi depes connòschere pro impreare bene diaspora*."
+ getting_started_q: "Agiudade·mi! Mi serbit carchi informatzione de base pro incumintzare!"
+ title: "Otènnere agiudu"
+ getting_started_tutorial: "Serie de ghias \"Comente incumintzare\""
+ here: "inoghe"
+ irc: "IRC"
+ markdown: "Markdown"
+ mentions:
+ how_to_mention_a: "Iscrie su sìmbulu \"@\" e incumintza a iscrìere su nùmene suo. Unu menù a ventanedda s'at a abèrrere e l'as a pòdere ischertare in manera prus fàtzile. Ammenta·ti chi est possìbile numenare petzi a sas persones chi as annantu a una cara."
+ how_to_mention_q: "Comente potzo numenare calicunu cando so publichende una cosa?"
+ mention_in_comment_a: "Dae sa versione 0.7.0.0 eja! Podes numenare calicunu in unu cummentu in sa matessi manera chi dias impreare pro lu fàghere in una publicatzione, iscriende \"@\" e, a pustis, incumintzende a iscrìere su nùmene suo. Pro praghere ammenta·ti chi cando commentas in una publicatzione chi no est pùblica podes numenare petzi impreadores chi ant giai interagidu cun sa publicatzione."
+ mention_in_comment_q: "Potzo numenare calicunu in unu cummentu?"
+ see_mentions_a: "Eja, incarca \"@Numenadas\" in sa culunna a manca in sa pàgina printzipale tua."
+ see_mentions_q: "B'est una manera pro abbistare in cale publicatziones so istadu numenadu?"
+ title: "Numenadas"
+ what_is_a_mention_a: "Una numenada est unu ligàmene a sa pàgina de su profilu de una persone chi aparit in una publicatzione. Cando calicunu est numanedu retzit una notìfica chi li sinnalat sa publicatzione."
+ what_is_a_mention_q: "Ite est una \"numenada\"?"
+ miscellaneous:
+ back_to_top_a: "Eja. A pustis de àere fatu cùrrere in suta una pàgina, incarca in sa fritza murra chi at a aparire in s'àngulu in bassu a destra de sa bentana de s'esploradore/navigadore (browser) tuo."
+ back_to_top_q: "B'est una manera lestra de torrare a s'incumintzu de una pàgina a pustis de àere fata cùrrere in suta?"
+ diaspora_app_a: "Bi sunt istadas medas aplicatziones pro Android in isvilupu dae mebros de sa comunidade. Calicunas sunt progetos abbandonados dae meda e pro custa resone non funtzionant comente si tocat cun sa versione atuale de diaspora*. Non t'isetes meda dae custas aplicatziones, in custu momentu. Non b'est un'aplicatzione pro iOS, pro como. Sa mègius manera de atzèdere a diaspora* dae su dispositivu mòbile suo est impreende un'esploradore/navigadore (browser), ca amus progetadu una versione mòbile de su situ chi diat dèpere funtzionare bene in totu sos dispositivos, fintzas si non tenet galu totu sas funtzionalidades."
+ diaspora_app_q: "B'est un'aplicatzione de diaspora* pro Android o iOS?"
+ photo_albums_a: "Nono, pro como. In cada manera podes abbistare sas immàgines carrigadas dae una persone in suta de s'ischeda de sas fotografias in sa pàgina de su profilu suo."
+ photo_albums_q: "Bi sunt albums de fotografias o vìdeos?"
+ subscribe_feed_a: "Eja, ma custa no est galu una funtzionalidade afinada e sa formatatzione de sos risultados est galu fata a sa grussera. Si boles proare su matessi, bae a sa pàgina de profilu de calicunu e incarca su butone de su feed in s'esploradore/navigadore tuo (browser), o podes copiare su ligàmene URL de su profilu (es: https://nùmenepod.org/people/carchinùmeru) e lu podes incollare in su leghidore de feeds. S'indiritzu de su feed risultante at a aparire una cosa gasi: https://nùmenepod.org/public/nùmeneimpreadore.atom – diaspora* impreat Atom imbetzes de RSS."
+ subscribe_feed_q: "Potzo sighire sas publicatziones pùblicas cun unu leghidore de feeds?"
+ title: "Vàrias"
+ pods:
+ find_people_a: "Si cheres invitare sos amigos tuos a s'aunire a diaspora*, imprea su ligàmene de invitu o su ligàmene pro p. eletrònica in sa barra laterale. Sighi #etichetas pro iscobèrrere àteras persones chi tenent sos matessi interessos tuos, e annanghe sos chi publicant cosas chi t'interessant a una cara. Pùblica cun s'eticheta #nouinoghe pro lu fàghere ischire a sa gente e calicunu t'at a dare su \"bene bènnidu\"."
+ find_people_q: "Mi so registradu como como in unu pod, comente agato persones cun las cales cumpartzire?"
+ title: "Pods"
+ use_search_box_a: "Podes chircare una persone impreende su nùmene impreadore o su nùmene diaspora* suo (su nùmene chi est ammustradu in su profilu suo). Si ambos custos mètodos non funtzionant inserta s'ID diaspora* intreu suo (es: nùmeneimpreadore@nùmenepod.org) . Si una chirca no agatat risultados sa prima borta, diat pòdere èssere pro more de problemas de retza. Torra a proare prus a tardu."
+ use_search_box_q: "Comente potzo impreare su campu de chirca pro agatare calicunu in particulare?"
+ what_is_a_pod_a: "Unu pod est unu server in ue est installadu su programma de diaspora* e chi est connessu a sa retza de diaspora*.\"Pod\" est una metàfora chi faghet riferimentu a sas cambas de sos frores, chi cuntenint sas semesntas, gasi comente unu server cuntenit meda contos. Bi sunt meda contos diferentes. Podes annànghere amigos dae àteros pods e comunicare chin issos. Non b'est bisòngiu de abèrrere unu contu in pods diferentes! Unu bastat – in custa manera, podes pensare a unu pod de diaspora* comente a carchi cosa de sìmile a unu frunidore de posta eletrònica. Esistint pods pùblicos, privados, e cun unu pagu de apentu ti nde podes fàghere unu personale tuo."
+ what_is_a_pod_q: "It'est unu pod?"
+ posts_and_posting:
+ char_limit_services_a: "In custu casu dias limitare sa publicatzione tua a cussu lìmite de caràteres (140 in su casu de Twitter; 1000 in cussu de Tumblr), e su nùmeru de caràteres chi galu tenes est ammustradu cando s'icona de su servìtziu est alluta. Podes publicare in custos servìtzios fintzas si sa publicatzione tua est prus longa de su lìmite issoro, ma su testu at a bènnere truncadu in ie cun unu ligàmene a sa publicatzione in diaspora*."
+ char_limit_services_q: "E si so cumpartzinde sa publicatzione mea cun unu servìtziu ligadu chi tenet unu lìmite de caràteres prus minore?"
+ character_limit_a: "65,535 caràteres. Sunt 65,395 caràteres in prus de sos chi tenes in Twitter! ;)"
+ character_limit_q: "Cale est su lìmite de caràteres pro sas publicatziones?"
+ embed_multimedia_a: "De sòlitu bastat a incollare su ligàmene URL (es: http://www.youtube.com/watch?v=nnnnnnnnnnn ) in sa publicatzione tua e su vìdeu o su documentu àudio at a èssere insertadu automaticamente. Sos sitos suportados incluint: YouTube, Vimeo, SoundCloud, Flickr e calicun'àteru. diaspora* impreat oEmbed pro custa funtzionalidade. Prus tempus colat e prus sitos e mitzas de cuntenutos amus a suportare, nde semus annanghinde semper. Ammenta·ti de impreare semper sos ligàmenes intreos – cussos incurtzados no andant bene; perunu operadore a pustis de s'URL de base – e iseta carchi segundu in antis de torrare a carrigare sa pàgina a pustis de sa publicatzione pro bìdere s'anteprima."
+ embed_multimedia_q: "Comente potzo insertare unu vìdeu, unu documentu àudio o àteros cuntenutos multimediales esternos in una publicatzione?"
+ format_text_a: "diaspora* Impreat unu sistema semplificadu chi si mutit %{markdown}. Su publicadore tenet butones chi agiudant a formatare su testu. Si cheres formatare manualmente sa publicatzione tua, podes agatare sa sintassi Markdown intrea %{here}. Su butone pro s'anteprima est meda de agiudu inoghe, ca ti permitit de bìdere comente ant a aparire sas publicatziones tuas in antis chi tue las cumpartzas. Ammenta·ti chi non las podes acontzare a pustis de sa publicatzione e, pro custu motivu, de impreare s'anteprima pro èssere seguru chi totu siat a postu in antis de incarcare Cumpartzi!"
+ format_text_q: "Comente potzo formatare su testu in sas publicatziones meas (grassetu, corsivu etz.)?"
+ hide_posts_a: "Si colas su puntadore in subra de una publicatzione, a pitzu, una X at a aparire a destra. Incarca·la pro istichire sa publicatzione e istudare sas notìficas chi li pertocant. As a pòdere galu bìdere sa publicatzione si as a bisitare sa pàgina de profilu de sa persone chi l'at publicada."
+ hide_posts_q: "Comentze potzo istichire una publicatzione?"
+ insert_images_a: "Si cheres incluire in sa publicatzione tua un'immàgine sarvada in s'elaboradore tuo Incarca in s'icona chi tenet sa forma de una fotocàmera in fundu a su publicadore.Podes fintzas trisinare e lassare un'immàgine, o prus immàgines, dae s'elaboradore tuo a intro de cuss'icona. Si cheres insertare un'immàgine dae ìnternet in sa publicatzione tua incarca su butone pro sas immàgines in pitzu de su publicadore, chi at a creare su còdighe Markdown pro tie."
+ insert_images_comments_q: "Potzo insertare immàgines in sos cummentos?"
+ insert_images_q: "Comente potzo insertare immàgines in sas publicatziones meas?"
+ size_of_images_a: "Nono. Sas immàgines benint ridimensionadas automaticamente pro intrare in sa vista de su flussu o de sa publicatzione sìngula. Markdown non tenet unu còdighe pro dislindare sa mannària de un'immàgine."
+ size_of_images_q: "Potzo personalizare sa mannària de sas immàgines in sas publicatziones o in sos cummentos?"
+ stream_full_of_posts_a1: "In su flussu tuo bi sunt tres castas de publicatziones:"
+ stream_full_of_posts_li1: "Publicatziones de gente cun sa cale ses cumpartzinde, de duas genias: publicatziones pùblicas e publicatziones limitadas cun una cara in ue bi ses tue. Pro bogare custas publicatziones dae su flussu tuo firma sa cumpartzidura cun cussa persone."
+ stream_full_of_posts_li2: "Publicatziones pùblicas chi cuntenent una de sas etichetas chi sighis. Pro las bogare, acabba·la de sighire cussa eticheta."
+ stream_full_of_posts_li3: "Publicatziones pùblicas de impreadores in evidèntzia in sa comunidade. Custas podent èssere bogadas istudende s'optzione \"Ammustra \"in evidèntzia in sa comunidade\" in su flussu tuo\" in sas optziones in s'ischeda de su contu de sas impostatziones tuas."
+ stream_full_of_posts_q: "Proite su flussu meu est prenu de publicatziones de gente disconnota e cun sa cale non so cumpartzinde?"
+ title: "Publicatzione"
+ private_posts:
+ can_comment_a: "Petzi impreadores chi as annantu in cussa cara in antis de fàghere sa publicatzione podent cummentare o sinnalare chi lis agradat, e petzi cando sunt intrados in su contu issoro."
+ can_comment_q: "Chie podet cummentare o sinnalare s'agradessimentu suo in sas publicatziones privadas meas?"
+ can_reshare_a: "Nemos. Sas publicatziones privadas non podent èssere torradas a cumpartzire. Sos impreadores in cussa cara, però, dae su contu issoro lu diant pòdere copiare e incollare. De ti fidare o nono de issos est un'issèbera tua!"
+ can_reshare_q: "Chie podet torrare a cumpartzire sas publicatziones privadas meas?"
+ see_comment_a: "Petzi sas persones cun sas cales fiat cumpartzida sa publicatzione (sas persones chi sunt in sas caras isseberadas dae su publicadore originale) podent bìdere sos cummentos e sos agradessimentos. "
+ see_comment_q: "Cando cummento o sinnalo chi m'agradat una publicatzione privada, chie lu podet bìdere?"
+ title: "Publicatziones privadas"
+ who_sees_post_a: "Petzi impreadores chi as annantu in cussa cara in antis de fàghere sa publicatzione la podent bìdere, e petzi cando sunt intrados in su contu issoro."
+ who_sees_post_q: "Cando pùblico carchi cosa in una cara (creo una publicatzione privada) chie la podet bìdere?"
+ profile:
+ title: "Profilu"
+ whats_in_profile_q: "Ite b'est in su profilu meu?"
+ public_posts:
+ can_comment_reshare_like_a: "Totu sos chi tenent unu contu de diaspora* e chi bi sunt in intro podent cummentare o cumpartzire sa publicatzione tua, o sinnalare chi lis agradat. S'etzetzione sunt sos chi as ignoradu, chi no ant a pòdere pònnere agradessimentos o cummentare in sas publicatziones tuas."
+ can_comment_reshare_like_q: "Chie podet cummentare o cumpartzire sa publicatzione mea, o sinnalare chi lis agradat?"
+ deselect_aspect_posting_a: "Boghende s'ischerta a sas caras no at a tènnere efetu perunu in una publicatzione pùblica. At a abarrare pùblica e at galu a aparire in su flussu de totu sos cuntatos tuos. Pro fàghere una publicatzione chi siat visìbile petzi a carchi cara dislindada, depes ischertare cussas caras dae s'ischertadore in suta de su publicadore."
+ deselect_aspect_posting_q: "Ite acontesset cando bogo s'ischerta a una o prus caras in sa culunna a manca faghende una publicatzione pùblica?"
+ find_public_post_a: "Sas publicatziones pùblicas tuas ant a aparire in su flussu de totu sos chi ti sighint. Si as incluidu #etichetas in sa publicatzione pùblica tua totu sos chi sighint cussas etichetas ant a bìdere sa publicatzione tua in su flussu issoro. Totu sas publicatziones pùblicas tenet fintzas unu ligàmene URL suo chi cadaunu podet bìdere, fintzas chene intrare in sos contos issoro – pro custa resone sas publicatziones pùblicas podent èssere bidos pro mèdiu de ligàmenes postos diretamente in Twitter, blogs, etz. Sas publicatziones pùblicas diant pòdere èssere fintzas inditzitzadas dae sos motores de chirca."
+ find_public_post_q: "Comente podent sos àteros agatare sas publicatziones pùblicas meas?"
+ see_comment_reshare_like_a: "Sos cummentos, agradessimentos, e ri-cumaprtziduras de sas publicatziones pùblicas sunt pùblicos. Totus sos chi sunt impreende unu contu de diaspora* e fintzas totu sos àteros chi sunt in ìnternet podent bìdere sas interatziones tuas cun una publicatzione pùblica."
+ see_comment_reshare_like_q: "Cando cummento, cumpartzo, o sinnalo chi m'agradat una publicatzione pùblica, chie lu podet bìdere?"
+ title: "Publicatziones pùblicas"
+ who_sees_post_a: "Totu sos chi tenent ìnternet diant potentzialmente bìdere una publicatziones chi sinnas comente \"pùblica\", e pro custa resone depes istare atentu a nde èssere seguru a beru in antis de lu fàghere. Est una manera ispantosa de comunicare cun su mundu."
+ who_sees_post_q: "Cando pùblico carchi cosa in manera pùblica, chie lu podet bìdere?"
+ resharing_posts:
+ reshare_private_post_aspects_a: "Nono, no est possìbile a torrare a cumpartzire una publicatzione privada. Custu pro rispetare sas intentziones de su publicadore originale, chi l'at cumpartzida petzi cun unu grupu particulare de persones."
+ reshare_private_post_aspects_q: "Potzo torrare a cumpartzire una publicatzione privada in caras ischertadas?"
+ reshare_public_post_aspects_a: "Nono, cando torras a cumpartzire una publicatzione pùblica cussa diventat automaticamente una de sas publicatziones pùblicas tuas. Pro la cumpartzire petzi cun carchi cara isseberada còpia e incolla su cuntenutu in una publicatzione limitada noa."
+ reshare_public_post_aspects_q: "Potzo torrare a cumpartzire una publicatzione pùblica cun petzi carchi cara?"
+ title: "Torrare a cumparztire publicatziones"
+ sharing:
+ add_to_aspect_a1: "Naramus chi Amy at annantu Ben a una cara, ma Ben no at (galu) annantu Amy a una cara:"
+ add_to_aspect_a2: "Custa est connota comente \"cumpartzidura assimmètrica\". Si e cando Ben at a annànghere Amy a una cara at a divènnere una cumpartzidura simmètrica, cun ambas sas publicatziones pùblicas e sas privadas chi lis pertochent de ambos Amy e Ben chi lis ant a aparire in sos flussos issoro, e Amy at a pòdere bìdere su profilu privadu de Ben. Tando s'ant fintzas a pòdere imbiare messàgios privados unu cun s'àtera."
+ add_to_aspect_li1: "Ben at a retzire una notìfica chi l'at a nàrrer chi Amy at \"incumintzadu a cumpartzire\" cun Ben."
+ add_to_aspect_li2: "Amy at a incumintzare a bìdere sas publicatziones pùblicas de Ben in su flussu suo."
+ add_to_aspect_li3: "Amy no at a bìdere nissuna de sas publicatziones privadas de Ben."
+ add_to_aspect_li4: "Ben no at a bìdere sas publicatziones pùblicas o privadas de Amy in su flussu suo."
+ add_to_aspect_li5: "Ma si Ben at a andare a sa pàgina de su profilu de Amy, tando at a bìdere sas publicatziones privadas chi Amy faghet in sa cara in ue l'at postu (in paris cun sas publicatziones pùblicas de issa, chi totus podent bìdere in ie)."
+ add_to_aspect_li6: "Ben at a pòdere bìdere su profilu privadu de Amy (biografia, logu, natura, data de nàschida)."
+ add_to_aspect_li7: "Amy at a aparire in suta de \"Petzi cumpartzinde cun mie\" in sa pàgina de sos cuntatos de Ben."
+ add_to_aspect_q: "Ite acontessit cando annango calicunu a una de sas caras meas, o cando calicunu m'annanghet a una de sas caras suas?"
+ list_not_sharing_a: "Nono, ma podes bìdere si calicunu est o no est cumpartzende cun bois bisitende sa pàgina de profilu issoro. Si lu sunt faghende, b'at a èssere una icona birde a un'ala de s'ID diaspora suo. Si nono, b'at a èssere unu chircu murru."
+ list_not_sharing_q: "B'est una lista de sa gente chi apo annantu a unu de sas caras, ma chi non m'ant annantu a una de sas issoro?"
+ only_sharing_a: "Sunt persones chi t'ant annantu a una de sas caras issoro, ma chi tue no as (galu) annantu a una de sas tuas. In àteras paràulas: issos sunt cumpartzinde cun tie, ma tue non ses cumpartzinde cun issos: lu podes bìdere comente si issos ti fiant \"sighinde\". Si los as a annànghere a una cara, tando, ant a aparirein suta de cussa cara imbetzes chi in suta de \"Petzi cumpartzinde cun mie\". Abbista in susu."
+ only_sharing_q: "Chie sunt sas persones in sa lista in suta de \"Petzi cumpartzinde cun mie\" in sa pàgina mea de sos cuntatos?"
+ see_old_posts_a: "Nono. At a pòdere bìdere petzi sas publicatziones noas in cussa cara. Issu (in paris a totu sos àteros) at a pòdere bìdere sas publicatziones tuas prus betzas in sa pàgina de su profilu tua, e l'at a pòdere bìdere fintzas in su flussu suo."
+ see_old_posts_q: "Cando annango calicunu a una cara, podet bìdere sas publicatziones prus betzas chi apo giai publicadu in cussa cara?"
+ title: "Cumpartzende"
+ tags:
+ filter_tags_a: "Custu no est galu disponìbile in manera direta pro mèdiu de diaspora*, ma bi sunt %{third_party_tools} chi lu diant pòdere permìtere."
+ filter_tags_q: "Comente potzo filtrare/esclùdere carchi eticheta dae su flussu meu?"
+ followed_tags_a: "A pustis de àere chircadu un'eticheta podes incarcare su butone in pitzu de sa pàgina de s'eticheta pro \"sighire\" cussa eticheta. Gasi at aparire in sa lista de sas etichetas sighidas tuas in su menù a manca. Incarchende una de sas etichetas sighidas dae tie s'at a abèrrere sa pàgina de cussa eticheta in manera de ti permìtere de bìdere sas publicatziones reghentes chi cuntenit cussa eticheta. Incarca in #Etichetas Sighidas pro bìdere unu flussu de publicatziones chi incluit una de sas etichetas sighidas. Sas publicatziones chi incluint cussa eticheta ant fintzas a èssere annantas a su flussu printzipale tuo."
+ followed_tags_q: "Ite sunt sas “#Etichetas Sighidas” e comente potzo sighire un'eticheta?"
+ people_tag_page_a: "Sunt persones chi ant postu cussa eticheta in sa descritzione issoro in su profilu pùblicu."
+ people_tag_page_q: "Chie sunt sas persones allistadas in s'ala a manca de sa pàgina de s'eticheta?"
+ tags_in_comments_a: "Un'eticheta annanta a unu cummentu at a aparire in unu ligàmene in sa pàgina de cussa eticheta, ma no at a fàghere aparire cussa publicatzione (o cummentu) in sa pàgina de cussa eticheta. Custu funtzionat petzi pro sas etichetas in sas publicatziones."
+ tags_in_comments_q: "Potzo pònnere etichetas in sos cummentos o petzi in sas publicatziones?"
+ title: "Etichetas"
+ what_are_tags_for_a: "Sas etichetas sunt una manera pro categorizare sas publicatziones, de sòlitu pro argumentu. Chirchende un'eticheta as a bìdere totu sas publicatziones, pùblicas e privadas, chi podes bìdere cun cussa eticheta. Custu at a permìtere a chie est interessadu in unu argumentu dislindadu de agatare publicatziones pùblicas chi li pertochent."
+ what_are_tags_for_q: "A ite serbint sas etichetas?"
+ third_party_tools: "Ainas esternas"
+ title_header: "Agiudu"
+ tutorial: "ghia"
+ tutorials: "ghias"
+ wiki: "wiki"
invitations:
create:
+ empty: "Pro praghere inserta a su mancu un'indiritzu de posta eletrònica."
no_more: "Non tenes prus invitos."
+ note_already_sent: "Sos invitos sunt istados giai imbiados a: %{emails}"
rejected: "Custos indiritzos de posta eletrònica ant tentu problemas: %{emails}"
sent: "Sos invitos sunt istados imbiados a: %{emails}"
new:
+ codes_left:
+ one: "Tenes galu un'invitu cun custu còdighe"
+ other: "Tenes galu %{count} invitos cun custu còdighe"
+ zero: "Non tenes prus invitos cun custu còdighe"
+ comma_separated_plz: "Podes insertare prus indiritzos de posta eletrònica separados dae vìrgulas."
invite_someone_to_join: "Invita calicunu a intrare in diaspora*!"
language: "Limba"
+ paste_link: "Cumpartzi custu ligàmene cun sos amigos tuos pro los invitare in diaspora*, o imbia·li su ligàmene diretamente cun una e-lìtera."
send_an_invitation: "Imbia un'invitu"
+ sending_invitation: "Imbiende s'invitu..."
layouts:
application:
back_to_top: "Torra a s'incumintzu"
powered_by: "Suportadu dae diaspora*"
public_feed: "Flussu de diaspora* pùblicu de %{name}"
+ source_package: "Iscàrriga su pachete de su còdighe mitza"
+ toggle: "Allughe/istuda sa versione mòbile"
whats_new: "Ite b'est de nou?"
header:
code: "Còdighe"
@@ -181,8 +445,24 @@ sc:
other: "%{actors} ant cummentadu sa publicatzione tua %{post_link}."
zero: "%{actors} at cummentadu sa publicatzione tua %{post_link}."
index:
+ all_notifications: "Totu sas notìficas"
+ also_commented: "Àteros cummentos"
and: "e"
+ and_others:
+ one: "e un'àteru"
+ other: "e àteros %{count}"
+ zero: "e nissun'àteru"
+ comment_on_post: "Cummentu in una publicatzione"
+ liked: "Agradèssidu"
+ mark_all_as_read: "Sinnala·las totu comente lèghidas"
+ mark_read: "Sinnala comente lèghida"
+ mark_unread: "Sinna·las comente non lèghidas"
+ mentioned: "Numenadu in una publicatzione"
notifications: "Notìficas"
+ reshared: "Torrada a cumparzire"
+ show_all: "Ammustra totu"
+ show_unread: "Ammustra sas non lèghidas"
+ started_sharing: "Incumintzadu a cumpartzire"
liked:
one: "A %{actors} agradat sa publicatzione tua %{post_link}."
other: "A %{actors} agradat sa publicatzione tua %{post_link}."
@@ -218,6 +498,12 @@ sc:
notifier:
a_post_you_shared: "una publicatzione."
click_here: "Incarca inoghe"
+ comment_on_post:
+ reply: "Risponde o abbista sa publicatzione de %{name} >"
+ confirm_email:
+ click_link: "Pro ativare s'indiritzu de posta eletrònica nou tuo %{unconfirmed_email} pro praghere sighi custu ligàmene:"
+ subject: "Pro praghere ativa s'indiritzu de posta eletrònica tuo %{unconfirmed_email}"
+ email_sent_by_diaspora: "Custa e-lìtera est istada imbiada dae %{pod_name}. Si dias prefèrrere a l'acabare de retzire lìteras comente a custa,"
export_photos_email:
body: |-
Salude, %{name},
@@ -227,39 +513,345 @@ sc:
Saludos,
Su robot de sa posta eletrònica de diaspora*!
hello: "Salude %{name}!"
+ invite:
+ message: |-
+ Salude!
+
+ Ses istadu invitadu a t'iscrìere a diaspora* dae %{user}!
+
+ Incarca in custu ligàmene pro incumintzare
+
+ [%{invite_url}][1]
+
+ O podes fintzas annànghere %{diaspora_id} a sos cuntatos tuos si tenes giai unu contu.
+
+
+ Salude e trigu,
+
+ Su robot de sa posta eletrònica de diaspora*!
+
+ P.S.: Si (galu) no ischis ite est diaspora*, [inoghe][2] b'est sa risposta!
+
+ [1]: %{invite_url}
+ [2]: %{diasporafoundation_url}
+ invited_you: "%{name} t'at invitadu a t'iscrìere a diaspora*"
liked:
liked: "A %{name} l'agradat sa publicatzione tua"
+ view_post: "Abbista publicatzione >"
+ mentioned:
+ subject: "%{name} t'at numenadu in diaspora*"
private_message:
+ reply_to_or_view: "Risponde o abbista custu arresonu >"
subject: "B'est unu messàgiu privadu nou pro tie"
+ report_email:
+ body: |-
+ Salude,
+
+ s'elementu %{type} cun ID %{id} est istadu sinnaladu comente ofensivu.
+
+ Resone: "%{reason}"
+
+ [%{url}][1]
+
+ Pro praghere verifica·lu prus in presse chi podes!
+
+
+ Saludos,
+
+ Su robot de p. eletrònica de diaspora*!
+
+ [1]: %{url}
+ subject: "Un'elementu (%{type}) est istadu sinnaladu comente ofensivu"
+ type:
+ comment: "cummentu"
+ post: "publicatzione"
+ reshared:
+ reshared: "%{name} at cumpartzidu sa publicatzione tua"
+ view_post: "Abbista publicatzione >"
+ single_admin:
+ admin: "S'amministradore diaspora* tuo"
+ subject: "Unu messàgiu a pitzu de su contu diaspora* tuo:"
started_sharing:
+ sharing: "at incumintzadu a cumpartzire cun tie!"
+ subject: "%{name} at incumintzadu a cumpartzire cun tie in diaspora*"
view_profile: "Abbista su profilu de %{name}"
thanks: "Gràtzias,"
+ to_change_your_notification_settings: "pro mudaee sas impostatziones de notìfica tuas"
nsfw: "NSFW (no est adatu pro unu logu de traballu)"
ok: "AB"
people:
+ add_contact:
+ invited_by: "Ses istadu invitadu dae"
+ index:
+ couldnt_find_them: "Non l'as agatadu/a?"
+ looking_for: "Ses chirchende publicatziones etichetadas cun %{tag_link}?"
+ no_one_found: "...e nemos est istadu agatadu."
+ no_results: "Ehi! Depes iscriere carchi cosa pro chircare."
+ results_for: "Impreadores currelados a %{search_term}"
+ search_handle: "Imprea s'ID diaspora* issoro (nùmeneimpreadore@pod.tld) pro tènnere sa tzerteza de agatare sos amigos tuos."
+ searching: "Chirchende, pro praghere iseta..."
+ send_invite: "Galu nudda? Imbia un'invitu!"
+ person:
+ thats_you: "Ses tue!"
profile_sidebar:
+ bio: "Biografia"
born: "Die de nàschida"
gender: "Gènere"
location: "Logu"
+ show:
+ closed_account: "Custu contu est istadu serradu."
+ does_not_exist: "Custa persone no esistit!"
+ has_not_shared_with_you_yet: "%{name} no at galu cumpartzidu peruna publicatzione cun tie!"
photos:
+ create:
+ integrity_error: "Carrigamentu de sa fotografia fallidu. Seguru ses chi cussa fiat un'immàgine?"
+ runtime_error: "Carrigamentu de sa fotografia fallidu. As ismentigadu de pònnere sa tzinta de sa màchina?"
+ type_error: "Carrigamentu de sa fotografia fallidu. Seguru ses de àere annantu un'immàgine?"
destroy:
notice: "Fotografia iscantzellada."
new_profile_photo:
upload: "Càrriga una fotografia de profilu noa!"
+ posts:
+ presenter:
+ title: "Una publicatzione de %{name}"
+ show:
+ photos_by:
+ one: "Una fotografia de %{author}"
+ other: "%{count} fotografias de %{author}"
+ zero: "Peruna fotografia de %{author}"
+ reshare_by: "Cumpartzidu dae %{author}"
privacy: "Privadesa"
profile: "Profilu"
+ profiles:
+ edit:
+ allow_search: "Permiti a sos àteros de ti chircare in intro de diaspora*"
+ first_name: "Nùmene"
+ last_name: "Sambenadu"
+ nsfw_check: "Sinna totu sos chi cumpartzo comente NSFW"
+ nsfw_explanation: "NSFW (“not safe for work”, non apropriadu pro su traballu) est s'istandard de sa comunidade pro su cuntenutu chi diat pòdere non èssere adatu pro èssere bidu cando ses in unu logu de traballu. Si tenes s'intentzione de cumpartzire custa casta de materiale in manera fitiana pro praghere incarca custa optzione pro istichire totu sos chi cumpartzis dae sos flussos de sa gente, si non isseberant de lu bìdere."
+ nsfw_explanation2: "Si as isseberadu de non ischertare custa optzione pro praghere annanghe s'eticheta #nsfw cada borta chi cumpartzis carchi cosa de custa casta."
+ update_profile: "Agiorna su profilu"
+ your_bio: "Sa biografia tua"
+ your_birthday: "Su compleannu tuo"
+ your_gender: "Gènere"
+ your_location: "In ue ses"
+ your_name: "Su nùmene tuo"
+ your_photo: "Sa fotografia tua"
+ your_tags: "Descrie·ti in 5 paràulas"
+ your_tags_placeholder: "Pro esèmpiu #films #gatos #biàgios #mùsica #nùgoro"
+ update:
+ failed: "Agiornamentu de su profilu fallidu"
+ updated: "Profilu agiornadu"
public: "Pùblicu"
+ registrations:
+ closed: "Sas registratziones sunt serradas in custu pod de diaspora*."
+ create:
+ success: "Ti ses registradu in diaspora*!"
+ invalid_invite: "Su ligàmene de invitu chi as impreadu no est prus vàlidu!"
+ new:
+ email: "P. eletr. (e-mail)"
+ enter_email: "Inserta s'indiritzu de posta eletrònica tuo"
+ enter_password: "Inserta una crae de intrada (màssimu ses caràteres)"
+ enter_password_again: "Inserta sa matessi crae chi as iscritu in antis"
+ enter_username: "Issèbera unu nùmene impreadore (petzi lìteras, nùmeros e tratigheddos bassos)"
+ password: "Crae"
+ password_confirmation: "Cunfirma sa crae"
+ sign_up: "Crea unu contu"
+ submitting: "Imbiende..."
+ username: "Nùmene impreadore"
+ report:
+ comment_label: "<b>Cummentu</b>: %{data}"
+ delete_link: "Iscantzella elementu"
+ post_label: "<b>Publicatzione</b>: %{content}"
+ reason_label: "Resone:"
+ reported_label: "<b>Sinnaladu dae</b> %{person}"
+ review_link: "Sinna comente verificadu"
+ title: "Summàriu de sas verìficas"
+ reshares:
+ comment_email_subject: "Sa cumpartzidura de %{resharer} de sa publicatzione de %{author}"
+ reshare:
+ deleted: "Publicatzione originale iscantzellada dae s'autore."
+ reshare_confirmation: "Cumpartzire sa publicatzione de %{author}?"
+ reshared_via: "Cumpartzidu pro mèdiu de"
search: "Chirca"
+ services:
+ create:
+ already_authorized: "Un'impreadore cun id diaspora %{diaspora_id} at giai autorizadu cussu contu de %{service_name}."
+ failure: "Autenticatzione fallida."
+ read_only_access: "S'atzessu est in modalidade petzi leghidura, pro praghere torra a proare a l'autorizare prus a tardu"
+ success: "Autenticatzione resissida."
+ destroy:
+ success: "Iscantzellamentu de s'autenticatzione resissidu."
+ failure:
+ error: "B'est istadu un'errore in sa connessione a cussu servìtziu"
+ index:
+ disconnect: "Disconnete"
+ edit_services: "Modìfica sos servìtzios"
+ logged_in_as: "Atzessu fatu comente %{nickname}."
+ really_disconnect: "Disconnètere %{service}?"
+ services_explanation: "Cunnetende·ti a servìtzios esternos as a tènnere sa possibilidade de publicare in ie su chi iscries in diaspora*."
settings: "Impostatziones"
+ shared:
+ aspect_dropdown:
+ toggle:
+ one: "In %{count} cara"
+ other: "In %{count} caras"
+ invitations:
+ by_email: "Invita gente pro mèdiu de e-lìteras"
+ invite_your_friends: "Invita sos amigos tuos"
+ invites: "Invitos"
+ share_this: "Cumpartzi custu ligàmene impreende sa posta eletrònica, sos blogs o sas retzas sotziales!"
+ public_explain:
+ atom_feed: "Flussu Atom"
+ control_your_audience: "Manìgia su pùblicu tuo"
+ logged_in: "Atzessu fatu in %{service}"
+ manage: "Manìgia sos servìtzios ligados"
+ new_user_welcome_message: "Imprea sos #cantzelletos pro classificare sas publicatziones tuas e agatare persones chi cumpartzint sos interessos tuos. Nùmena perones ispantosas cun @Numenadas"
+ outside: "Sos messàgios pùblicos ant a èssere disponìbile fintzas a sa vista de chie est in foras de diaspora*."
+ share: "Cumpartzi"
+ title: "Imposta servìtzios ligados"
+ visibility_dropdown: "Imprea custu menù pro mudare sa visibilidade de sa publicatzione tua. (Pro custa prima publicatzione ti cunsigiamus de la lassare pùblica.)"
+ publisher:
+ discard_post: "Iscantzella sa publicatzione"
+ formatWithMarkdown: "Podes impreare %{markdown_link} pro formatare sa publicatzione tua"
+ get_location: "Agata sa positzione tua"
+ new_user_prefill:
+ hello: "Salude a totus, so #%{new_user_tag}. "
+ i_like: "Sos interessos meos sunt %{tags}. "
+ invited_by: "Gràtzias pro s'invitu, "
+ newhere: "nouinoghe"
+ poll:
+ add_a_poll: "Annanghe unu sondàgiu"
+ posting: "Publichende..."
+ remove_location: "Boga sa positzione"
+ share: "Cumpartzi"
+ whats_on_your_mind: "A ite ses pensende?"
+ stream_element:
+ via: "Pro mèdiu de %{link}"
+ via_mobile: "Pro mèdiu de unu tzellulare"
+ simple_captcha:
+ label: "Inserta su còdighe in s'iscatuledda:"
+ message:
+ default: "Su còdighe segretu non currispondet cun s'immàgine"
+ failed: "Sa verìfica de s'umanidade est fallida"
+ user: "S'immàgine segreta e su còdighe sunt diferentes"
+ placeholder: "Inserta su valore de s'immàgine"
+ status_messages:
+ new:
+ mentioning: "Ses numenende: %{person}"
+ too_long: "Pro praghere iscrie un'istadu cun prus pagu de %{count} caràteres. In custu momentu bi sunt %{current_length} caràteres."
streams:
+ activity:
+ title: "Atividade mea"
admin:
title: "Amministradore"
+ aspects:
+ title: "Caras meas"
+ aspects_stream: "Caras"
+ comment_stream:
+ title: "Publicatziones cummentadas"
commented:
title: "Publicatziones cummentadas"
+ community_spotlight_stream: "In evidèntzia in sa comunidade"
+ followed_tag:
+ add_a_tag: "Annanghe un'eticheta"
+ follow: "Sighi"
+ title: "#Etichetas sighidas"
+ followed_tags_stream: "#Etichetas sighidas"
+ like_stream:
+ title: "Publicatziones chi t'agradant"
liked:
title: "Publicatziones agradadas"
+ mentioned_stream: "@Numenadas"
+ mentions:
+ title: "@Numenadas"
+ multi:
+ title: "Flussu"
+ public:
+ title: "Atividade pùblica"
+ tags:
+ title: "Publicatziones cun s'eticheta: %{tags}"
+ tags:
+ show:
+ follow: "Sighi #%{tag}"
+ none: "S'eticheta bòida no esistit!"
+ stop_following: "Acaba·la de sighire #%{tag}"
username: "Nùmene impitadore"
users:
+ confirm_email:
+ email_confirmed: "P. eletrònica %{email} ativada"
+ email_not_confirmed: "S'indiritzu de p. eletrònica no est istadu aviadu. B'est unu problema cun su ligàmene?"
+ destroy:
+ no_password: "Pro praghere inserta sa crae atuale tua pro serrare su contu tuo."
+ success: "Su contu tuo est istadu blocadu. Nos podent bòlere finas a 20 minutos pro acabare de serrare su contu tuo. Gràtzias pro àere proadu diaspora*."
+ wrong_password: "Sa crae insertada no est sa chi ses impreande como."
edit:
+ also_commented: "calicunu at cummentadu una publicatzione chi as cummentadu fintzas tue"
+ auto_follow_aspect: "Cara pro sos impreadores cun sos cales cumpartzis automaticamente:"
+ auto_follow_back: "Cumpartzi automaticamente cun sos impreadores chi incumintzant a cumpartzire cun tie"
+ change: "Càmbia"
+ change_email: "Càmbia s'indiritzu de posta eletrònica"
+ change_language: "Càmbia sa limba"
+ change_password: "Càmbia sa crae de intrada"
+ character_minimum_expl: "depet tènnere a su mancu ses caràteres"
+ close_account:
+ dont_go: "Ajò, non ti c'andes!"
+ lock_username: "Su nùmene impreadore tuo at a èssere blocadu. No as a pòdere prus creare unu contu in custu pod cun su matessi ID."
+ locked_out: "As a èssere bogadu a foras dae su contu tuo e non b'as a pòdere intrare prus finas a cando no at a èssere istadu iscantzelladu."
+ make_diaspora_better: "Nos diat agradare meda a tènnere s'agiudu tuo pro megiorare diaspora*; si cheres nos podes dare una manu, imbetzes de ti c'andare. Si ti che cheres andare a beru custu est su chi depes fàghere:"
+ mr_wiggles: "Mr Wiggles at a èssere tristu si ti c'andas!"
+ no_turning_back: "No as a pòdere prus torrare in segus! Si a beru ses seguru, inserta sa crae tua inoghe in suta."
+ what_we_delete: "Amus a iscantzellare totu sas publicatziones tuas e sos datos de su profilu tuo su prus in presse chi podimus. Sos cummentos tuos in sas publicatziones de àtera gente ant a abarrare, ma ant a èssere atzotziados a s'ID diaspora* tuo imbetzes chi a su nùmene tuo."
+ close_account_text: "Serra su contu"
+ comment_on_post: "calicunu cummentat una publicatzione tua"
+ current_password: "Crae de como"
+ current_password_expl: "sa chi impreas pro intrare..."
download_export_photos: "Iscàrriga sas fotos meas"
- export_photos_in_progress: "Semus elaborande sas fotos tuas. Pro piaghere torra a compidare intre pagu." \ No newline at end of file
+ edit_account: "Modìfica su contu"
+ email_awaiting_confirmation: "Amus imbiadu unu ligàmene de cunfirma a%{unconfirmed_email}. Finas a cando no as a àere abertu cussu ligàmene e no as a àere ativadu s'indiritzu nou amos a impreare s'indiritzu originale tuo %{email}."
+ export_data: "Esporta sos datos"
+ export_photos_in_progress: "Semus elaborande sas fotos tuas. Pro piaghere torra a compidare intre pagu."
+ following: "Impostatziones de cumpartzidura"
+ liked: "a calicunu agradat una publicatzione tua"
+ mentioned: "ses numenadu in una publicatzione"
+ new_password: "Crae noa"
+ private_message: "as retzidu unu messàgiu privadu"
+ receive_email_notifications: "Retzi notìficas pro mèdiu de e-lìteras cando:"
+ reshared: "calicunu at cumpartzidu una publicatzione tua"
+ show_community_spotlight: "Ammustra \"in evidèntzia in sa comunidade\" in su flussu tuo"
+ show_getting_started: "Ammustra sa ghia initziale"
+ started_sharing: "calicunu at incumintzadu a cumpartzire cun tie"
+ stream_preferences: "Preferèntzias pro su flussu"
+ your_email: "S'indiritzu de posta eletrònica tuo"
+ your_handle: "S'ID diaspora* tuo"
+ getting_started:
+ awesome_take_me_to_diaspora: "Fantasticu! Faghe·mi intrare in diaspora*"
+ community_welcome: "Sa comunidade de diaspora* est cuntenta de ti tènnere a bordu cun nois!"
+ connect_to_facebook: "Podimus fàghere in manera unu pagu prus lestra impreende %{link} a diaspora*. Gasi as a carrigare su nùmene e sa fotografia tua, e as a abilitare sa cumpartzidura de sas publicatziones."
+ connect_to_facebook_link: "Su collegamentu de su contu tuo de Facebook"
+ hashtag_explanation: "Sos cantzelletos ti permitint de chistionare de sos interessos tuos e de los sighire. Sunt fintzas una manera ispantosa de connòschere gente noa in diaspora*."
+ hashtag_suggestions: "Proa a sighire etichetas comente a #art, #movies, #gif, etz."
+ well_hello_there: "Salude!"
+ what_are_you_in_to: "Cales sunt sos interessos tuos?"
+ who_are_you: "Chie ses tue?"
+ privacy_settings:
+ ignored_users: "Impreadores ignorados"
+ stop_ignoring: "Acaba·la de l'ignorare"
+ title: "Impostatziones pro sa privadesa"
+ public:
+ does_not_exist: "S'impreadore %{username} no esistit!"
+ update:
+ email_notifications_changed: "Notìficas pro mèdiu de p. eletrònica modificadas"
+ follow_settings_changed: "Impostatziones pro sa sighidura cambiadas"
+ follow_settings_not_changed: "Modìfica de sas impostatziones de sighidura fallida."
+ language_changed: "Limba cambiada"
+ language_not_changed: "Càmbiu de sa limba fallidu"
+ password_changed: "Crae cambiada. Como podes intrare in su contu tuo cun sa crae noa."
+ password_not_changed: "Càmbiu de sa crae fallidu"
+ settings_not_updated: "Agiornamentu de sas impostatziones fallidu"
+ settings_updated: "Impostatziones agiornadas"
+ unconfirmed_email_changed: "Indiritzu de posta eletrònica cambiadu. Tenet bisòngiu de èssere ativadu."
+ unconfirmed_email_not_changed: "Modìfica de s'indiritzu de posta eletrònica fallida"
+ will_paginate:
+ next_label: "imbeniente &raquo;"
+ previous_label: "&laquo; antepostu" \ No newline at end of file
diff --git a/config/locales/diaspora/sk.yml b/config/locales/diaspora/sk.yml
index 225dec5ba..8e7a18984 100644
--- a/config/locales/diaspora/sk.yml
+++ b/config/locales/diaspora/sk.yml
@@ -266,7 +266,6 @@ sk:
mentions:
how_to_mention_a: "Napíš znak \"@\" pred meno toho človeka (bez medzery). Malo by sa zobraziť rolovacie menu, aby si si mohol (-hla) ľahšie vybrať. Pamätaj si, že takto môžeš spomenúť iba ľudí, ktorých máš pridaných do kategórií."
how_to_mention_q: "Ako môžem niekoho spomenúť, keď píšem príspevok?"
- mention_in_comment_a: "Nie, nie v súčasnosti."
mention_in_comment_q: "Môžem niekoho spomenúť v komentári?"
title: "Zmienky"
what_is_a_mention_a: "Zmienka je odkaz na niečiu stránku s profilom, ktorý sa objaví v príspevku. Keď niekoho spomeniete, dostane oznam, ktorý upriami jeho pozornosť na príspevok."
@@ -281,25 +280,15 @@ sk:
character_limit_a: "65 535 znakov. To je o 65 395 znakov viac, ako Ti dá Twitter! ;)"
character_limit_q: "Aký je limit znakov pre príspevok?"
format_text_q: "Ako môžem formátovať text v mojom príspevku (hrúbku, kurzíva, atď.)?"
- image_text: "text k obrázku"
- image_url: "adresa obrázka"
insert_images_comments_q: "Môžem vložiť obrázok do komentáru?"
insert_images_q: "Ako môžem vložiť obrázok do príspevku?"
size_of_images_q: "Môžem upraviť veľkosť obrázku v príspevku alebo komentári?"
title: "Príspevky a ich posielanie"
private_posts:
title: "Súkromné príspevky"
- private_profiles:
- title: "Súkromné profily"
- whats_in_profile_q: "Čo obsahuje môj súkromný profil?"
- who_sees_profile_q: "Kto vidí môj osobný profil?"
public_posts:
find_public_post_q: "Ako môžu ľudia nájsť môj verejný príspevok?"
title: "Verejné príspevky"
- public_profiles:
- title: "Verejné profily"
- whats_in_profile_q: "Čo je môj verejný profil?"
- who_sees_profile_q: "Kto vidí môj verejný profil?"
sharing:
title: "Zdieľanie"
tags:
diff --git a/config/locales/diaspora/sv.yml b/config/locales/diaspora/sv.yml
index 9c9ebe8f3..01c5a8149 100644
--- a/config/locales/diaspora/sv.yml
+++ b/config/locales/diaspora/sv.yml
@@ -409,7 +409,6 @@ sv:
mentions:
how_to_mention_a: "Skriv ett snabel-a innan du skriver personens namn. En meny borde då dyka upp med dina kontakter i, för att hjälpa dig att nämna rätt person. Observera att du bara kan nämna personer som finns i någon av dina aspekter."
how_to_mention_q: "Hur nämner jag någon när jag skriver ett inlägg?"
- mention_in_comment_a: "Nej, inte i nuläget."
mention_in_comment_q: "Kan jag @nämna någon i en kommentar?"
see_mentions_a: "Ja. Tryck på \"@Omnämnanden\" i vänstra kolonnen på din sida."
see_mentions_q: "Är det möjligt för mig att se inlägg jag nämnts i?"
@@ -445,11 +444,7 @@ sv:
format_text_q: "Hur kan jag formatera texten i mina inlägg? (Fet stil, kursivera, etcetera.)"
hide_posts_a: "Om du pekar muspekaren överst på ett inlägg kommer ett kryss att dyka upp till höger. Tryck på det för att dölja inlägget och avsluta notifieringarna berörande det. Du kommer fortfarande kunna se inlägget om du besöker författarens profilsida."
hide_posts_q: "Hur döljer jag ett inlägg?"
- image_text: "bildtext"
- image_url: "bild-url"
insert_images_a: "Tryck på den lilla kameraikonen för att bifoga en bild till inlägget. Tryck på ikonen igen för att lägga till fler foton. Du kan välja fler att ladda upp flera bilder samtidigt"
- insert_images_comments_a1: "Du kan inte ha bilder i kommentarer, men med följande kodrad"
- insert_images_comments_a2: "används för att lägga till bilder från en webbplats till både kommentarer och inlägg."
insert_images_comments_q: "Kan jag lägga till bilder i kommentarer?"
insert_images_q: "Hur lägger jag in bilder till mitt inlägg?"
post_location_a: "Tryck på knappnålsikonen bredvid kameran där du laddar upp bilder. Det här kommer att lägga till din plats från OpenStreetMap.org. Du själv kan ändra platsen, för att bara ange staden du befinner dig i och inte den exakta adressen."
@@ -478,14 +473,6 @@ sv:
title: "Privata inlägg"
who_sees_post_a: "Bara personer som är inloggade på Diaspora*, och som du har i en aspekt, kan se dessa privata inlägg."
who_sees_post_q: "Vem kan se mitt inlägg till en aspekt, alltså ett privat inlägg?"
- private_profiles:
- title: "Privata profiler"
- whats_in_profile_a: "Biografi, plats, kön och födelsedag; om du angivit dessa. De finns längst ned på profilredigeringssidan. All information är frivillig – det är du som bestämmer vad som skall fyllas i. Inloggade personer i dina aspekter är de enda som kan se din privata profil. De kommer också att se privata inlägg som du skrivit till den aspekten eller de aspekterna som du lagt till dem i. När de besöker din profilsida syns dem bland dina publika inlägg."
- whats_in_profile_q: "Vad finns i min privata profil?"
- who_sees_profile_a: "Alla inloggade användare som du har i en aspekt skulle kunna se din privata profil. Personer som följer dig, men du inte följer, kan däremot se din publika information."
- who_sees_profile_q: "Vilka ser min privata profil?"
- who_sees_updates_a: "Personerna i dina aspekter ser ändringarna du gör till din profil. "
- who_sees_updates_q: "Vilka ser dem uppdateringar jag gör till min privata profil?"
public_posts:
can_comment_reshare_like_a: "Bara de som är inloggade på Diaspora* kan kommentera, dela vidare och gilla dina offentliga inlägg."
can_comment_reshare_like_q: "Vilka kan kommentera, dela och gilla mina publika inlägg?"
@@ -498,16 +485,6 @@ sv:
title: "Publika inlägg"
who_sees_post_a: "Vem som helst med en Internetuppkoppling kan potentiellt se dina publika inlägg. Var därför noga med att du verkligen vill att dina publika inlägg skall vara publika. Det är bra sätt komma i kontakt med resten av världen."
who_sees_post_q: "Vilka ser de publika inlägg som jag gör?"
- public_profiles:
- title: "Publika profiler"
- what_do_tags_do_a: "Taggarna hjälper andra att lära känna dig. Din profilbild kommer också att synas till på taggarnas sida, tillsammans med alla andra som har dessa taggar på sin sida."
- what_do_tags_do_q: "Vad gör taggarna på min publika profilsida?"
- whats_in_profile_a: "Ditt namn, de fem taggarna du beskrivit dig med och din profilbild. De ändras i den övre delen på profilinställningssidan. Du kan själv välja hur publik du vill att informationen på din profilsida ska vara. Din profilsida visar även alla de offentliga inlägg du har gjort."
- whats_in_profile_q: "Vad syns i min publika profil?"
- who_sees_profile_a: "Alla som besöker din sida kan se den, oavsett om de är inloggade på Diaspora* eller inte. Varje profil har en direktlänk så att man kan länka till den direkt från andra sidor. Sökmotorer kan indexera din profilsida."
- who_sees_profile_q: "Vilka ser min publika profil?"
- who_sees_updates_a: "Alla kan se ändringarna du gör, givet att de besöker din sida."
- who_sees_updates_q: "Vilka ser uppdateringar av min offentliga profilsida?"
resharing_posts:
reshare_private_post_aspects_a: "Nej, det är inte möjligt att dela vidare privata inlägg. Med hänsyn för upphovspersonen, kan inlägget bara ses av dem personen själv vill."
reshare_private_post_aspects_q: "Kan jag dela vidare privata inlägg till specifika aspekter?"
diff --git a/config/locales/diaspora/te.yml b/config/locales/diaspora/te.yml
index 9f517d98c..8bfb6a7f6 100644
--- a/config/locales/diaspora/te.yml
+++ b/config/locales/diaspora/te.yml
@@ -298,7 +298,6 @@ te:
markdown: "మార్క్‌డౌన్"
mentions:
how_to_mention_q: "నేను పోస్టు చేసేటప్పుడు ఎవరినైనా పేర్కొనడం ఎలా?"
- mention_in_comment_a: "లేదు, ప్రస్థుతం వీలుకాదు."
mention_in_comment_q: "వ్యాఖ్యలో ఎవరినైనా నేను పేర్కొనవచ్చా?"
title: "పేర్కోలు"
what_is_a_mention_q: "“పేర్కొలు” అంటే ఏమిటి?"
@@ -310,8 +309,6 @@ te:
posts_and_posting:
character_limit_q: "టపాలకు అక్షరాల పరిమితి ఎంత?"
hide_posts_q: "ఒక పోస్టును దాయడం ఎలా?"
- image_text: "బొమ్మ పాఠ్యం"
- image_url: "బొమ్మ url"
insert_images_comments_q: "వ్యాఖ్యలలో బొమ్మలను పెట్ట‍డం ఎలా?"
insert_images_q: "జాబులలో బొమ్మలను పెట్టడ‍ం ఎలా?"
post_location_q: "టపాలకు నా ప్రాంతాన్ని ఎలా చేర్చవచ్చు?"
@@ -320,23 +317,10 @@ te:
can_comment_q: "నా రహస్య టపాలను ఎవరు ఇష్టపడవచ్చు లేదా వ్యాఖ్యలను ఉంచవచ్చు?"
can_reshare_q: "నా రహస్య టపాలను ఎవరెవరు తిరిగి పంచుకోగలరు?"
title: "అంతరంగిక టపాలు"
- private_profiles:
- title: "రహస్య ప్రవరలు"
- whats_in_profile_q: "నా రహస్య ప్రవరలో ఏమేమి ఉంటుంది?"
- who_sees_profile_q: "నా రహస్య ప్రవరను ఎవరెవరు చూడగలరు?"
- who_sees_updates_q: "నా రహస్య ప్రవర తాజాకరణలను ఎవరెవరు చూస్తారు?"
public_posts:
find_public_post_q: "నా బహిరంగ టపాలను ఇతరులు ఎలా కనుగొనగలరు?"
title: "బహిరంగ టపాలు"
who_sees_post_q: "నేను ఏదైనా బహిరంగంగా ప్రచురించినపుడు, దాన్ని ఎవరు చూడగలరు?"
- public_profiles:
- title: "బహిరంగ ప్రవరలు"
- what_do_tags_do_a: "మీ గురించి తెలుసుకోవడానికి వ్యక్తులకు ఉపయోగపడతాయి. ఎవరైతే కొసలను వారి బహిరంగ ప్రవరలో కలిగివున్నారో వారు మరియు ఆయా నిర్దిష్ట కొస పుటలలో ఎడమవైపు మీ ప్రవర చిత్రం కూడా కనిపిస్తుంది."
- what_do_tags_do_q: "నా బహిరంగ ప్రవరపై ఉన్న కొసలు ఏమి చేస్తాయి?"
- whats_in_profile_q: "నా బహిరంగ ప్రవరలో ఏముంటుంది?"
- who_sees_profile_q: "నా బహిరంగ ప్రవరను ఎవరు చూడగలరు?"
- who_sees_updates_a: "మీ ప్రవర పుటను సందర్శించిన వారు ఎవరైనా చూడగలరు."
- who_sees_updates_q: "నా బహిరంగ ప్రవర తాజాకరణలను ఎవరెవరు చూడగలరు?"
resharing_posts:
title: "టపాలను మళ్ళీ పంచుకొనుట"
sharing:
diff --git a/config/locales/diaspora/tr.yml b/config/locales/diaspora/tr.yml
index cde3970a0..4aa106506 100644
--- a/config/locales/diaspora/tr.yml
+++ b/config/locales/diaspora/tr.yml
@@ -179,6 +179,12 @@ tr:
heading: "Diaspora yer işareti"
post_something: "Diaspora için bir şey gönder"
cancel: "İptal Et"
+ color_themes:
+ dark_green: "Koyu yeşil"
+ egyptian_blue: "Mısır mavisi"
+ magenta: "Macenta"
+ original: "Asıl gri"
+ original_white: "Asıl beyaz arkaplan"
comments:
new_comment:
comment: "Yorum yaz"
@@ -284,7 +290,6 @@ tr:
mentions:
how_to_mention_a: "@ yazın ve kullanıcının adını yazmaya başlayın. Açılır menü, seçiminizi kolaylaştırmak üzere belirecektir. Yalnızca bir bakışa eklediğiniz kişiden bahsedebilirsiniz."
how_to_mention_q: "Gönderi yaparken birisini nasıl anabilirim?"
- mention_in_comment_a: "Hayır, henüz değil."
mention_in_comment_q: "Bir yorumun içinde birisini anabilir miyim?"
see_mentions_a: "Evet. Ana sayfanızın sol sütunundaki \"Anılmalar\"ı tıklayın."
see_mentions_q: "Benim anıldığım gönderileri görmenin bir yolu var mı?"
@@ -315,10 +320,7 @@ tr:
format_text_q: "Gönderilerimi nasıl biçimlendirebilirim(kalın, İtalik, vs.)?"
hide_posts_a: "Fareyi gönderinin üzerinde getirdiğinizde sağ tarafta X belirir. Ona tıkladığınızda gönderiyi gizleyip bildirimleri susturmuş olursunuz. Ancak bu, gönderenin profilini ziyaret ettiğinizde gönderiyi görmenizi engellemez."
hide_posts_q: "Gönderilerimi nasıl gizlerim?"
- image_text: "resim metni"
- image_url: "resim url'si"
insert_images_a: "Ufak kamera simgesine tıklayarak bunu yapabilirsiniz. Başka bir görüntü yüklemek için kamera simgesine tekrar tıklayabilir veya birden fazlasını tek seferde yükleyebilirsiniz."
- insert_images_comments_a1: "Aşağıda not düşülen kod"
insert_images_comments_q: "Yorumlara resim ekleyebilir miyim?"
insert_images_q: "Gönderilere nasıl görüntü eklerim?"
size_of_images_a: "Yapamazsınız. Resimler kendiliğinden akış genişliğine uyacak şekilde boyutlandırılırlar. Markdown içinde resim boyutunu belirleyecek bir kod yoktur."
@@ -333,19 +335,8 @@ tr:
can_reshare_a: "Hiç kimse. Özel gönderiler yeniden paylaşılamaz, ancak diaspora* nın kopyala-yapıştır koruması yoktur."
can_reshare_q: "Özel gönderimi kim paylaşabilir?"
title: "Özel gönderiler"
- private_profiles:
- title: "Özel profiller"
- whats_in_profile_q: "Ne benim özel profil var?"
- who_sees_profile_a: "Paylaşımda bulunduğunuz (bakışlarınızdan birinde olan) her hangi kullanıcı, adıyla girdiğinde görebilir. Ancak sizin takip etmediğiniz takipçiler, ancak herkese açık bilgilerinizi görür."
- who_sees_profile_q: "Özel profilimi kimler görür?"
- who_sees_updates_a: "Bakışlarınızdaki herkes özel profilinizdeki değişiklikleri görebilir. "
- who_sees_updates_q: "Özel profilimin güncelllemelerini kim görebilir?"
public_posts:
title: "Genel gönderiler"
- public_profiles:
- title: "Genel profiller"
- whats_in_profile_a: "Adınız, kendinizi tanımladığınız beş etiket, fotoğrafınız. Profili düzenleme sayfasının üstündeki şeyler. Profil bilgilerini tanımlanabilir ya da anonim olarak tanımlayabilirsiniz. Profil sayfası ayrıca tüm genel gönderilerinizi gösterir."
- whats_in_profile_q: "Genel profilimin içinde ne var"
resharing_posts:
reshare_private_post_aspects_a: "Hayır, bu mümkün değildir. Böyle bir şey, gönderenin, yalnızca belirli bir kitle ile paylaşmak niyetine ters düşerdi."
reshare_private_post_aspects_q: "Özel bir gönderiyi yeniden paylaşabilir miyim?"
diff --git a/config/locales/diaspora/uk.yml b/config/locales/diaspora/uk.yml
index 05f558559..5260a79b8 100644
--- a/config/locales/diaspora/uk.yml
+++ b/config/locales/diaspora/uk.yml
@@ -288,6 +288,13 @@ uk:
heading: "Інтерактивна закладка Діаспори"
post_something: "Повідомлення до Діаспори"
cancel: "Скасувати"
+ color_themes:
+ dark: "Темний"
+ dark_green: "Темно-зелений"
+ egyptian_blue: "Єгипетська синь"
+ magenta: "Маджента"
+ original: "Оригінальний синій"
+ original_white: "Оригінальний з білим тлом"
comments:
create:
error: "Неможливо коментувати."
@@ -395,9 +402,11 @@ uk:
add_contact_roster_q: "Як я можу поспілкуватися з кимось у Діаспора?"
contacts_page: "сторінка контактів"
title: "Розмова"
+ community_guidelines: "правила спільноти"
faq: "ЧаПи"
foundation_website: "сайт Diaspora* Foundation"
getting_help:
+ get_support_a_discourse: "Пошукайте наявні обговорення, що стосуються вашого питання, або започаткуйте нову тему на нашій платформі %{discourse}"
get_support_a_faq: "Читайте нашу %{faq} сторінку у вікі"
get_support_a_hashtag: "запитайте в публічному записі на Діаспорі*, використовуючи мітку %{question}"
get_support_a_irc: "приєднуйтесь до нас в %{irc} або джаббер чаті diaspora@conference.dukgo.com"
@@ -427,7 +436,7 @@ uk:
mentions:
how_to_mention_a: "Напишіть знак \"@\" та почніть набирати ім'я. З'явиться меню з вибором відповідних користувачів. Зауважте, що згадувати користувача можна тільки, якщо ви додали його у свої аспекти."
how_to_mention_q: "Як мені згадати кого-небудь, коли я створюю запис?"
- mention_in_comment_a: "Поки що ні."
+ mention_in_comment_a: "Починаючи з версії 0.7.0.0, так! Ви можете згадати когось у коментарі так само, як у дописі, написавши «@», а тоді ім'я. Будь ласка, зауважте, що коли коментуєте непублічний допис, то можна згадати лише тих користувачів, які якось відреагували на допис."
mention_in_comment_q: "Чи можна згадати кого-небудь у коментарях?"
see_mentions_a: "Так. Натисність кнопку \"@Упоминания\" у бічній панелі на вашій сторінці."
see_mentions_q: "Чи є спосіб побачити список записів, у яких я згадуюсь?"
@@ -463,11 +472,8 @@ uk:
format_text_q: "Як мені оформити текст моїх записів (полужирний, курсив і т.д.)?"
hide_posts_a: "Якщо Ви наведете мишкою на запис, справа вверху з'явиться хрестик. Натисніть на нього. Ви все одно зможете бачити запис і коментарі, якщо зайдете на сторінку до автора цього запису."
hide_posts_q: "Як мені приховати запис і перестати отримувати повідомлення про коментарі до нього?"
- image_text: "спливаючий текст"
- image_url: "Адреса зображення"
insert_images_a: "Натисність піктограму фотокамери та вкажіть потрібне зображення для завантаження з вашого комп'ютера. Якщо ж Ви бажаєте вставити зображення з Інтернету, то Ви можете скористатися синтаксисом Мarkdown."
- insert_images_comments_a1: "Ви не можете завантажувати зображення в коментарі, але можете скористатись кодом Markdown"
- insert_images_comments_a2: "може бути використаний як для коментарів, так і для записів."
+ insert_images_comments_a: "Ми можете використовувати Markdown, щоб вставити зображення з мережі у коментар, так само, як і в дописах. Однак прямо з комп'ютера завантажити зображення не можна. Закиньте їх на сервіс гостингу зображень, а тоді вставте, скориставшись кнопкою зображень."
insert_images_comments_q: "Чи можу я додати зображення у коментарі?"
insert_images_q: "Як мені додати у запис зображення?"
post_location_a: "Натисніть на значок-булавку, поряд з камерою у вікні оформлення запису. Це добавить ваше місце розташування згідно OpenStreetMap. Ви можете відредагувати адресу, наприклад залишивши тільки місто, без вказівки вулиці."
@@ -496,14 +502,14 @@ uk:
title: "Приватні записи"
who_sees_post_a: "Тільки залогінені користувачі Діаспори*, які були додані в цей аспект."
who_sees_post_q: "Коли я створюю запис для аспекту (тобто приватний запис), хто його зможе бачити?"
- private_profiles:
- title: "Приватні профілі"
- whats_in_profile_a: "Біографію, місцезнаходження, стать і день народження. Якщо, звичайно, ви вказали цю інформацію у налаштуваннях свого профілю. Сторінку побачать лише користувачі, яких ви додали у свої аспекти, які також побачать у стрічці крім публічних записів, ті приватні записи, якими ви поділились з цими аспектами."
- whats_in_profile_q: "Що знаходиться в моєму приватному профілі?"
- who_sees_profile_a: "Будь-який залогинений користувач Діаспори, якого ви додали у свої аспекти. Проте, люди, які додали вас, але яких не додали ви бачитимуть тільки публічну інформацію."
- who_sees_profile_q: "Хто може бачити мій приватний профіль?"
- who_sees_updates_a: "Будь-який користувач з ваших аспектів. "
- who_sees_updates_q: "Хто побачить оновлення у моєму приватному профілі?"
+ profile:
+ title: "Профіль"
+ what_do_tags_do_a: "Допомагають іншим людям з вами познайомитися. Картинка вашого профілю також з'являтиметься ліворуч на сторінках стрічок цих міток, поруч з іншими, хто використовує їх у своєму публічному профілі."
+ what_do_tags_do_q: "Що роблять мітки в моєму основному профілі?"
+ whats_in_profile_a: "Ваш профіль складається з двох частин: основний профіль і розширений. До вашого основного профілю належить ім'я, п'ять міток, якими ви себе представляєте, і фото. Ваш розширений профіль містить біографію, розташування, стать та дату народження. Уся ця інформація необов'язкова: від вас залежить, чи надавати її, і свій профіль можна зробити так впізнаваним чи анонімним, як ви хочете. Розширений профіль показується у лівій колонці сторінки профілю, під картинкою профілю."
+ whats_in_profile_q: "Що є в моєму профілі"
+ who_sees_profile_a: "Ваш основний профіль (ім'я, зображення і #мітки) — публічний. Ваш розширений профіль за замовчуванням приватний, але за бажання його можна зробити публічно доступним. Лише люди, з якими ви ділитеся (тобто ви додали їх до одного з аспектів), можуть бачити ваш розширений профіль, якщо він приватний. Інші люди бачать лише публічну інформацію. Будь-яку інформацію, яку ви робите публічною, може переглянути будь-хто в мережі, і вона також індексується пошуковиками"
+ who_sees_profile_q: "Хто бачить мій профіль?"
public_posts:
can_comment_reshare_like_a: "Будь-який зареєстрований користувач Діаспори*."
can_comment_reshare_like_q: "Хто може коментувати мої публічні записи, ділитися або відмічати як вподобані?"
@@ -516,16 +522,6 @@ uk:
title: "Публічні записи"
who_sees_post_a: "Всі інтернет користувачі можуть побачити запис, який ви зробили публічним. Так що перевірте - чи дійсно ви хочете цього. З іншого боку це непоганий спосіб поділитися зі всім світом."
who_sees_post_q: "Хто може бачити мої публічні записи?"
- public_profiles:
- title: "Публічні профілі"
- what_do_tags_do_a: "Вони допомагають людям пізнати Вас. Ваш аватар також буде відображатись у списку зліва серед інших людей, які використовували цю позначку в їх публічних профілях."
- what_do_tags_do_q: "Для чого потрібні позначки у моєму публічному профілі?"
- whats_in_profile_a: "Ваше ім'я, п'ять позначок, які Ви вибрали, щоб описати себе, аватар і стрічка ваших публічних записів. Ви можете зробити цю інформацію настільки особистою або настільки анонімною, наскільки захочете."
- whats_in_profile_q: "Що містить сторінка публічного профілю?"
- who_sees_profile_a: "Будь-який користувач Діаспори* а також інтернету може побачити це. У кожного профілю є пряме посилання, яке можна вказувати на зовнішніх сайтах.Також публічні профілі індексуються пошуковими системами."
- who_sees_profile_q: "Хто бачить мій публічний профіль?"
- who_sees_updates_a: "Будь-який користувач мережі Internet, відвідуючий вашу сторінку."
- who_sees_updates_q: "Хто бачить оновлення в моєму публічному профілі?"
resharing_posts:
reshare_private_post_aspects_a: "Ні. Ця функція відсутня з поваги до бажань автора запису, який поділився ним тільки з обмеженим колом людей."
reshare_private_post_aspects_q: "Чи можу я поділитися приватним записом?"
@@ -684,6 +680,7 @@ uk:
mark_read: "Помітити як прочитане"
mark_unread: "позначити як непрочитане"
mentioned: "Згадав"
+ mentioned_in_comment: "Згадується у коментарі"
no_notifications: "У Вас немає повідомлень."
notifications: "Повідомлення"
reshared: "Поділився"
@@ -716,6 +713,16 @@ uk:
one: "%{actors} згадали вас у вилученому записі."
other: "%{actors} згадали вас у вилученому записі."
zero: "%{actors} згадали вас у вилученому записі."
+ mentioned_in_comment:
+ few: "%{actors} згадали Вас в <a href='%{comment_path}'>коментарях</a> до запису %{post_link}."
+ many: "%{actors} згадали Вас в <a href='%{comment_path}'>коментарях</a> до запису %{post_link}."
+ one: "%{actors} згадав Вас в <a href='%{comment_path}'>коментарі</a> до запису %{post_link}."
+ other: "%{actors} згадали Вас в <a href='%{comment_path}'>коментарях</a> до запису %{post_link}."
+ mentioned_in_comment_deleted:
+ few: "%{actors} згадали Вас у видалених коментарях."
+ many: "%{actors} згадали Вас у видалених коментарях."
+ one: "%{actors} згадав Вас у видаленому коментарі."
+ other: "%{actors} згадали Вас у видалених коментарях."
private_message:
few: "%{actors} надіслали вам повідомлення."
many: "%{actors} надіслали вам повідомлення."
@@ -849,6 +856,9 @@ uk:
mentioned:
limited_post: "Вас згадали в приватному записі."
subject: "%{name} згадав вас у Діаспорі*"
+ mentioned_in_comment:
+ limited_post: "Ви були згадані в коментарі до приватного запису."
+ reply: "Відповісти або подивитися цю розмову>"
private_message:
reply_to_or_view: "Відповісти або подивитися цю бесіду >"
subject: "Там нове ПП для Вас"
@@ -1224,6 +1234,7 @@ uk:
last_exported_at: "(Востаннє оновлено %{timestamp})"
liked: "комусь подобається ваш запис"
mentioned: "вас згадали у записі"
+ mentioned_in_comment: "вас згадали у коментарі"
new_password: "Новий пароль"
private_message: "ви отримали особисте повідомлення"
receive_email_notifications: "Отримувати повідомлення електронною поштою, коли:"
diff --git a/config/locales/diaspora/zh-TW.yml b/config/locales/diaspora/zh-TW.yml
index 1aea8e6ff..e8ed7b43c 100644
--- a/config/locales/diaspora/zh-TW.yml
+++ b/config/locales/diaspora/zh-TW.yml
@@ -267,6 +267,13 @@ zh-TW:
heading: "書籤小程式"
post_something: "貼到 diaspora*"
cancel: "取消"
+ color_themes:
+ dark: "暗色系"
+ dark_green: "暗綠色"
+ egyptian_blue: "埃及藍"
+ magenta: "紫紅色"
+ original: "原始灰"
+ original_white: "原始白背"
comments:
create:
error: "發表意見失敗。"
@@ -342,7 +349,7 @@ zh-TW:
data_visible_to_podmin_q: "我所在豆莢的管理員可以看到多少我的資料?"
download_data_a: "可以的。在設定頁面的帳號頁籤的最下面,分別有兩個按鈕可以讓你下載個人資料和相片。"
download_data_q: "我可以把豆子裡全部的資料都下載下來嗎?"
- move_pods_a: "目前不行,未來我們會加入匯出匯入的功能,你就可以從某個豆莢匯出後,再從另一個豆莢匯入了。不過你還是可以開一個新的帳號以及裡面的社交面,然後把每一個聯絡人重加一次,請他們也重加你一次。"
+ move_pods_a: "0.7..0.0 版的 diaspora* 支援帳號移轉的第一個步驟: 你可以在使用者設定的「帳號」下匯出你的所有資料。請好好保管資料!你將可以在未來的版本中完全移轉你的帳號到其他的豆莢,保留之前的貼文和聯絡人。"
move_pods_q: "要怎樣把我的豆子(帳號)搬到別的豆莢去呢?"
title: "帳號與資料管理"
aspects:
@@ -350,7 +357,7 @@ zh-TW:
change_aspect_of_post_q: "我可以在貼文之後更改它發表的社交面嗎?"
contacts_know_aspect_a: "不知道。無論如何他們都看不到社交面的名稱。"
contacts_know_aspect_q: "我的聯絡人知道我把他們放到哪些社交面中嗎?"
- contacts_visible_a: 如果你對某個社交面打開這個選項,那麼其中的所有聯絡人都可以從你個人檔案的"聯絡人"頁籤看到其他人。最好是在該社交面中的所有人都彼此認識的情況下,才開啟這個選項,比如說是專屬於某個社團或你所屬社群的社交面。不過聯絡人並不會知道你把這個社交面叫什麼名字。
+ contacts_visible_a: 如果你對某個社交面打開這個選項,那麼其中的所有聯絡人都可以從你個人檔案的"聯絡人"頁籤看到其他人。(不過,目前版本只有跟你在同一個豆莢的聯絡人才看得到。)最好是在該社交面中的所有人都彼此認識的情況下,才開啟這個選項,比如說是專屬於某個社團或你所屬社群的社交面。不過聯絡人並不會知道你把這個社交面叫什麼名字。
contacts_visible_q: "\"讓社交面中的聯絡人可以互相看見\"是什麼意思?"
delete_aspect_a: 請從流水帳畫面的側邊欄點一下"我的社交面",然後點一下你想刪掉的那個社交面旁邊的鉛筆圖示。或是到你的聯絡人畫面,點選你想刪掉的那一面。接著點一下頁面右上方的垃圾桶圖示就可以了。
delete_aspect_q: "要怎樣刪掉社交面?"
@@ -374,9 +381,11 @@ zh-TW:
add_contact_roster_q: "要怎樣在 diaspora* 跟某人即時聊天?"
contacts_page: "聯絡人頁面"
title: "即時聊天"
+ community_guidelines: "社群共識"
faq: "常見問答"
foundation_website: "diaspora* 基金會網站"
getting_help:
+ get_support_a_discourse: "來我們的%{discourse}平台搜尋看看你的問題是否已經被討論過,或是開始一個新的討論串。"
get_support_a_faq: "來看看我們在維基上的%{faq}頁面"
get_support_a_hashtag: "公開用 %{question} 標籤在 diaspora* 上發問"
get_support_a_irc: "來%{irc}加入我們(即時聊天)"
@@ -406,7 +415,7 @@ zh-TW:
mentions:
how_to_mention_a: "先打 @ 符號再接著打名字,應該會出現一個下拉式選單讓你比較好選。要注意的是你只能提到那些在你的社交面中的人。"
how_to_mention_q: "我在寫貼文時要怎樣提到某人?"
- mention_in_comment_a: "目前還不行。"
+ mention_in_comment_a: "從 0.7.0.0 版開始就可以了!你可以在回應中提到某人,就像在貼文中一樣,只要先打 @ 符號再接著名字就可以了。請注意,如果你回應的是非公開的貼文,就只能夠指指點點已經跟該貼文互動的人。"
mention_in_comment_q: "我可以在留言中提到某人嗎?"
see_mentions_a: 可以,請點首頁左手邊的"@指指點點"。
see_mentions_q: "有辦法看到所有我被提到的貼文嗎?"
@@ -427,7 +436,7 @@ zh-TW:
find_people_a: "你可以用側邊欄的邀請或電子郵件連結,來邀請你的朋友一起加入 diaspora*。你也可以用追蹤 #標籤 來尋找志同道合的人,這樣當他們發表了你有興趣的貼文時,你就可以將他們加進你的社交面。公開貼文大喊你是 #新來的 也行。"
find_people_q: "我剛剛加入一個豆莢,要怎樣找到其它可以分享的人?"
title: "豆莢"
- use_search_box_a: "如果你知道他們的 diaspora* 識別碼全寫的話(比方說像是 username@podname.org),直接搜尋識別碼就可以了。如果你們在同一個豆莢裡,可以用他們的使用者名稱搜尋。不然就用他們的檔案名字(也就是畫面上看到的名字)搜尋看看。如果第一次搜尋不到,就再重試一次看看。"
+ use_search_box_a: "你可以用使用者名稱或是 diaspora* 名稱(也就是檔案上看到的名字)來搜尋他們。如果都沒有的話,就改用完整的 diaspora* 識別碼(像是 username@podname.org)搜尋。第一次搜尋可能會因為網路延遲而搜尋不到,可以再重試一次看看。"
use_search_box_q: "要怎樣用搜尋框框找到特定的人?"
what_is_a_pod_a: "豆莢是一台伺服器,上面跑了 diaspora* 軟體,和整個 diaspora* 網路相連接。用\"豆莢\"這一個詞,是在比喻伺服器上包含了許多使用者的帳號,就有如植物的豆莢包含了許多豆子一樣。網路上會有許許多多的豆莢。你可以加位於其它豆莢的朋友,好跟他們交流。你不需要在每個豆莢都註冊,只要有一個帳號就夠了!你也可以想像 diaspora* 豆莢就好像電子郵件的信箱一樣:有公開供應的,也有私人專屬的,甚至如果你肯下功夫,也可以維護自己的信箱或豆莢。"
what_is_a_pod_q: "什麼是豆莢?"
@@ -438,24 +447,21 @@ zh-TW:
character_limit_q: "貼文的字數上限是多少?"
embed_multimedia_a: "通常只要在你的貼文中貼影片或音訊的網址(比如說: http://www.youtube.com/watch?v=nnnnnnnnnnn),就會自動嵌入了。支援的網站有: YouTube, Vimeo, SoundCloud, Flickr 等等。diaspora* 用 oEmbed 機制來提供這個功能。我們會陸續支援更多的媒體來源網站。請記得一定要貼完整的的網址,而不是縮短過的,也不要有多餘的控制參數。貼完後要看預覽畫面的話,請先等一段時間再重新載入頁面。"
embed_multimedia_q: "要怎樣在貼文中嵌入一段影片、音訊、或是其他多媒體作品?"
- format_text_a: "用一種叫%{markdown}的簡化寫法,在%{here}有完整的格式說明。\"預覽\"按鈕可以讓你在分享出去之前,先知道貼文看起來會是什麼樣子,真的很有用。"
+ format_text_a: "diaspora* 用一種叫%{markdown}的簡化排版系統。發表對話框上有一些按鈕可以幫助排版。如果你想要自己手動排版的話,在%{here}有完整的格式說明。\"預覽\"分頁可以讓你在分享出去之前,先知道貼文看起來會是什麼樣子。要知道貼文後是不能再修改的,所以在分享出去之前,請用預覽來確定它完美無瑕!"
format_text_q: "要怎樣對我的貼文加格式(比如說加粗、推斜等等)?"
hide_posts_a: "當你把滑鼠游標放在一篇貼文上面時,右邊會出現一個 X 圖示。點那個圖示就可以把貼文隱藏起來,也不會再收到關於它的通知。你還是可以到作者的個人檔案去找到那篇貼文。"
hide_posts_q: "要怎樣隱藏一篇貼文?"
- image_text: "圖片說明"
- image_url: "圖片網址"
- insert_images_a: "按那個照相機的小圖示就可以選一張要放到貼文裡的圖片。再按一次就可以再加一張相片,或是一次同時選好幾張相片也可以。"
- insert_images_comments_a1: "你不能上傳圖片到留言裡面,但是貼文和留言都可以用以下的 Markdown 語法:"
- insert_images_comments_a2: "來顯示在網路上的圖片。"
+ insert_images_a: "如果你想要在貼文中加一張存在電腦上的圖片,請按發表對話框下方的那個照相機小圖示。也可以拖放一張或多張的圖片到那個圖示上。如果你想要加入一張網路(web)上的圖片,請按發表對話框上方的圖片按鈕,就會產生對應的 Markdown 代碼。"
+ insert_images_comments_a: "你可以在回應時用 Markdown 加入網路上的圖片,就像是在貼文時一樣。不過,你不能直接加入在你的電腦上的圖片。替代方案是:先將圖片上傳到其他相簿網站,然後用發表對話框上方的圖片按鈕來加入連結。"
insert_images_comments_q: "我可以在留言中放圖片嗎?"
insert_images_q: "要怎樣把圖片放到貼文裡面?"
- post_location_a: "按一下發表對話盒的別針圖示,就在相機的旁邊。這樣會把你的所在位置用 OpenStreetMap 加到貼文去。你也可以編輯你的位置,比如說你可能只想要標那個城市,而不是完整的地址。"
+ post_location_a: "按一下發表對話框的別針圖示,就在相機的旁邊。這樣會把你的所在位置用 OpenStreetMap 加到貼文去。你也可以編輯你的位置,比如說你可能只想要標那個城市,而不是完整的地址。"
post_location_q: "要怎樣把我的所在位置加到貼文去?"
post_notification_a: "你可以在貼文的右上角看到一個鈴鐺的圖示,點這個圖示就可以打開或關掉該篇貼文的活動通知。"
post_notification_q: "要怎樣收到或停止收到某一篇貼文的活動通知?"
post_poll_a: "點圖表那個圖示就可以產生一場投票。你要打題目以及至少兩個選項。如果想要任何人都能參加你的投票的話,別忘了要公開你的貼文。"
post_poll_q: "要怎樣加一場投票到貼文裡?"
- post_report_a: "點一下貼文右上角的三角警告圖示就可以投訴給你的莢主。請在對話盒中輸入投訴的理由。"
+ post_report_a: "點一下貼文右上角的三角警告圖示就可以投訴給你的莢主。請在對話盒中輸入投訴的理由。只有在貼文違反%{community_guidelines}或是豆莢的使用條款時才投訴它,比如說包含違法內容、濫用、或是大量廣告。"
post_report_q: "要怎樣投訴某一篇貼文涉及人身攻擊呢?"
size_of_images_a: "不行。圖片會根據目前是流水帳或單一貼文的版面來自動調整大小。Markdown 並沒有設定圖片大小的語法。"
size_of_images_q: "我可以設定貼文或留言中的圖片大小嗎?"
@@ -475,19 +481,19 @@ zh-TW:
title: "非公開貼文"
who_sees_post_a: "只有在你發表該篇非公開貼文前,就已經在那個社交面中的使用者才可以看得到,並且必須要在登入 diaspora* 的狀態下。"
who_sees_post_q: "當我貼文到某個社交面時(也就是貼一篇非公開貼文),有誰可以看得到?"
- private_profiles:
- title: "私人檔案"
- whats_in_profile_a: "私人檔案裡面可以有自傳、所在地、性別、還有生日。你可以選擇要提供哪些給人看,沒有一項是必需要填的。只有那些你把他們加到社交面中的人,在登入的狀態下可以看到你的私人檔案。當他們看你的個人檔案時,除了你的公開貼文之外,還可以看到他們所屬社交面的非公開貼文。"
- whats_in_profile_q: "私人檔案裡面有什麼?"
- who_sees_profile_a: "任何你有跟他們分享的人(也就是那些你把他們加到社交面中的人)都可以。那些有追蹤你,但是你沒有追蹤他們的人,只能夠看到你的公開檔案。"
- who_sees_profile_q: "誰看得到我的私人檔案?"
- who_sees_updates_a: "任何在你的社交面中的人都可以看得到你私人檔案的改變。"
- who_sees_updates_q: "我的私人檔案更新時,誰可以看得到?"
+ profile:
+ title: "個人檔案"
+ what_do_tags_do_a: "這些標籤可以幫助人們了解你。這些標籤的標籤流水帳的左手邊也會顯示你和其他人的個人照,你們的共同點就是基本檔案裡包含了該標籤。"
+ what_do_tags_do_q: "基本檔案裡的標籤有什麼用途?"
+ whats_in_profile_a: "個人檔案有兩個部份:基本檔案和進階檔案。基本檔案包含了名字、描述你自己的五個標籤、以及你的相片。進階檔案則包含了自傳、所在地、性別、還有生日。這些資料都不是必填的,要不要提供隨你高興,內容是要很容易看出來是你本人,還是要神神秘秘都可以。進階檔案會顯示在個人檔案頁面的左手邊 、個人照的下方位置。"
+ whats_in_profile_q: "個人檔案裡面有什麼?"
+ who_sees_profile_a: "你的基本檔案(名字、個人照、和 #標籤)是公開的。進階檔案則預設是不公開的,但是你想的話也可以開放給大家看。如果維持不公開的話,只有你有跟他們分享的人(也就是那些你把他們加到社交面中的人)才能看見。其他人只能看到你的公開資訊。任何一個網路(web)使用者都能夠看到你開放出來的所有檔案資料,也可能被搜尋引擎建檔使用。"
+ who_sees_profile_q: "誰看得到我的個人檔案?"
public_posts:
- can_comment_reshare_like_a: "任何 diaspora* 的使用者在登入狀態下都可以對你的公開貼文留言、轉貼、或是按讚。"
+ can_comment_reshare_like_a: "任何 diaspora* 的使用者在登入狀態下都可以對你的公開貼文留言、轉貼、或是按讚。被你忽視的人是例外,他們不能對你的貼文按讚或留言。"
can_comment_reshare_like_q: "誰可以對我的公開貼文留言、轉貼、或是按讚?"
- deselect_aspect_posting_a: "沒有影響,它還是一篇公開貼文,還是會出現在你的所有聯絡人的流水帳裡。如果只想讓某些面看到該篇貼文,你必須要在發表時點選那些面。"
- deselect_aspect_posting_q: "我在發表公開貼文時,不選某個或某些面會有什麼影響?"
+ deselect_aspect_posting_a: "沒有影響,它還是一篇公開貼文,還是會出現在你的所有聯絡人的流水帳裡。如果只想讓某些面看到該篇貼文,你必須要在發表對話框下方點選那些面。"
+ deselect_aspect_posting_q: "我在發表公開貼文時,不選左手邊的某個或某些社交面會有什麼影響?"
find_public_post_a: "追蹤你的人會在他們的流水帳看到。如果你在貼文中加了 #標籤 ,那麼任何追蹤該標籤的人都會在他們的流水帳看到。每一篇公開貼文都有專屬的網址,讓任何人不用登入都可以用那個網址看到。因此,公開貼文的連結可以直接貼到 Twitter​、部落格、或是其他地方去。公開貼文也有可能會被搜尋引擎收集並編入索引。"
find_public_post_q: "其他人要怎樣找到我的公開貼文?"
see_comment_reshare_like_a: "公開貼文的留言、稱讚、或是轉貼,也都是公開的。任何登入 diaspora* 的使用者,以及其他使用網際網路的人,都可以看到你對該篇貼文的參與。"
@@ -495,16 +501,6 @@ zh-TW:
title: "公開貼文"
who_sees_post_a: "任何用網際網路的人都有可能看到你公開的貼文,因此請務必確定你希望該貼文要公開出去。這是一個和世界溝通的好方法。"
who_sees_post_q: "當我公開貼文時,誰可以看得到?"
- public_profiles:
- title: "公開檔案"
- what_do_tags_do_a: "幫助別人了解你。另外,在這些標籤的專頁的左側也會秀你和其他檔案中有該標籤的人的個人照。"
- what_do_tags_do_q: "個人檔案裡的標籤有什麼用?"
- whats_in_profile_a: "你的公開檔案可能包含了你的名字、描述你自己的五個標籤、以及你的相片。你可以選擇要提供哪些給別人看,沒有一項是必須要填的。隨你高興要讓它一眼就知道是你,還是完全認不出來是誰。你的個人檔案也會顯示你發表過的公開貼文。"
- whats_in_profile_q: "公開檔案的內容有什麼?"
- who_sees_profile_a: "任何在登入狀態下的 diaspora* 使用者,以及廣大的網際網路世界,都可以看到。每個個人檔案都有一個網址,透過這個網址其他外部網站可以直接連結該檔案。公開檔案也有可能被搜尋引擎收集並編入索引。"
- who_sees_profile_q: "誰會看到我的公開檔案?"
- who_sees_updates_a: "任何來看你的個人檔案頁面的人都可以。"
- who_sees_updates_q: "誰會看到我的公開檔案的更新?"
resharing_posts:
reshare_private_post_aspects_a: "不行,非公開貼文是不能轉貼的。這是為了要尊重原作者的意願,因為她/他只想跟特定的一群人分享。"
reshare_private_post_aspects_q: "我可以轉貼一篇非公開貼文到特定的社交面嗎?"
@@ -523,7 +519,7 @@ zh-TW:
add_to_aspect_li7: 春嬌會出現在志明聯絡人頁面中的"跟我分享的人"裡面。
add_to_aspect_li8: "春嬌也開始可以在貼文裡 @指指點點 志明。"
add_to_aspect_q: "當我把某人加進某個社交面,或是當某人把我加進她/他的某一面時,會發生什麼事?"
- list_not_sharing_a: "沒有,但是你可以看某人的個人檔案來檢查她/他是否有跟你分享。如果有的話,社交面的按鈕會顯示你所加她/他的那個或那些面;如果沒有的話,按鈕會是灰色的。"
+ list_not_sharing_a: "沒有,但是你可以看某人的個人檔案,來檢查她/他是否有跟你分享。如果有的話,她/他的 diaspora* 識別碼旁邊會有一個綠色的勾勾;如果沒有的話,則會是灰色圈圈。"
list_not_sharing_q: "是否有我把他們加進某一個社交面,但是他們卻沒有加我的聯絡人清單呢?"
only_sharing_a: 這些人已經把你加進他們的社交面了,但是你的社交面中還沒有他們。也就是說他們有跟你分享,但是你卻(還)沒有跟他們分享,就好像是他們在追蹤你。如果你把他們加進任何社交面,他們就會出現在那一面的清單中,而不會在"跟我分享的人"裡面了。請看上面的說明。
only_sharing_q: 聯絡人頁面中有"跟我分享的人",出現在裡面的人是誰?
@@ -535,7 +531,7 @@ zh-TW:
tags:
filter_tags_a: "目前 diaspora* 還不能直接這麼做,但是某些%{third_party_tools}可能有提供這個功能。"
filter_tags_q: "要怎樣在我的流水帳過濾(排除)掉某些標籤?"
- followed_tags_a: "搜尋一個標籤之後,你可以在標籤專頁的上方按\"追蹤\"按鈕來追蹤它。這樣一來,該標籤就會出現在左手邊追蹤中標籤的選單裡面。點任何一個你追蹤中的標籤會帶你到該標籤的專頁,讓你看到有該標籤的最新貼文。如果是點 #追蹤中的標籤 看到的會是你追蹤的所有標籤的流水帳。"
+ followed_tags_a: "搜尋一個標籤之後,你可以在標籤專頁的上方按\"追蹤\"按鈕來追蹤它。這樣一來,該標籤就會出現在左手邊追蹤中標籤的選單裡面。點任何一個你追蹤中的標籤會帶你到該標籤的專頁,讓你看到有該標籤的最新貼文。如果是點 #追蹤中的標籤 看到的會是你追蹤的所有標籤的流水帳。你的主要流水帳也會有包含該標籤的貼文。"
followed_tags_q: "什麼是\"#追蹤中的標籤\"?要怎麼追蹤一個標籤?"
people_tag_page_a: "是那些在他們的公開檔案放該標籤的人。"
people_tag_page_q: "標籤專頁左手邊列出來的人是誰?"
@@ -651,7 +647,8 @@ zh-TW:
mark_all_shown_as_read: "把目前顯示的都標示成讀過了"
mark_read: "標示為看過了"
mark_unread: "標示為沒看過"
- mentioned: "被提到了"
+ mentioned: "在貼文中被提到了"
+ mentioned_in_comment: "被貼文意見提到了"
no_notifications: "目前還沒有任何通知。"
notifications: "通知"
reshared: "被轉貼"
@@ -665,11 +662,15 @@ zh-TW:
other: "%{actors} 稱讚了你刪掉的貼文。"
zero: "%{actors} 稱讚了你刪掉的貼文。"
mentioned:
- other: "%{actors} 在貼文%{post_link}中提到了你"
+ other: "%{actors} 在貼文%{post_link}中提到了你。"
zero: "%{actors} 在貼文%{post_link}中提到了你"
mentioned_deleted:
other: "%{actors} 在已刪掉的貼文中提到了你。"
zero: "%{actors} 在已刪掉的貼文中提到了你。"
+ mentioned_in_comment:
+ other: "%{actors} 在貼文%{post_link}的<a href='%{comment_path}'>意見</a>中提到了你。"
+ mentioned_in_comment_deleted:
+ other: "%{actors} 在已刪掉的貼文中提到了你。"
private_message:
other: "%{actors} 送訊息給你。"
zero: "%{actors} 送訊息給你。"
@@ -754,7 +755,7 @@ zh-TW:
message: |-
你好!
- %{diaspora_id} 邀請你加入 diaspora* 囉!
+ %{user} 邀請你加入 diaspora* 囉!
請按這個連結來開始使用吧:
@@ -762,6 +763,7 @@ zh-TW:
如果你已經有 diaspora* 帳號的話,可以直接把 %{diaspora_id} 加到你的聯絡人喔。
+
祝順利!
diaspora* 電郵機器人
@@ -778,6 +780,9 @@ zh-TW:
mentioned:
limited_post: "你在一篇設限的貼文中被提到了。"
subject: "%{name} 在 diaspora* 提到了你"
+ mentioned_in_comment:
+ limited_post: "你在一篇設限貼文的意見中被提到了。"
+ reply: "回或看這次對話 >"
private_message:
reply_to_or_view: "回或看這次對話 >"
subject: "你有一則新的私人訊息。"
@@ -1133,6 +1138,7 @@ zh-TW:
last_exported_at: "(最後一次是在 %{timestamp} 更新)"
liked: "有人稱讚你的貼文"
mentioned: "有貼文提到了你"
+ mentioned_in_comment: "你在一則貼文的意見中被提到了"
new_password: "新的密碼"
private_message: "收到私人訊息"
receive_email_notifications: "接收電子郵件通知的時機:"
diff --git a/config/locales/javascript/javascript.da.yml b/config/locales/javascript/javascript.da.yml
index 32cc3a344..5b093deb9 100644
--- a/config/locales/javascript/javascript.da.yml
+++ b/config/locales/javascript/javascript.da.yml
@@ -241,6 +241,7 @@ da:
reshares:
post: "Videredel <%= name %>s indlæg?"
successful: "Indlægget er blevet videredelt!"
+ show_all: "Vis alle"
show_more: "Vis mere"
stream:
comment: "Kommenter"
diff --git a/config/locales/javascript/javascript.de.yml b/config/locales/javascript/javascript.de.yml
index 15b45970c..1fc156df4 100644
--- a/config/locales/javascript/javascript.de.yml
+++ b/config/locales/javascript/javascript.de.yml
@@ -242,6 +242,7 @@ de:
reshares:
post: "<%= name %>s Beitrag weitersagen?"
successful: "Der Beitrag wurde erfolgreich weitergesagt!"
+ show_all: "Alle anzeigen"
show_more: "Mehr zeigen"
stream:
comment: "Kommentieren"
@@ -260,11 +261,8 @@ de:
hide_nsfw_posts: "#nsfw-Beiträge verstecken"
like: "Gefällt mir"
likes:
- few: "<%= count %> Personen gefällt das"
- many: "<%= count %> Personen gefällt das"
one: " Einer Person gefällt das"
other: "<%= count %> Personen gefällt das"
- two: "<%= count %> Personen gefällt das"
zero: "Niemandem gefällt das"
limited: "Begrenzt"
more_comments:
diff --git a/config/locales/javascript/javascript.de_formal.yml b/config/locales/javascript/javascript.de_formal.yml
index f73704580..7d68220c5 100644
--- a/config/locales/javascript/javascript.de_formal.yml
+++ b/config/locales/javascript/javascript.de_formal.yml
@@ -129,7 +129,7 @@ de_formal:
help: "Hilfe"
home: "Startseite"
log_out: "Abmelden"
- mark_all_as_read: "Markiere alle als gelesen"
+ mark_all_as_read: "Alle als gelesen markieren"
moderator: "Moderator"
notifications: "Benachrichtigungen"
profile: "Profil"
@@ -241,6 +241,7 @@ de_formal:
reshares:
post: "<%= name %>s Beitrag weitersagen?"
successful: "Der Beitrag wurde erfolgreich weitergesagt!"
+ show_all: "Alle anzeigen"
show_more: "Mehr zeigen"
stream:
comment: "Kommentieren"
diff --git a/config/locales/javascript/javascript.en.yml b/config/locales/javascript/javascript.en.yml
index 7c5071762..8f4ed6953 100644
--- a/config/locales/javascript/javascript.en.yml
+++ b/config/locales/javascript/javascript.en.yml
@@ -28,6 +28,7 @@ en:
comma: ","
edit: "Edit"
no_results: "No results found"
+ show_all: "Show all"
admins:
dashboard:
diff --git a/config/locales/javascript/javascript.es.yml b/config/locales/javascript/javascript.es.yml
index 6bb1a8b29..dbe3838f1 100644
--- a/config/locales/javascript/javascript.es.yml
+++ b/config/locales/javascript/javascript.es.yml
@@ -97,6 +97,8 @@ es:
confirm_unload: "Por favor, confirma que quieres abandonar esta página. Los datos que no hayas introducido, no serán guardados."
contacts:
add_contact: "Añadir contacto"
+ aspect_chat_is_enabled: "Los contactos de este \"aspecto\" pueden chatear contigo."
+ aspect_chat_is_not_enabled: "Los contactos de este \"aspecto\" no pueden chatear contigo."
aspect_list_is_not_visible: "Los contactos de este aspecto no pueden verse entre ellos."
aspect_list_is_visible: "Los contactos de este aspecto pueden verse entre ellos."
error_add: "No se pudo añadir a <%= name %> al aspecto :("
@@ -104,11 +106,15 @@ es:
remove_contact: "Eliminar contacto"
search_no_results: "No se encontraron contactos"
conversation:
+ create:
+ no_recipient: "¡Eh, primero tienes que agregar un destinatario!"
new:
no_contacts: "Necesitas añadir algún contacto antes de empezar una conversación."
create: "Crear"
delete: "Eliminar"
edit: "Editar"
+ errors:
+ connection: "No ha sido posible conectarse al servidor."
failed_to_post_message: "¡Error al publicar el mensaje!"
failed_to_remove: "¡Se produjo un error al eliminar la entrada!"
getting_started:
@@ -146,6 +152,9 @@ es:
notifications:
mark_read: "Marcar como leído"
mark_unread: "Marcar como no leído"
+ new_notifications:
+ one: "Tienes <%= count %> notificación sin leer."
+ other: "Tienes <%= count %> notificaciones sin leer."
people:
edit_my_profile: "Editar mi perfil"
helper:
@@ -233,6 +242,7 @@ es:
reshares:
post: "¿Compartir la publicación de <%= name %>?"
successful: "¡Publicación compartida con éxito!"
+ show_all: "Mostrar todo"
show_more: "mostrar más"
stream:
comment: "Comentar"
@@ -289,6 +299,7 @@ es:
hour: "1 hora aproximadamente"
hours:
other: "%d horas aproximadamente"
+ inPast: "próximamente"
minute: "1 minuto aproximadamente"
minutes:
other: "%d minutos"
diff --git a/config/locales/javascript/javascript.fr.yml b/config/locales/javascript/javascript.fr.yml
index 4e0a6856f..063700e8d 100644
--- a/config/locales/javascript/javascript.fr.yml
+++ b/config/locales/javascript/javascript.fr.yml
@@ -243,13 +243,14 @@ fr:
reshares:
post: "Repartager le message de <%= name %> ?"
successful: "Le message a été repartagé !"
+ show_all: "Afficher tout"
show_more: "Voir plus"
stream:
comment: "Commenter"
comments:
- one: "<%= count %> commantaire"
- other: "<%= count %> commantaires"
- zero: "<%= count %> commantaire"
+ one: "<%= count %> commentaire"
+ other: "<%= count %> commentaires"
+ zero: "<%= count %> commentaire"
disable_post_notifications: "Désactiver les notifications pour ce message"
enable_post_notifications: "Activer les notifications pour ce message"
follow: "Suivre"
diff --git a/config/locales/javascript/javascript.hu.yml b/config/locales/javascript/javascript.hu.yml
index 4c3254345..7d7121ad5 100644
--- a/config/locales/javascript/javascript.hu.yml
+++ b/config/locales/javascript/javascript.hu.yml
@@ -159,6 +159,7 @@ hu:
other: "Mutasd a többi <%= count %> hozzászólást"
two: "Mutasd a többi <%= count %> hozzászólást"
zero: "Mutasd a többi <%= count %> hozzászólást"
+ no_posts_yet: "Még nincs itt megjeleníthető bejegyzés."
original_post_deleted: "Eredeti bejegyzés törölve a szerzője által."
public: "Nyilvános"
reshare: "Megosztás"
diff --git a/config/locales/javascript/javascript.ja.yml b/config/locales/javascript/javascript.ja.yml
index bfa725878..77c302d88 100644
--- a/config/locales/javascript/javascript.ja.yml
+++ b/config/locales/javascript/javascript.ja.yml
@@ -233,6 +233,7 @@ ja:
reshares:
post: "<%= name %>さんの投稿をリシェアしますか?"
successful: "投稿は正常にリシェアされました!"
+ show_all: "すべて表示"
show_more: "さらに表示する"
stream:
comment: "コメント"
diff --git a/config/locales/javascript/javascript.oc.yml b/config/locales/javascript/javascript.oc.yml
index 922b8cffd..19730c5e3 100644
--- a/config/locales/javascript/javascript.oc.yml
+++ b/config/locales/javascript/javascript.oc.yml
@@ -54,7 +54,7 @@ oc:
compare_versions: "La darrièra version de diaspora* es <%= latestVersion %>, vòstre pod vira jos la version <%= podVersion %>."
error: "Impossible de determinar la darrièra version de diaspora*."
outdated: "Vòstre pod es pas a jorn."
- up_to_date: "Vòstre pod es a jorn !"
+ up_to_date: "Vòstre pod es a jorn !"
and: "e"
aspect_dropdown:
add_to_aspect: "Apondre un contacte"
@@ -86,7 +86,7 @@ oc:
bookmarklet:
post_something: "Publicar sus diaspora*"
post_submit: "Messatge en cors de publicacion..."
- post_success: "Publicat ! Tampadura de la fenèstra popup..."
+ post_success: "Publicat ! Tampadura de la fenèstra popup…"
cancel: "Anullar"
comma: ","
comments:
@@ -107,7 +107,7 @@ oc:
search_no_results: "Cap de contact pas trobat"
conversation:
create:
- no_recipient: "Ei, vos cal apondre un destinari d'en primièr !"
+ no_recipient: "Ei, vos cal apondre un destinari d'en primièr !"
new:
no_contacts: "Vos cal apondre de contactes abans de poder aviar una conversacion."
create: "Crear"
@@ -115,12 +115,12 @@ oc:
edit: "Editar"
errors:
connection: "Impossible de se conectar al servidor."
- failed_to_post_message: "Impossible de partejar lo messatge !"
+ failed_to_post_message: "Impossible de partejar lo messatge !"
failed_to_remove: "L'entrada a pas pogut èsser suprimida"
getting_started:
alright_ill_wait: "Bon, vau esperar."
hey: "Adiu, <%= name %>"
- no_tags: "È, seguissètz pas cap de tag ! Contunar malgrat tot ?"
+ no_tags: "È, seguissètz pas cap d’etiquetas ! Contunhar malgrat tot ?"
preparing_your_stream: "Preparacion de vòstre flux personalizat..."
header:
admin: "Administracion"
@@ -170,7 +170,7 @@ oc:
empty: "{file} es void, mercé de seleccionar d'autres fichièrs."
error: "Un problèma s'es produit pendent lo mandadís del fichièr <%= file %>"
invalid_ext: "{file} a una extension invalida, Solas {extensions} son permesas."
- looking_good: "Impressionant, avètz un super estil !"
+ looking_good: "Impressionant, avètz un super estil !"
size_error: "{file} es tròp gròs, la talha maximala es de {sizeLimit}."
upload_photos: "Mandar de fotografias"
poll:
@@ -198,7 +198,7 @@ oc:
location: "Localizacion"
photos: "Fòtos"
posts: "Publicacions"
- you_have_no_tags: "Avètz pas d'etiquetas !"
+ you_have_no_tags: "Avètz pas d'etiquetas !"
publisher:
add_option: "Apondre una responsa"
markdown_editor:
@@ -229,8 +229,8 @@ oc:
quote: "Inserir una citacion"
write: "Modificar lo messatge"
write: "Escriure"
- mention_success: "Es ben estat mencionat : <%= names %>"
- near_from: "Postat a : <%= location %>"
+ mention_success: "Es ben estat mencionat : <%= names %>"
+ near_from: "Postat a : <%= location %>"
option: "Responsa"
question: "Question"
remove_post: "Suprimir aqueste messatge ?"
@@ -243,7 +243,8 @@ oc:
exists: "Lo senhalament existís ja"
reshares:
post: "Repartejar lo messatge de <%= name %> ?"
- successful: "Lo messatge es estat repartejat !"
+ successful: "Lo messatge es estat repartejat !"
+ show_all: "Afichar tot"
show_more: "N'afichar mai"
stream:
comment: "Comentar"
diff --git a/config/locales/javascript/javascript.pl.yml b/config/locales/javascript/javascript.pl.yml
index e695f4a17..bdf4571ce 100644
--- a/config/locales/javascript/javascript.pl.yml
+++ b/config/locales/javascript/javascript.pl.yml
@@ -108,7 +108,7 @@ pl:
getting_started:
alright_ill_wait: "Dobrze, poczekam."
hey: "Hej, <%= name %>!"
- no_tags: "Hej, nie obserwujesz żadnych znaczników! Kontynuować mimo to?"
+ no_tags: "Hej, nie obserwujesz żadnych tagów! Kontynuować mimo to?"
preparing_your_stream: "Przygotowanie spersonalizowanego strumienia..."
header:
admin: "Administrator"
@@ -225,6 +225,7 @@ pl:
reshares:
post: "Przesłać dalej wpis użytkownika <%= name %>?"
successful: "Wpis został pomyślnie przesłany dalej!"
+ show_all: "Pokaż wszystkie"
show_more: "wyświetl więcej"
stream:
comment: "Skomentuj"
@@ -232,9 +233,9 @@ pl:
enable_post_notifications: "Włącz powiadomienia do tego wpisu"
follow: "Obserwuj"
followed_tag:
- add_a_tag: "Dodaj znacznik"
+ add_a_tag: "Dodaj tag"
follow: "Obserwuj"
- title: "#Obserwowane znaczniki"
+ title: "#Obserwowane tagi"
hide: "Ukryj"
hide_nsfw_posts: "Ukryj wpisy #nsfw"
like: "Lubię to!"
@@ -279,16 +280,25 @@ pl:
timeago:
day: "dzień"
days:
- other: "%d dni"
+ few: "%d dni temu"
+ many: "%d dni temu"
+ one: "1 dzień temu"
+ other: "%d dni temu"
hour: "około godziny"
hours:
- other: "około %d godzin"
+ few: "około %d godziny"
+ many: "około %d godzin"
+ one: "około godzinę"
+ other: "około %d godziny"
inPast: "w każdej chwili"
minute: "około minuty"
minutes:
other: "%d minut"
month: "około miesiąca"
months:
+ few: "%d miesiące"
+ many: "%d miesięcy"
+ one: "miesiąc"
other: "%d miesięcy"
prefixAgo: ""
prefixFromNow: ""
diff --git a/config/locales/javascript/javascript.pt-BR.yml b/config/locales/javascript/javascript.pt-BR.yml
index fac60e12a..74b0d55f7 100644
--- a/config/locales/javascript/javascript.pt-BR.yml
+++ b/config/locales/javascript/javascript.pt-BR.yml
@@ -243,6 +243,7 @@ pt-BR:
reshares:
post: "Recompartilhar a publicação de <%= name %>?"
successful: "A publicação foi recompartilhada com sucesso!"
+ show_all: "Mostrar tudo"
show_more: "Mostrar mais"
stream:
comment: "Comentar"
diff --git a/config/locales/javascript/javascript.sc.yml b/config/locales/javascript/javascript.sc.yml
index 1bfdf63d6..c174b2888 100644
--- a/config/locales/javascript/javascript.sc.yml
+++ b/config/locales/javascript/javascript.sc.yml
@@ -6,12 +6,15 @@
sc:
javascripts:
+ aspects:
+ make_aspect_list_visible: "Permìtere a sos cuntatos in custa cara de si bìdere unu cun s'àteru?"
header:
moderator: "Moderatore"
photo_uploader:
upload_photos: "Càrriga fotografias"
publisher:
mention_success: "Etichetados curretamente: <%= names %>"
+ show_all: "Ammustra totu"
timeago:
prefixAgo: ""
prefixFromNow: ""
diff --git a/config/locales/javascript/javascript.uk.yml b/config/locales/javascript/javascript.uk.yml
index 60385bbcc..f1deb87d2 100644
--- a/config/locales/javascript/javascript.uk.yml
+++ b/config/locales/javascript/javascript.uk.yml
@@ -130,7 +130,7 @@ uk:
getting_started:
alright_ill_wait: "Добре, я почекаю."
hey: "Привіт, <%= name %>!"
- no_tags: "Ви не стежите ні за однією міткою! Все одно продовжити?"
+ no_tags: "Ви не стежите за жодною міткою! Все одно продовжити?"
preparing_your_stream: "Підготовка вашого особистого потоку..."
header:
admin: "Керування"
@@ -259,6 +259,7 @@ uk:
reshares:
post: "Поширити запис <%= name %>?"
successful: "Ви успішно поділилися записом!"
+ show_all: "Показати все"
show_more: "показати більше"
stream:
comment: "Коментувати"
diff --git a/config/locales/javascript/javascript.zh-TW.yml b/config/locales/javascript/javascript.zh-TW.yml
index 29053b465..80c037f24 100644
--- a/config/locales/javascript/javascript.zh-TW.yml
+++ b/config/locales/javascript/javascript.zh-TW.yml
@@ -234,6 +234,7 @@ zh-TW:
reshares:
post: "要轉貼 <%= name %> 的貼文嗎?"
successful: "貼文轉貼成功!"
+ show_all: "看全部"
show_more: "顯示更多"
stream:
comment: "留言"
diff --git a/config/logging.rb b/config/logging.rb
index 57cf39b0a..230ea8117 100644
--- a/config/logging.rb
+++ b/config/logging.rb
@@ -85,6 +85,7 @@ Logging::Rails.configure do |config|
Logging.logger.root.level = config.log_level
# log-levels from the diaspora.yml for SQL and federation debug-logging
+ Logging.logger[ActionView::Base].level = Rails.env.development? ? :debug : :warn
Logging.logger[ActiveRecord::Base].level = AppConfig.environment.logging.debug.sql? ? :debug : :info
Logging.logger[DiasporaFederation::Salmon::MagicEnvelope].level =
AppConfig.environment.logging.debug.federation? ? :debug : :info
@@ -103,3 +104,10 @@ Logging::Rails.configure do |config|
end
end
end
+
+# Include LoggerSilence from ActiveSupport. This is needed to silent assets
+# requests with `config.assets.quiet`, because the default silence method of
+# the logging gem is no-op. See: https://github.com/TwP/logging/issues/11
+Logging::Logger.send :alias_method, :local_level, :level
+Logging::Logger.send :alias_method, :local_level=, :level=
+Logging::Logger.send :include, LoggerSilence
diff --git a/config/routes.rb b/config/routes.rb
index b75883051..82d9afc91 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -6,7 +6,8 @@ require "sidekiq/web"
require "sidekiq/cron/web"
Sidekiq::Web.set :sessions, false # disable rack session cookie
-Diaspora::Application.routes.draw do
+Rails.application.routes.draw do
+ # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
resources :report, except: %i(edit new show)
@@ -28,7 +29,7 @@ Diaspora::Application.routes.draw do
resources :posts, only: %i(show destroy) do
member do
- get :interactions
+ get :mentionable
end
resource :participation, only: %i(create destroy)
@@ -229,6 +230,5 @@ Diaspora::Application.routes.draw do
end
end
- get ".well-known/webfinger", to: "api/openid_connect/discovery#webfinger"
get ".well-known/openid-configuration", to: "api/openid_connect/discovery#configuration"
end
diff --git a/config/spring.rb b/config/spring.rb
new file mode 100644
index 000000000..0598e88c3
--- /dev/null
+++ b/config/spring.rb
@@ -0,0 +1,6 @@
+%w[
+ .ruby-version
+ .rbenv-vars
+ tmp/restart.txt
+ tmp/caching-dev.txt
+].each {|path| Spring.watch(path) }
diff --git a/db/migrate/0000_create_schema.rb b/db/migrate/0000_create_schema.rb
index 97fcc3da6..a6393fd40 100644
--- a/db/migrate/0000_create_schema.rb
+++ b/db/migrate/0000_create_schema.rb
@@ -1,488 +1,492 @@
-class CreateSchema < ActiveRecord::Migration
- create_table "account_deletions", :force => true do |t|
- t.string "diaspora_handle"
- t.integer "person_id"
- end
-
- create_table "aspect_memberships", :force => true do |t|
- t.integer "aspect_id", :null => false
- t.integer "contact_id", :null => false
- t.datetime "created_at", :null => false
- t.datetime "updated_at", :null => false
- end
-
- add_index "aspect_memberships", ["aspect_id", "contact_id"], :name => "index_aspect_memberships_on_aspect_id_and_contact_id", :unique => true
- add_index "aspect_memberships", ["aspect_id"], :name => "index_aspect_memberships_on_aspect_id"
- add_index "aspect_memberships", ["contact_id"], :name => "index_aspect_memberships_on_contact_id"
-
- create_table "aspect_visibilities", :force => true do |t|
- t.integer "shareable_id", :null => false
- t.integer "aspect_id", :null => false
- t.datetime "created_at", :null => false
- t.datetime "updated_at", :null => false
- t.string "shareable_type", :default => "Post", :null => false
- end
-
- add_index "aspect_visibilities", ["aspect_id"], :name => "index_aspect_visibilities_on_aspect_id"
- add_index 'aspect_visibilities', ["shareable_id", "shareable_type", "aspect_id"], :name => 'shareable_and_aspect_id', length: {"shareable_type"=>189}, :using => :btree
- add_index 'aspect_visibilities', ["shareable_id", "shareable_type"], :name => 'index_aspect_visibilities_on_shareable_id_and_shareable_type', length: {"shareable_type"=>190}, :using => :btree
-
- create_table "aspects", :force => true do |t|
- t.string "name", :null => false
- t.integer "user_id", :null => false
- t.datetime "created_at", :null => false
- t.datetime "updated_at", :null => false
- t.boolean "contacts_visible", :default => true, :null => false
- t.integer "order_id"
- end
-
- add_index "aspects", ["user_id", "contacts_visible"], :name => "index_aspects_on_user_id_and_contacts_visible"
- add_index "aspects", ["user_id"], :name => "index_aspects_on_user_id"
-
- create_table "blocks", :force => true do |t|
- t.integer "user_id"
- t.integer "person_id"
- end
-
- create_table "comments", :force => true do |t|
- t.text "text", :null => false
- t.integer "commentable_id", :null => false
- t.integer "author_id", :null => false
- t.string "guid", :null => false
- t.text "author_signature"
- t.text "parent_author_signature"
- t.datetime "created_at", :null => false
- t.datetime "updated_at", :null => false
- t.integer "likes_count", :default => 0, :null => false
- t.string "commentable_type", :limit => 60, :default => "Post", :null => false
- end
-
- add_index "comments", ["author_id"], :name => "index_comments_on_person_id"
- add_index "comments", ["commentable_id", "commentable_type"], :name => "index_comments_on_commentable_id_and_commentable_type"
- add_index 'comments', ["guid"], :name => 'index_comments_on_guid', length: {"guid"=>191}, :using => :btree, :unique => true
-
- create_table "contacts", :force => true do |t|
- t.integer "user_id", :null => false
- t.integer "person_id", :null => false
- t.datetime "created_at", :null => false
- t.datetime "updated_at", :null => false
- t.boolean "sharing", :default => false, :null => false
- t.boolean "receiving", :default => false, :null => false
- end
-
- add_index "contacts", ["person_id"], :name => "index_contacts_on_person_id"
- add_index "contacts", ["user_id", "person_id"], :name => "index_contacts_on_user_id_and_person_id", :unique => true
-
- create_table "conversation_visibilities", :force => true do |t|
- t.integer "conversation_id", :null => false
- t.integer "person_id", :null => false
- t.integer "unread", :default => 0, :null => false
- t.datetime "created_at", :null => false
- t.datetime "updated_at", :null => false
- end
-
- add_index "conversation_visibilities", ["conversation_id", "person_id"], :name => "index_conversation_visibilities_usefully", :unique => true
- add_index "conversation_visibilities", ["conversation_id"], :name => "index_conversation_visibilities_on_conversation_id"
- add_index "conversation_visibilities", ["person_id"], :name => "index_conversation_visibilities_on_person_id"
-
- create_table "conversations", :force => true do |t|
- t.string "subject"
- t.string "guid", :null => false
- t.integer "author_id", :null => false
- t.datetime "created_at", :null => false
- t.datetime "updated_at", :null => false
- end
-
- add_index "conversations", ["author_id"], :name => "conversations_author_id_fk"
-
- create_table "invitation_codes", :force => true do |t|
- t.string "token"
- t.integer "user_id"
- t.integer "count"
- t.datetime "created_at", :null => false
- t.datetime "updated_at", :null => false
- end
-
- create_table "invitations", :force => true do |t|
- t.text "message"
- t.integer "sender_id"
- t.integer "recipient_id"
- t.integer "aspect_id"
- t.datetime "created_at", :null => false
- t.datetime "updated_at", :null => false
- t.string "service"
- t.string "identifier"
- t.boolean "admin", :default => false
- t.string "language", :default => "en"
- end
-
- add_index "invitations", ["aspect_id"], :name => "index_invitations_on_aspect_id"
- add_index "invitations", ["recipient_id"], :name => "index_invitations_on_recipient_id"
- add_index "invitations", ["sender_id"], :name => "index_invitations_on_sender_id"
-
- create_table "likes", :force => true do |t|
- t.boolean "positive", :default => true
- t.integer "target_id"
- t.integer "author_id"
- t.string "guid"
- t.text "author_signature"
- t.text "parent_author_signature"
- t.datetime "created_at", :null => false
- t.datetime "updated_at", :null => false
- t.string "target_type", :limit => 60, :null => false
- end
-
- add_index "likes", ["author_id"], :name => "likes_author_id_fk"
- add_index 'likes', ["guid"], :name => 'index_likes_on_guid', length: {"guid"=>191}, :using => :btree, :unique => true
- add_index "likes", ["target_id", "author_id", "target_type"], :name => "index_likes_on_target_id_and_author_id_and_target_type", :unique => true
- add_index "likes", ["target_id"], :name => "index_likes_on_post_id"
-
- create_table "locations", :force => true do |t|
- t.string "address"
- t.string "lat"
- t.string "lng"
- t.integer "status_message_id"
- t.datetime "created_at", :null => false
- t.datetime "updated_at", :null => false
- end
-
- create_table "mentions", :force => true do |t|
- t.integer "post_id", :null => false
- t.integer "person_id", :null => false
- end
-
- add_index "mentions", ["person_id", "post_id"], :name => "index_mentions_on_person_id_and_post_id", :unique => true
- add_index "mentions", ["person_id"], :name => "index_mentions_on_person_id"
- add_index "mentions", ["post_id"], :name => "index_mentions_on_post_id"
-
- create_table "messages", :force => true do |t|
- t.integer "conversation_id", :null => false
- t.integer "author_id", :null => false
- t.string "guid", :null => false
- t.text "text", :null => false
- t.datetime "created_at", :null => false
- t.datetime "updated_at", :null => false
- t.text "author_signature"
- t.text "parent_author_signature"
- end
-
- add_index "messages", ["author_id"], :name => "index_messages_on_author_id"
- add_index "messages", ["conversation_id"], :name => "messages_conversation_id_fk"
-
- create_table "notification_actors", :force => true do |t|
- t.integer "notification_id"
- t.integer "person_id"
- t.datetime "created_at", :null => false
- t.datetime "updated_at", :null => false
- end
-
- add_index "notification_actors", ["notification_id", "person_id"], :name => "index_notification_actors_on_notification_id_and_person_id", :unique => true
- add_index "notification_actors", ["notification_id"], :name => "index_notification_actors_on_notification_id"
- add_index "notification_actors", ["person_id"], :name => "index_notification_actors_on_person_id"
-
- create_table "notifications", :force => true do |t|
- t.string "target_type"
- t.integer "target_id"
- t.integer "recipient_id", :null => false
- t.boolean "unread", :default => true, :null => false
- t.datetime "created_at", :null => false
- t.datetime "updated_at", :null => false
- t.string "type"
- end
-
- add_index "notifications", ["recipient_id"], :name => "index_notifications_on_recipient_id"
- add_index "notifications", ["target_id"], :name => "index_notifications_on_target_id"
- add_index 'notifications', ["target_type", "target_id"], name: 'index_notifications_on_target_type_and_target_id', length: {"target_type"=>190}, using: :btree
-
- create_table "o_embed_caches", :force => true do |t|
- t.string "url", :limit => 1024, :null => false
- t.text "data", :null => false
- end
-
- add_index "o_embed_caches", ["url"], :name => "index_o_embed_caches_on_url", :length => {"url"=> 191}, using: :btree
-
- create_table "participations", :force => true do |t|
- t.string "guid"
- t.integer "target_id"
- t.string "target_type", :limit => 60, :null => false
- t.integer "author_id"
- t.text "author_signature"
- t.text "parent_author_signature"
- t.datetime "created_at", :null => false
- t.datetime "updated_at", :null => false
- end
-
- add_index 'participations', ["guid"], :name => 'index_participations_on_guid', length: {"guid"=>191}, :using => :btree
- add_index "participations", ["target_id", "target_type", "author_id"], :name => "index_participations_on_target_id_and_target_type_and_author_id"
-
- create_table "people", :force => true do |t|
- t.string "guid", :null => false
- t.text "url", :null => false
- t.string "diaspora_handle", :null => false
- t.text "serialized_public_key", :null => false
- t.integer "owner_id"
- t.datetime "created_at", :null => false
- t.datetime "updated_at", :null => false
- t.boolean "closed_account", :default => false
- t.integer "fetch_status", :default => 0
- end
-
- add_index "people", ["diaspora_handle"], :name => "index_people_on_diaspora_handle", :unique => true, :length => {"diaspora_handle" => 191}
- add_index 'people', ["guid"], :name => 'index_people_on_guid', length: {"guid"=>191}, :using => :btree, :unique => true
- add_index "people", ["owner_id"], :name => "index_people_on_owner_id", :unique => true
-
- create_table "photos", :force => true do |t|
- t.integer "tmp_old_id"
- t.integer "author_id", :null => false
- t.boolean "public", :default => false, :null => false
- t.string "diaspora_handle"
- t.string "guid", :null => false
- t.boolean "pending", :default => false, :null => false
- t.text "text"
- t.text "remote_photo_path"
- t.string "remote_photo_name"
- t.string "random_string"
- t.string "processed_image"
- t.datetime "created_at"
- t.datetime "updated_at"
- t.string "unprocessed_image"
- t.string "status_message_guid"
- t.integer "comments_count"
- t.integer "height"
- t.integer "width"
- end
-
- add_index 'photos', ["status_message_guid"], :name => 'index_photos_on_status_message_guid', length: {"status_message_guid"=>191}, :using => :btree
-
- create_table "pods", :force => true do |t|
- t.string "host"
- t.boolean "ssl"
- t.datetime "created_at", :null => false
- t.datetime "updated_at", :null => false
- end
-
- create_table "posts", :force => true do |t|
- t.integer "author_id", :null => false
- t.boolean "public", :default => false, :null => false
- t.string "diaspora_handle"
- t.string "guid", :null => false
- t.boolean "pending", :default => false, :null => false
- t.string "type", :limit => 40, :null => false
- t.text "text"
- t.text "remote_photo_path"
- t.string "remote_photo_name"
- t.string "random_string"
- t.string "processed_image"
- t.datetime "created_at", :null => false
- t.datetime "updated_at", :null => false
- t.string "unprocessed_image"
- t.string "object_url"
- t.string "image_url"
- t.integer "image_height"
- t.integer "image_width"
- t.string "provider_display_name"
- t.string "actor_url"
- t.string "objectId"
- t.string "root_guid", :limit => 30
- t.string "status_message_guid"
- t.integer "likes_count", :default => 0
- t.integer "comments_count", :default => 0
- t.integer "o_embed_cache_id"
- t.integer "reshares_count", :default => 0
- t.datetime "interacted_at"
- t.string "frame_name"
- t.boolean "favorite", :default => false
- end
-
- add_index 'posts', ["author_id", "root_guid"], :name => 'index_posts_on_author_id_and_root_guid', length: {"root_guid"=>30}, :using => :btree, :unique => true
- add_index "posts", ["author_id"], :name => "index_posts_on_person_id"
- add_index 'posts', ["guid"], :name => 'index_posts_on_guid', length: {"guid"=>191}, :using => :btree, :unique => true
- add_index "posts", ["id", "type", "created_at"], :name => "index_posts_on_id_and_type_and_created_at"
- add_index 'posts', ["root_guid"], :name => 'index_posts_on_root_guid', length: {"root_guid"=>30}
- add_index 'posts', ["status_message_guid", "pending"], :name => 'index_posts_on_status_message_guid_and_pending', length: {"status_message_guid"=>190}, :using => :btree
- add_index 'posts', ["status_message_guid"], :name => 'index_posts_on_status_message_guid', length: {"status_message_guid"=>191}, :using => :btree
- add_index "posts", ["type", "pending", "id"], :name => "index_posts_on_type_and_pending_and_id"
-
- create_table "profiles", :force => true do |t|
- t.string "diaspora_handle"
- t.string "first_name", :limit => 127
- t.string "last_name", :limit => 127
- t.string "image_url"
- t.string "image_url_small"
- t.string "image_url_medium"
- t.date "birthday"
- t.string "gender"
- t.text "bio"
- t.boolean "searchable", :default => true, :null => false
- t.integer "person_id", :null => false
- t.datetime "created_at", :null => false
- t.datetime "updated_at", :null => false
- t.string "location"
- t.string "full_name", :limit => 70
- t.boolean "nsfw", :default => false
- end
-
- add_index "profiles", ["full_name", "searchable"], :name => "index_profiles_on_full_name_and_searchable"
- add_index "profiles", ["full_name"], :name => "index_profiles_on_full_name"
- add_index "profiles", ["person_id"], :name => "index_profiles_on_person_id"
-
- create_table "rails_admin_histories", :force => true do |t|
- t.text "message"
- t.string "username"
- t.integer "item"
- t.string "table"
- t.integer "month", :limit => 2
- t.integer "year", :limit => 8
- t.datetime "created_at", :null => false
- t.datetime "updated_at", :null => false
- end
-
- add_index "rails_admin_histories", ["item", "table", "month", "year"], :name => "index_rails_admin_histories", :length => {"table" => 188}
-
- create_table "roles", :force => true do |t|
- t.integer "person_id"
- t.string "name"
- t.datetime "created_at", :null => false
- t.datetime "updated_at", :null => false
- end
-
- create_table "services", :force => true do |t|
- t.string "type", :limit => 127, :null => false
- t.integer "user_id", :null => false
- t.string "uid", :limit => 127
- t.string "access_token"
- t.string "access_secret"
- t.string "nickname"
- t.datetime "created_at", :null => false
- t.datetime "updated_at", :null => false
- end
-
- add_index 'services', ["type", "uid"], :name => 'index_services_on_type_and_uid', length: {"type"=>64, "uid"=>127}, :using => :btree
- add_index "services", ["user_id"], :name => "index_services_on_user_id"
-
- create_table "share_visibilities", :force => true do |t|
- t.integer "shareable_id", :null => false
- t.datetime "created_at", :null => false
- t.datetime "updated_at", :null => false
- t.boolean "hidden", :default => false, :null => false
- t.integer "contact_id", :null => false
- t.string "shareable_type", :limit => 60, :default => "Post", :null => false
- end
-
- add_index "share_visibilities", ["contact_id"], :name => "index_post_visibilities_on_contact_id"
- add_index "share_visibilities", ["shareable_id", "shareable_type", "contact_id"], :name => "shareable_and_contact_id"
- add_index "share_visibilities", ["shareable_id", "shareable_type", "hidden", "contact_id"], :name => "shareable_and_hidden_and_contact_id"
- add_index "share_visibilities", ["shareable_id"], :name => "index_post_visibilities_on_post_id"
-
- create_table "tag_followings", :force => true do |t|
- t.integer "tag_id", :null => false
- t.integer "user_id", :null => false
- t.datetime "created_at", :null => false
- t.datetime "updated_at", :null => false
- end
-
- add_index "tag_followings", ["tag_id", "user_id"], :name => "index_tag_followings_on_tag_id_and_user_id", :unique => true
- add_index "tag_followings", ["tag_id"], :name => "index_tag_followings_on_tag_id"
- add_index "tag_followings", ["user_id"], :name => "index_tag_followings_on_user_id"
-
- create_table "taggings", :force => true do |t|
- t.integer "tag_id"
- t.integer "taggable_id"
- t.string "taggable_type", :limit => 127
- t.integer "tagger_id"
- t.string "tagger_type", :limit => 127
- t.string "context", :limit => 127
- t.datetime "created_at"
- end
-
- add_index "taggings", ["created_at"], :name => "index_taggings_on_created_at"
- add_index "taggings", ["tag_id"], :name => "index_taggings_on_tag_id"
- add_index 'taggings', ["taggable_id", "taggable_type", "context"], :name => 'index_taggings_on_taggable_id_and_taggable_type_and_context', length: {"taggable_type"=>95, "context"=>95}, :using => :btree
- add_index "taggings", ["taggable_id", "taggable_type", "tag_id"], :name => "index_taggings_uniquely", :unique => true
-
- create_table "tags", :force => true do |t|
- t.string "name"
- end
-
- add_index "tags", ["name"], :name => "index_tags_on_name", :unique => true, :length => {"name" => 191}
-
- create_table "user_preferences", :force => true do |t|
- t.string "email_type"
- t.integer "user_id"
- t.datetime "created_at", :null => false
- t.datetime "updated_at", :null => false
- end
-
- create_table "users", :force => true do |t|
- t.string "username"
- t.text "serialized_private_key"
- t.boolean "getting_started", :default => true, :null => false
- t.boolean "disable_mail", :default => false, :null => false
- t.string "language"
- t.string "email", :default => "", :null => false
- t.string "encrypted_password", :default => "", :null => false
- t.string "invitation_token", :limit => 60
- t.datetime "invitation_sent_at"
- t.string "reset_password_token"
- t.datetime "remember_created_at"
- t.integer "sign_in_count", :default => 0
- t.datetime "current_sign_in_at"
- t.datetime "last_sign_in_at"
- t.string "current_sign_in_ip"
- t.string "last_sign_in_ip"
- t.datetime "created_at", :null => false
- t.datetime "updated_at", :null => false
- t.string "invitation_service", :limit => 127
- t.string "invitation_identifier", :limit => 127
- t.integer "invitation_limit"
- t.integer "invited_by_id"
- t.string "invited_by_type"
- t.string "authentication_token", :limit => 30
- t.string "unconfirmed_email"
- t.string "confirm_email_token", :limit => 30
- t.datetime "locked_at"
- t.boolean "show_community_spotlight_in_stream", :default => true, :null => false
- t.boolean "auto_follow_back", :default => false
- t.integer "auto_follow_back_aspect_id"
- t.text "hidden_shareables"
- t.datetime "reset_password_sent_at"
- end
-
- add_index "users", ["authentication_token"], :name => "index_users_on_authentication_token", :unique => true
- add_index "users", ["email"], :name => "index_users_on_email", length: {"email" => "191"}
- add_index 'users', ["invitation_service", "invitation_identifier"], :name => 'index_users_on_invitation_service_and_invitation_identifier', length: {"invitation_service"=>64, "invitation_identifier"=>127}, :using => :btree, :unique => true
- add_index "users", ["invitation_token"], :name => "index_users_on_invitation_token"
- add_index 'users', ["username"], :name => 'index_users_on_username', length: {"username"=>191}, :using => :btree, :unique => true
-
- add_foreign_key "aspect_memberships", "aspects", name: "aspect_memberships_aspect_id_fk", on_delete: :cascade
- add_foreign_key "aspect_memberships", "contacts", name: "aspect_memberships_contact_id_fk", on_delete: :cascade
-
- add_foreign_key "aspect_visibilities", "aspects", name: "aspect_visibilities_aspect_id_fk", on_delete: :cascade
-
- add_foreign_key "comments", "people", name: "comments_author_id_fk", column: "author_id", on_delete: :cascade
-
- add_foreign_key "contacts", "people", name: "contacts_person_id_fk", on_delete: :cascade
-
- add_foreign_key "conversation_visibilities", "conversations", name: "conversation_visibilities_conversation_id_fk", on_delete: :cascade
- add_foreign_key "conversation_visibilities", "people", name: "conversation_visibilities_person_id_fk", on_delete: :cascade
-
- add_foreign_key "conversations", "people", name: "conversations_author_id_fk", column: "author_id", on_delete: :cascade
-
- add_foreign_key "invitations", "users", name: "invitations_recipient_id_fk", column: "recipient_id", on_delete: :cascade
- add_foreign_key "invitations", "users", name: "invitations_sender_id_fk", column: "sender_id", on_delete: :cascade
-
- add_foreign_key "likes", "people", name: "likes_author_id_fk", column: "author_id", on_delete: :cascade
-
- add_foreign_key "messages", "conversations", name: "messages_conversation_id_fk", on_delete: :cascade
- add_foreign_key "messages", "people", name: "messages_author_id_fk", column: "author_id", on_delete: :cascade
-
- add_foreign_key "notification_actors", "notifications", name: "notification_actors_notification_id_fk", on_delete: :cascade
-
- add_foreign_key "posts", "people", name: "posts_author_id_fk", column: "author_id", on_delete: :cascade
-
- add_foreign_key "profiles", "people", name: "profiles_person_id_fk", on_delete: :cascade
-
- add_foreign_key "services", "users", name: "services_user_id_fk", on_delete: :cascade
-
- add_foreign_key "share_visibilities", "contacts", name: "post_visibilities_contact_id_fk", on_delete: :cascade
+class CreateSchema < ActiveRecord::Migration[4.2]
+ # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/LineLength, Layout/ExtraSpacing
+ def up
+ create_table :account_deletions do |t|
+ t.string :diaspora_handle
+ t.integer :person_id
+ end
+
+ create_table :aspect_memberships do |t|
+ t.integer :aspect_id, null: false
+ t.integer :contact_id, null: false
+ t.datetime :created_at, null: false
+ t.datetime :updated_at, null: false
+ end
+
+ add_index :aspect_memberships, %i[aspect_id contact_id], name: :index_aspect_memberships_on_aspect_id_and_contact_id, unique: true
+ add_index :aspect_memberships, [:aspect_id], name: :index_aspect_memberships_on_aspect_id
+ add_index :aspect_memberships, [:contact_id], name: :index_aspect_memberships_on_contact_id
+
+ create_table :aspect_visibilities do |t|
+ t.integer :shareable_id, null: false
+ t.integer :aspect_id, null: false
+ t.datetime :created_at, null: false
+ t.datetime :updated_at, null: false
+ t.string :shareable_type, default: "Post", null: false
+ end
+
+ add_index :aspect_visibilities, [:aspect_id], name: :index_aspect_visibilities_on_aspect_id
+ add_index :aspect_visibilities, %i[shareable_id shareable_type aspect_id], name: :shareable_and_aspect_id, length: {shareable_type: 189}, using: :btree
+ add_index :aspect_visibilities, %i[shareable_id shareable_type], name: :index_aspect_visibilities_on_shareable_id_and_shareable_type, length: {shareable_type: 190}, using: :btree
+
+ create_table :aspects do |t|
+ t.string :name, null: false
+ t.integer :user_id, null: false
+ t.datetime :created_at, null: false
+ t.datetime :updated_at, null: false
+ t.boolean :contacts_visible, default: true, null: false
+ t.integer :order_id
+ end
+
+ add_index :aspects, %i[user_id contacts_visible], name: :index_aspects_on_user_id_and_contacts_visible
+ add_index :aspects, [:user_id], name: :index_aspects_on_user_id
+
+ create_table :blocks do |t|
+ t.integer :user_id
+ t.integer :person_id
+ end
+
+ create_table :comments do |t|
+ t.text :text, null: false
+ t.integer :commentable_id, null: false
+ t.integer :author_id, null: false
+ t.string :guid, null: false
+ t.text :author_signature
+ t.text :parent_author_signature
+ t.datetime :created_at, null: false
+ t.datetime :updated_at, null: false
+ t.integer :likes_count, default: 0, null: false
+ t.string :commentable_type, limit: 60, default: "Post", null: false
+ end
+
+ add_index :comments, [:author_id], name: :index_comments_on_person_id
+ add_index :comments, %i[commentable_id commentable_type], name: :index_comments_on_commentable_id_and_commentable_type
+ add_index :comments, [:guid], name: :index_comments_on_guid, length: {guid: 191}, using: :btree, unique: true
+
+ create_table :contacts do |t|
+ t.integer :user_id, null: false
+ t.integer :person_id, null: false
+ t.datetime :created_at, null: false
+ t.datetime :updated_at, null: false
+ t.boolean :sharing, default: false, null: false
+ t.boolean :receiving, default: false, null: false
+ end
+
+ add_index :contacts, [:person_id], name: :index_contacts_on_person_id
+ add_index :contacts, %i[user_id person_id], name: :index_contacts_on_user_id_and_person_id, unique: true
+
+ create_table :conversation_visibilities do |t|
+ t.integer :conversation_id, null: false
+ t.integer :person_id, null: false
+ t.integer :unread, default: 0, null: false
+ t.datetime :created_at, null: false
+ t.datetime :updated_at, null: false
+ end
+
+ add_index :conversation_visibilities, %i[conversation_id person_id], name: :index_conversation_visibilities_usefully, unique: true
+ add_index :conversation_visibilities, [:conversation_id], name: :index_conversation_visibilities_on_conversation_id
+ add_index :conversation_visibilities, [:person_id], name: :index_conversation_visibilities_on_person_id
+
+ create_table :conversations do |t|
+ t.string :subject
+ t.string :guid, null: false
+ t.integer :author_id, null: false
+ t.datetime :created_at, null: false
+ t.datetime :updated_at, null: false
+ end
+
+ add_index :conversations, [:author_id], name: :conversations_author_id_fk
+
+ create_table :invitation_codes do |t|
+ t.string :token
+ t.integer :user_id
+ t.integer :count
+ t.datetime :created_at, null: false
+ t.datetime :updated_at, null: false
+ end
+
+ create_table :invitations do |t|
+ t.text :message
+ t.integer :sender_id
+ t.integer :recipient_id
+ t.integer :aspect_id
+ t.datetime :created_at, null: false
+ t.datetime :updated_at, null: false
+ t.string :service
+ t.string :identifier
+ t.boolean :admin, default: false
+ t.string :language, default: "en"
+ end
+
+ add_index :invitations, [:aspect_id], name: :index_invitations_on_aspect_id
+ add_index :invitations, [:recipient_id], name: :index_invitations_on_recipient_id
+ add_index :invitations, [:sender_id], name: :index_invitations_on_sender_id
+
+ create_table :likes do |t|
+ t.boolean :positive, default: true
+ t.integer :target_id
+ t.integer :author_id
+ t.string :guid
+ t.text :author_signature
+ t.text :parent_author_signature
+ t.datetime :created_at, null: false
+ t.datetime :updated_at, null: false
+ t.string :target_type, limit: 60, null: false
+ end
+
+ add_index :likes, [:author_id], name: :likes_author_id_fk
+ add_index :likes, [:guid], name: :index_likes_on_guid, length: {guid: 191}, using: :btree, unique: true
+ add_index :likes, %i[target_id author_id target_type], name: :index_likes_on_target_id_and_author_id_and_target_type, unique: true
+ add_index :likes, [:target_id], name: :index_likes_on_post_id
+
+ create_table :locations do |t|
+ t.string :address
+ t.string :lat
+ t.string :lng
+ t.integer :status_message_id
+ t.datetime :created_at, null: false
+ t.datetime :updated_at, null: false
+ end
+
+ create_table :mentions do |t|
+ t.integer :post_id, null: false
+ t.integer :person_id, null: false
+ end
+
+ add_index :mentions, %i[person_id post_id], name: :index_mentions_on_person_id_and_post_id, unique: true
+ add_index :mentions, [:person_id], name: :index_mentions_on_person_id
+ add_index :mentions, [:post_id], name: :index_mentions_on_post_id
+
+ create_table :messages do |t|
+ t.integer :conversation_id, null: false
+ t.integer :author_id, null: false
+ t.string :guid, null: false
+ t.text :text, null: false
+ t.datetime :created_at, null: false
+ t.datetime :updated_at, null: false
+ t.text :author_signature
+ t.text :parent_author_signature
+ end
+
+ add_index :messages, [:author_id], name: :index_messages_on_author_id
+ add_index :messages, [:conversation_id], name: :messages_conversation_id_fk
+
+ create_table :notification_actors do |t|
+ t.integer :notification_id
+ t.integer :person_id
+ t.datetime :created_at, null: false
+ t.datetime :updated_at, null: false
+ end
+
+ add_index :notification_actors, %i[notification_id person_id], name: :index_notification_actors_on_notification_id_and_person_id, unique: true
+ add_index :notification_actors, [:notification_id], name: :index_notification_actors_on_notification_id
+ add_index :notification_actors, [:person_id], name: :index_notification_actors_on_person_id
+
+ create_table :notifications do |t|
+ t.string :target_type
+ t.integer :target_id
+ t.integer :recipient_id, null: false
+ t.boolean :unread, default: true, null: false
+ t.datetime :created_at, null: false
+ t.datetime :updated_at, null: false
+ t.string :type
+ end
+
+ add_index :notifications, [:recipient_id], name: :index_notifications_on_recipient_id
+ add_index :notifications, [:target_id], name: :index_notifications_on_target_id
+ add_index :notifications, %i[target_type target_id], name: :index_notifications_on_target_type_and_target_id, length: {target_type: 190}, using: :btree
+
+ create_table :o_embed_caches do |t|
+ t.string :url, limit: 1024, null: false
+ t.text :data, null: false
+ end
+
+ add_index :o_embed_caches, [:url], name: :index_o_embed_caches_on_url, length: {url: 191}, using: :btree
+
+ create_table :participations do |t|
+ t.string :guid
+ t.integer :target_id
+ t.string :target_type, limit: 60, null: false
+ t.integer :author_id
+ t.text :author_signature
+ t.text :parent_author_signature
+ t.datetime :created_at, null: false
+ t.datetime :updated_at, null: false
+ end
+
+ add_index :participations, [:guid], name: :index_participations_on_guid, length: {guid: 191}, using: :btree
+ add_index :participations, %i[target_id target_type author_id], name: :index_participations_on_target_id_and_target_type_and_author_id
+
+ create_table :people do |t|
+ t.string :guid, null: false
+ t.text :url, null: false
+ t.string :diaspora_handle, null: false
+ t.text :serialized_public_key, null: false
+ t.integer :owner_id
+ t.datetime :created_at, null: false
+ t.datetime :updated_at, null: false
+ t.boolean :closed_account, default: false
+ t.integer :fetch_status, default: 0
+ end
+
+ add_index :people, [:diaspora_handle], name: :index_people_on_diaspora_handle, unique: true, length: {diaspora_handle: 191}
+ add_index :people, [:guid], name: :index_people_on_guid, length: {guid: 191}, using: :btree, unique: true
+ add_index :people, [:owner_id], name: :index_people_on_owner_id, unique: true
+
+ create_table :photos do |t|
+ t.integer :tmp_old_id
+ t.integer :author_id, null: false
+ t.boolean :public, default: false, null: false
+ t.string :diaspora_handle
+ t.string :guid, null: false
+ t.boolean :pending, default: false, null: false
+ t.text :text
+ t.text :remote_photo_path
+ t.string :remote_photo_name
+ t.string :random_string
+ t.string :processed_image
+ t.datetime :created_at
+ t.datetime :updated_at
+ t.string :unprocessed_image
+ t.string :status_message_guid
+ t.integer :comments_count
+ t.integer :height
+ t.integer :width
+ end
+
+ add_index :photos, [:status_message_guid], name: :index_photos_on_status_message_guid, length: {status_message_guid: 191}, using: :btree
+
+ create_table :pods do |t|
+ t.string :host
+ t.boolean :ssl
+ t.datetime :created_at, null: false
+ t.datetime :updated_at, null: false
+ end
+
+ create_table :posts do |t|
+ t.integer :author_id, null: false
+ t.boolean :public, default: false, null: false
+ t.string :diaspora_handle
+ t.string :guid, null: false
+ t.boolean :pending, default: false, null: false
+ t.string :type, limit: 40, null: false
+ t.text :text
+ t.text :remote_photo_path
+ t.string :remote_photo_name
+ t.string :random_string
+ t.string :processed_image
+ t.datetime :created_at, null: false
+ t.datetime :updated_at, null: false
+ t.string :unprocessed_image
+ t.string :object_url
+ t.string :image_url
+ t.integer :image_height
+ t.integer :image_width
+ t.string :provider_display_name
+ t.string :actor_url
+ t.string :objectId
+ t.string :root_guid, limit: 30
+ t.string :status_message_guid
+ t.integer :likes_count, default: 0
+ t.integer :comments_count, default: 0
+ t.integer :o_embed_cache_id
+ t.integer :reshares_count, default: 0
+ t.datetime :interacted_at
+ t.string :frame_name
+ t.boolean :favorite, default: false
+ end
+
+ add_index :posts, %i[author_id root_guid], name: :index_posts_on_author_id_and_root_guid, length: {root_guid: 30}, using: :btree, unique: true
+ add_index :posts, [:author_id], name: :index_posts_on_person_id
+ add_index :posts, [:guid], name: :index_posts_on_guid, length: {guid: 191}, using: :btree, unique: true
+ add_index :posts, %i[id type created_at], name: :index_posts_on_id_and_type_and_created_at
+ add_index :posts, [:root_guid], name: :index_posts_on_root_guid, length: {root_guid: 30}
+ add_index :posts, %i[status_message_guid pending], name: :index_posts_on_status_message_guid_and_pending, length: {status_message_guid: 190}, using: :btree
+ add_index :posts, [:status_message_guid], name: :index_posts_on_status_message_guid, length: {status_message_guid: 191}, using: :btree
+ add_index :posts, %i[type pending id], name: :index_posts_on_type_and_pending_and_id
+
+ create_table :profiles do |t|
+ t.string :diaspora_handle
+ t.string :first_name, limit: 127
+ t.string :last_name, limit: 127
+ t.string :image_url
+ t.string :image_url_small
+ t.string :image_url_medium
+ t.date :birthday
+ t.string :gender
+ t.text :bio
+ t.boolean :searchable, default: true, null: false
+ t.integer :person_id, null: false
+ t.datetime :created_at, null: false
+ t.datetime :updated_at, null: false
+ t.string :location
+ t.string :full_name, limit: 70
+ t.boolean :nsfw, default: false
+ end
+
+ add_index :profiles, %i[full_name searchable], name: :index_profiles_on_full_name_and_searchable
+ add_index :profiles, [:full_name], name: :index_profiles_on_full_name
+ add_index :profiles, [:person_id], name: :index_profiles_on_person_id
+
+ create_table :rails_admin_histories do |t|
+ t.text :message
+ t.string :username
+ t.integer :item
+ t.string :table
+ t.integer :month, limit: 2
+ t.integer :year, limit: 8
+ t.datetime :created_at, null: false
+ t.datetime :updated_at, null: false
+ end
+
+ add_index :rails_admin_histories, %i[item table month year], name: :index_rails_admin_histories, length: {table: 188}
+
+ create_table :roles do |t|
+ t.integer :person_id
+ t.string :name
+ t.datetime :created_at, null: false
+ t.datetime :updated_at, null: false
+ end
+
+ create_table :services do |t|
+ t.string :type, limit: 127, null: false
+ t.integer :user_id, null: false
+ t.string :uid, limit: 127
+ t.string :access_token
+ t.string :access_secret
+ t.string :nickname
+ t.datetime :created_at, null: false
+ t.datetime :updated_at, null: false
+ end
+
+ add_index :services, %i[type uid], name: :index_services_on_type_and_uid, length: {type: 64, uid: 127}, using: :btree
+ add_index :services, [:user_id], name: :index_services_on_user_id
+
+ create_table :share_visibilities do |t|
+ t.integer :shareable_id, null: false
+ t.datetime :created_at, null: false
+ t.datetime :updated_at, null: false
+ t.boolean :hidden, default: false, null: false
+ t.integer :contact_id, null: false
+ t.string :shareable_type, limit: 60, default: "Post", null: false
+ end
+
+ add_index :share_visibilities, [:contact_id], name: :index_post_visibilities_on_contact_id
+ add_index :share_visibilities, %i[shareable_id shareable_type contact_id], name: :shareable_and_contact_id
+ add_index :share_visibilities, %i[shareable_id shareable_type hidden contact_id], name: :shareable_and_hidden_and_contact_id
+ add_index :share_visibilities, [:shareable_id], name: :index_post_visibilities_on_post_id
+
+ create_table :tag_followings do |t|
+ t.integer :tag_id, null: false
+ t.integer :user_id, null: false
+ t.datetime :created_at, null: false
+ t.datetime :updated_at, null: false
+ end
+
+ add_index :tag_followings, %i[tag_id user_id], name: :index_tag_followings_on_tag_id_and_user_id, unique: true
+ add_index :tag_followings, [:tag_id], name: :index_tag_followings_on_tag_id
+ add_index :tag_followings, [:user_id], name: :index_tag_followings_on_user_id
+
+ create_table :taggings do |t|
+ t.integer :tag_id
+ t.integer :taggable_id
+ t.string :taggable_type, limit: 127
+ t.integer :tagger_id
+ t.string :tagger_type, limit: 127
+ t.string :context, limit: 127
+ t.datetime :created_at
+ end
+
+ add_index :taggings, [:created_at], name: :index_taggings_on_created_at
+ add_index :taggings, [:tag_id], name: :index_taggings_on_tag_id
+ add_index :taggings, %i[taggable_id taggable_type context], name: :index_taggings_on_taggable_id_and_taggable_type_and_context, length: {taggable_type: 95, context: 95}, using: :btree
+ add_index :taggings, %i[taggable_id taggable_type tag_id], name: :index_taggings_uniquely, unique: true
+
+ create_table :tags do |t|
+ t.string :name
+ end
+
+ add_index :tags, [:name], name: :index_tags_on_name, unique: true, length: {name: 191}
+
+ create_table :user_preferences do |t|
+ t.string :email_type
+ t.integer :user_id
+ t.datetime :created_at, null: false
+ t.datetime :updated_at, null: false
+ end
+
+ create_table :users do |t|
+ t.string :username
+ t.text :serialized_private_key
+ t.boolean :getting_started, default: true, null: false
+ t.boolean :disable_mail, default: false, null: false
+ t.string :language
+ t.string :email, default: "", null: false
+ t.string :encrypted_password, default: "", null: false
+ t.string :invitation_token, limit: 60
+ t.datetime :invitation_sent_at
+ t.string :reset_password_token
+ t.datetime :remember_created_at
+ t.integer :sign_in_count, default: 0
+ t.datetime :current_sign_in_at
+ t.datetime :last_sign_in_at
+ t.string :current_sign_in_ip
+ t.string :last_sign_in_ip
+ t.datetime :created_at, null: false
+ t.datetime :updated_at, null: false
+ t.string :invitation_service, limit: 127
+ t.string :invitation_identifier, limit: 127
+ t.integer :invitation_limit
+ t.integer :invited_by_id
+ t.string :invited_by_type
+ t.string :authentication_token, limit: 30
+ t.string :unconfirmed_email
+ t.string :confirm_email_token, limit: 30
+ t.datetime :locked_at
+ t.boolean :show_community_spotlight_in_stream, default: true, null: false
+ t.boolean :auto_follow_back, default: false
+ t.integer :auto_follow_back_aspect_id
+ t.text :hidden_shareables
+ t.datetime :reset_password_sent_at
+ end
+
+ add_index :users, [:authentication_token], name: :index_users_on_authentication_token, unique: true
+ add_index :users, [:email], name: :index_users_on_email, length: {email: 191}
+ add_index :users, %i[invitation_service invitation_identifier], name: :index_users_on_invitation_service_and_invitation_identifier, length: {invitation_service: 64, invitation_identifier: 127}, using: :btree, unique: true
+ add_index :users, [:invitation_token], name: :index_users_on_invitation_token
+ add_index :users, [:username], name: :index_users_on_username, length: {username: 191}, using: :btree, unique: true
+
+ add_foreign_key :aspect_memberships, :aspects, name: :aspect_memberships_aspect_id_fk, on_delete: :cascade
+ add_foreign_key :aspect_memberships, :contacts, name: :aspect_memberships_contact_id_fk, on_delete: :cascade
+
+ add_foreign_key :aspect_visibilities, :aspects, name: :aspect_visibilities_aspect_id_fk, on_delete: :cascade
+
+ add_foreign_key :comments, :people, name: :comments_author_id_fk, column: :author_id, on_delete: :cascade
+
+ add_foreign_key :contacts, :people, name: :contacts_person_id_fk, on_delete: :cascade
+
+ add_foreign_key :conversation_visibilities, :conversations, name: :conversation_visibilities_conversation_id_fk, on_delete: :cascade
+ add_foreign_key :conversation_visibilities, :people, name: :conversation_visibilities_person_id_fk, on_delete: :cascade
+
+ add_foreign_key :conversations, :people, name: :conversations_author_id_fk, column: :author_id, on_delete: :cascade
+
+ add_foreign_key :invitations, :users, name: :invitations_recipient_id_fk, column: :recipient_id, on_delete: :cascade
+ add_foreign_key :invitations, :users, name: :invitations_sender_id_fk, column: :sender_id, on_delete: :cascade
+
+ add_foreign_key :likes, :people, name: :likes_author_id_fk, column: :author_id, on_delete: :cascade
+
+ add_foreign_key :messages, :conversations, name: :messages_conversation_id_fk, on_delete: :cascade
+ add_foreign_key :messages, :people, name: :messages_author_id_fk, column: :author_id, on_delete: :cascade
+
+ add_foreign_key :notification_actors, :notifications, name: :notification_actors_notification_id_fk, on_delete: :cascade
+
+ add_foreign_key :posts, :people, name: :posts_author_id_fk, column: :author_id, on_delete: :cascade
+
+ add_foreign_key :profiles, :people, name: :profiles_person_id_fk, on_delete: :cascade
+
+ add_foreign_key :services, :users, name: :services_user_id_fk, on_delete: :cascade
+
+ add_foreign_key :share_visibilities, :contacts, name: :post_visibilities_contact_id_fk, on_delete: :cascade
+ end
+ # rubocop:enable Metrics/AbcSize, Metrics/MethodLength, Metrics/LineLength, Layout/ExtraSpacing
end
diff --git a/db/migrate/20130207231310_add_facebook_id_to_post.rb b/db/migrate/20130207231310_add_facebook_id_to_post.rb
index df888dcca..f559f46a7 100644
--- a/db/migrate/20130207231310_add_facebook_id_to_post.rb
+++ b/db/migrate/20130207231310_add_facebook_id_to_post.rb
@@ -1,4 +1,4 @@
-class AddFacebookIdToPost < ActiveRecord::Migration
+class AddFacebookIdToPost < ActiveRecord::Migration[4.2]
def change
add_column :posts, :facebook_id, :string
end
diff --git a/db/migrate/20130404211624_fix_default_image_url_from_profile.rb b/db/migrate/20130404211624_fix_default_image_url_from_profile.rb
index 4749728fc..80618b8a5 100644
--- a/db/migrate/20130404211624_fix_default_image_url_from_profile.rb
+++ b/db/migrate/20130404211624_fix_default_image_url_from_profile.rb
@@ -1,4 +1,4 @@
-class FixDefaultImageUrlFromProfile < ActiveRecord::Migration
+class FixDefaultImageUrlFromProfile < ActiveRecord::Migration[4.2]
def up
execute("UPDATE profiles SET image_url = REPLACE(image_url, 'images', 'assets'), image_url_small = REPLACE(image_url_small, 'images', 'assets'), image_url_medium = REPLACE(image_url_medium, 'images', 'assets') WHERE image_url LIKE '%images/user/default.png';")
end
diff --git a/db/migrate/20130429073928_add_tweet_id_to_post.rb b/db/migrate/20130429073928_add_tweet_id_to_post.rb
index f62c2b964..7f9c5808f 100644
--- a/db/migrate/20130429073928_add_tweet_id_to_post.rb
+++ b/db/migrate/20130429073928_add_tweet_id_to_post.rb
@@ -1,4 +1,4 @@
-class AddTweetIdToPost < ActiveRecord::Migration
+class AddTweetIdToPost < ActiveRecord::Migration[4.2]
def change
add_column :posts, :tweet_id, :string
add_index :posts, ['tweet_id'], :length => { "tweet_id" => 191 }
diff --git a/db/migrate/20130608171134_add_open_graph_cache.rb b/db/migrate/20130608171134_add_open_graph_cache.rb
index ccf4aecc4..ac4826c1f 100644
--- a/db/migrate/20130608171134_add_open_graph_cache.rb
+++ b/db/migrate/20130608171134_add_open_graph_cache.rb
@@ -1,4 +1,4 @@
-class AddOpenGraphCache < ActiveRecord::Migration
+class AddOpenGraphCache < ActiveRecord::Migration[4.2]
def up
create_table :open_graph_caches do |t|
t.string :title
diff --git a/db/migrate/20130613203350_remove_limit_from_root_guid_in_posts.rb b/db/migrate/20130613203350_remove_limit_from_root_guid_in_posts.rb
index 97b653a10..2e88f0a1e 100644
--- a/db/migrate/20130613203350_remove_limit_from_root_guid_in_posts.rb
+++ b/db/migrate/20130613203350_remove_limit_from_root_guid_in_posts.rb
@@ -1,4 +1,4 @@
-class RemoveLimitFromRootGuidInPosts < ActiveRecord::Migration
+class RemoveLimitFromRootGuidInPosts < ActiveRecord::Migration[4.2]
def up
remove_index 'posts', :name => 'index_posts_on_root_guid'
remove_index 'posts', :name => 'index_posts_on_author_id_and_root_guid'
diff --git a/db/migrate/20130717104359_migrate_activity_stream_to_status_message.rb b/db/migrate/20130717104359_migrate_activity_stream_to_status_message.rb
index c02282f81..c37d8dd3e 100644
--- a/db/migrate/20130717104359_migrate_activity_stream_to_status_message.rb
+++ b/db/migrate/20130717104359_migrate_activity_stream_to_status_message.rb
@@ -1,5 +1,5 @@
-class MigrateActivityStreamToStatusMessage < ActiveRecord::Migration
- class Post < ActiveRecord::Base; self.inheritance_column = false; end
+class MigrateActivityStreamToStatusMessage < ActiveRecord::Migration[4.2]
+ class Post < ApplicationRecord; self.inheritance_column = false; end
def up
posts_stream_photos = Post.where(type: 'ActivityStreams::Photo')
posts_stream_photos.each do |p|
diff --git a/db/migrate/20130801063213_add_tumblr_post_ids_to_posts.rb b/db/migrate/20130801063213_add_tumblr_post_ids_to_posts.rb
index e8ddb4877..638157388 100644
--- a/db/migrate/20130801063213_add_tumblr_post_ids_to_posts.rb
+++ b/db/migrate/20130801063213_add_tumblr_post_ids_to_posts.rb
@@ -1,4 +1,4 @@
-class AddTumblrPostIdsToPosts < ActiveRecord::Migration
+class AddTumblrPostIdsToPosts < ActiveRecord::Migration[4.2]
def change
add_column :posts, :tumblr_ids, :text
end
diff --git a/db/migrate/20131017093025_create_post_reports.rb b/db/migrate/20131017093025_create_post_reports.rb
index bb68ff896..5ccceca03 100644
--- a/db/migrate/20131017093025_create_post_reports.rb
+++ b/db/migrate/20131017093025_create_post_reports.rb
@@ -1,4 +1,4 @@
-class CreatePostReports < ActiveRecord::Migration
+class CreatePostReports < ActiveRecord::Migration[4.2]
def change
create_table :post_reports do |t|
t.integer :post_id, :null => false
diff --git a/db/migrate/20131213171804_create_simple_captcha_data.rb b/db/migrate/20131213171804_create_simple_captcha_data.rb
index 4573b2056..9068aec00 100644
--- a/db/migrate/20131213171804_create_simple_captcha_data.rb
+++ b/db/migrate/20131213171804_create_simple_captcha_data.rb
@@ -1,4 +1,4 @@
-class CreateSimpleCaptchaData < ActiveRecord::Migration
+class CreateSimpleCaptchaData < ActiveRecord::Migration[4.2]
def self.up
create_table :simple_captcha_data do |t|
t.string :key, :limit => 40
diff --git a/db/migrate/20140121132816_add_post_type_to_post_report.rb b/db/migrate/20140121132816_add_post_type_to_post_report.rb
index 4d6686eea..766efb9b9 100644
--- a/db/migrate/20140121132816_add_post_type_to_post_report.rb
+++ b/db/migrate/20140121132816_add_post_type_to_post_report.rb
@@ -1,4 +1,4 @@
-class AddPostTypeToPostReport < ActiveRecord::Migration
+class AddPostTypeToPostReport < ActiveRecord::Migration[4.2]
def change
add_column :post_reports, :post_type, :string, :null => false, :after => :post_id, :default => 'post'
change_column_default :post_reports, :post_type, nil
diff --git a/db/migrate/20140214104217_rename_post_report_to_report.rb b/db/migrate/20140214104217_rename_post_report_to_report.rb
index 2d477491e..3b02b0aec 100644
--- a/db/migrate/20140214104217_rename_post_report_to_report.rb
+++ b/db/migrate/20140214104217_rename_post_report_to_report.rb
@@ -1,4 +1,4 @@
-class RenamePostReportToReport < ActiveRecord::Migration
+class RenamePostReportToReport < ActiveRecord::Migration[4.2]
def self.up
rename_table :post_reports, :reports
end
diff --git a/db/migrate/20140222162826_devise_add_lastseenable_user.rb b/db/migrate/20140222162826_devise_add_lastseenable_user.rb
index 5c62814af..c0a5428d4 100644
--- a/db/migrate/20140222162826_devise_add_lastseenable_user.rb
+++ b/db/migrate/20140222162826_devise_add_lastseenable_user.rb
@@ -1,4 +1,4 @@
-class DeviseAddLastseenableUser < ActiveRecord::Migration
+class DeviseAddLastseenableUser < ActiveRecord::Migration[4.2]
def self.up
add_column :users, :last_seen, :datetime
User.find_each do |user|
diff --git a/db/migrate/20140308154022_create_polls.rb b/db/migrate/20140308154022_create_polls.rb
index f2d84ba6a..c9dd794a2 100644
--- a/db/migrate/20140308154022_create_polls.rb
+++ b/db/migrate/20140308154022_create_polls.rb
@@ -1,4 +1,4 @@
-class CreatePolls < ActiveRecord::Migration
+class CreatePolls < ActiveRecord::Migration[4.2]
def up
create_table :polls do |t|
t.string :question, :null => false
diff --git a/db/migrate/20140422134050_rename_post_columns_to_item.rb b/db/migrate/20140422134050_rename_post_columns_to_item.rb
index 4550eacd7..986326152 100644
--- a/db/migrate/20140422134050_rename_post_columns_to_item.rb
+++ b/db/migrate/20140422134050_rename_post_columns_to_item.rb
@@ -1,4 +1,4 @@
-class RenamePostColumnsToItem < ActiveRecord::Migration
+class RenamePostColumnsToItem < ActiveRecord::Migration[4.2]
def up
rename_column :reports, :post_id, :item_id
rename_column :reports, :post_type, :item_type
diff --git a/db/migrate/20140422134627_change_user_id_type_to_integer.rb b/db/migrate/20140422134627_change_user_id_type_to_integer.rb
index 1f4918e8b..019cef962 100644
--- a/db/migrate/20140422134627_change_user_id_type_to_integer.rb
+++ b/db/migrate/20140422134627_change_user_id_type_to_integer.rb
@@ -1,4 +1,4 @@
-class ChangeUserIdTypeToInteger < ActiveRecord::Migration
+class ChangeUserIdTypeToInteger < ActiveRecord::Migration[4.2]
def up
remove_column :reports, :user_id
add_column :reports, :user_id, :integer, :null => false, :default => 1
diff --git a/db/migrate/20140601102543_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb b/db/migrate/20140601102543_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb
index 8edb50807..5a3f71a25 100644
--- a/db/migrate/20140601102543_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb
+++ b/db/migrate/20140601102543_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb
@@ -1,5 +1,5 @@
# This migration comes from acts_as_taggable_on_engine (originally 3)
-class AddTaggingsCounterCacheToTags < ActiveRecord::Migration
+class AddTaggingsCounterCacheToTags < ActiveRecord::Migration[4.2]
def self.up
add_column :tags, :taggings_count, :integer, default: 0
diff --git a/db/migrate/20140801101230_create_chat_contacts.rb b/db/migrate/20140801101230_create_chat_contacts.rb
index 718b5ae8d..b50afcece 100644
--- a/db/migrate/20140801101230_create_chat_contacts.rb
+++ b/db/migrate/20140801101230_create_chat_contacts.rb
@@ -1,4 +1,4 @@
-class CreateChatContacts < ActiveRecord::Migration
+class CreateChatContacts < ActiveRecord::Migration[4.2]
def up
create_table :chat_contacts do |t|
t.integer :user_id, null: false
diff --git a/db/migrate/20140801101352_create_chat_fragments.rb b/db/migrate/20140801101352_create_chat_fragments.rb
index 0fbdc40ee..0457abf22 100644
--- a/db/migrate/20140801101352_create_chat_fragments.rb
+++ b/db/migrate/20140801101352_create_chat_fragments.rb
@@ -1,4 +1,4 @@
-class CreateChatFragments < ActiveRecord::Migration
+class CreateChatFragments < ActiveRecord::Migration[4.2]
def up
create_table :chat_fragments do |t|
t.integer :user_id, null: false
diff --git a/db/migrate/20140824230505_add_completed_at_to_account_deletions.rb b/db/migrate/20140824230505_add_completed_at_to_account_deletions.rb
index 9b2af8c6a..2c701dcac 100644
--- a/db/migrate/20140824230505_add_completed_at_to_account_deletions.rb
+++ b/db/migrate/20140824230505_add_completed_at_to_account_deletions.rb
@@ -1,4 +1,4 @@
-class AddCompletedAtToAccountDeletions < ActiveRecord::Migration
+class AddCompletedAtToAccountDeletions < ActiveRecord::Migration[4.2]
def change
add_column :account_deletions, :completed_at, :datetime
end
diff --git a/db/migrate/20140826165533_increase_simple_captcha_limit.rb b/db/migrate/20140826165533_increase_simple_captcha_limit.rb
index b4d43dd64..c0d7d4827 100644
--- a/db/migrate/20140826165533_increase_simple_captcha_limit.rb
+++ b/db/migrate/20140826165533_increase_simple_captcha_limit.rb
@@ -1,4 +1,4 @@
-class IncreaseSimpleCaptchaLimit < ActiveRecord::Migration
+class IncreaseSimpleCaptchaLimit < ActiveRecord::Migration[4.2]
def self.up
change_column :simple_captcha_data, :value, :string, :limit => 12
end
diff --git a/db/migrate/20140906192846_fix_open_graph_data.rb b/db/migrate/20140906192846_fix_open_graph_data.rb
index 54959931d..5aec2b531 100644
--- a/db/migrate/20140906192846_fix_open_graph_data.rb
+++ b/db/migrate/20140906192846_fix_open_graph_data.rb
@@ -1,4 +1,4 @@
-class FixOpenGraphData < ActiveRecord::Migration
+class FixOpenGraphData < ActiveRecord::Migration[4.2]
def self.up
change_column :open_graph_caches, :url, :text
change_column :open_graph_caches, :image, :text
diff --git a/db/migrate/20141001162851_add_remove_after_to_users.rb b/db/migrate/20141001162851_add_remove_after_to_users.rb
index c63b916b6..8169e5e8b 100644
--- a/db/migrate/20141001162851_add_remove_after_to_users.rb
+++ b/db/migrate/20141001162851_add_remove_after_to_users.rb
@@ -1,4 +1,4 @@
-class AddRemoveAfterToUsers < ActiveRecord::Migration
+class AddRemoveAfterToUsers < ActiveRecord::Migration[4.2]
def change
add_column :users, :remove_after, :datetime
end
diff --git a/db/migrate/20141007003922_add_chat_enabled_to_aspects.rb b/db/migrate/20141007003922_add_chat_enabled_to_aspects.rb
index ba4fd31fc..a5e300b94 100644
--- a/db/migrate/20141007003922_add_chat_enabled_to_aspects.rb
+++ b/db/migrate/20141007003922_add_chat_enabled_to_aspects.rb
@@ -1,4 +1,4 @@
-class AddChatEnabledToAspects < ActiveRecord::Migration
+class AddChatEnabledToAspects < ActiveRecord::Migration[4.2]
def self.up
add_column :aspects, :chat_enabled, :boolean, default: false
end
diff --git a/db/migrate/20141024170120_create_chat_offline_messages.rb b/db/migrate/20141024170120_create_chat_offline_messages.rb
index 8c30101b0..5c31e632d 100644
--- a/db/migrate/20141024170120_create_chat_offline_messages.rb
+++ b/db/migrate/20141024170120_create_chat_offline_messages.rb
@@ -1,4 +1,4 @@
-class CreateChatOfflineMessages < ActiveRecord::Migration
+class CreateChatOfflineMessages < ActiveRecord::Migration[4.2]
def self.up
create_table :chat_offline_messages do |t|
t.string :from, :null => false
diff --git a/db/migrate/20141209041241_drop_open_graph_caches_with_invalid_urls.rb b/db/migrate/20141209041241_drop_open_graph_caches_with_invalid_urls.rb
index bfbfab884..1c2b3dbf7 100644
--- a/db/migrate/20141209041241_drop_open_graph_caches_with_invalid_urls.rb
+++ b/db/migrate/20141209041241_drop_open_graph_caches_with_invalid_urls.rb
@@ -1,4 +1,4 @@
-class DropOpenGraphCachesWithInvalidUrls < ActiveRecord::Migration
+class DropOpenGraphCachesWithInvalidUrls < ActiveRecord::Migration[4.2]
def up
OpenGraphCache.where(url: 'http://').delete_all
end
diff --git a/db/migrate/20141216213423_purge_orphan_conversations.rb b/db/migrate/20141216213423_purge_orphan_conversations.rb
index c5eb90bff..45e6f5856 100644
--- a/db/migrate/20141216213423_purge_orphan_conversations.rb
+++ b/db/migrate/20141216213423_purge_orphan_conversations.rb
@@ -1,4 +1,4 @@
-class PurgeOrphanConversations < ActiveRecord::Migration
+class PurgeOrphanConversations < ActiveRecord::Migration[4.2]
def up
Conversation.where(id: Conversation.joins("LEFT JOIN conversation_visibilities ON conversation_visibilities.conversation_id = conversations.id")
.group('conversations.id')
diff --git a/db/migrate/20141227120907_add_export_to_user.rb b/db/migrate/20141227120907_add_export_to_user.rb
index 376d5fe36..ef1779f76 100644
--- a/db/migrate/20141227120907_add_export_to_user.rb
+++ b/db/migrate/20141227120907_add_export_to_user.rb
@@ -1,4 +1,4 @@
-class AddExportToUser < ActiveRecord::Migration
+class AddExportToUser < ActiveRecord::Migration[4.2]
def change
add_column :users, :export, :string
add_column :users, :exported_at, :datetime
diff --git a/db/migrate/20141230214830_user_pref_strip_exif.rb b/db/migrate/20141230214830_user_pref_strip_exif.rb
index 79983181d..b573d4874 100644
--- a/db/migrate/20141230214830_user_pref_strip_exif.rb
+++ b/db/migrate/20141230214830_user_pref_strip_exif.rb
@@ -1,4 +1,4 @@
-class UserPrefStripExif < ActiveRecord::Migration
+class UserPrefStripExif < ActiveRecord::Migration[4.2]
def up
add_column :users, :strip_exif, :boolean, default: true
end
diff --git a/db/migrate/20150106050733_set_mysql_to_unicode_mb4.rb b/db/migrate/20150106050733_set_mysql_to_unicode_mb4.rb
deleted file mode 100644
index 37dd9373e..000000000
--- a/db/migrate/20150106050733_set_mysql_to_unicode_mb4.rb
+++ /dev/null
@@ -1,113 +0,0 @@
-class SetMysqlToUnicodeMb4 < ActiveRecord::Migration
- # Converts the tables and strings columns to utf8mb4, which is the true, full
- # unicode support in MySQl
-
- def self.up
- # shorten indexes regardless of the RDBMS provider - for consitency
- shorten_indexes
- change_encoding('utf8mb4', 'utf8mb4_bin') if AppConfig.mysql?
- end
-
- def self.down
- change_encoding('utf8', 'utf8_bin') if AppConfig.mysql?
- end
-
- def check_config(encoding, collation)
- connection_config = ActiveRecord::Base.connection_config
- raise "Database encoding is not #{encoding}!" if connection_config[:encoding] != encoding
- raise "Database collation is not #{collation}!" if connection_config[:collation] != collation
- end
-
- def change_encoding(encoding, collation)
- # Make sure the podmin changed the database.yml file
- check_config(encoding, collation)
-
- execute "ALTER DATABASE `#{ActiveRecord::Base.connection.current_database}` CHARACTER SET #{encoding} COLLATE #{collation};"
-
- tables.each do |table|
-
- modify_text_columns = columns(table).select {|column| column.type == :text }.map {|column|
- "MODIFY `#{column.name}` TEXT #{'NOT' unless column.null } NULL#{" DEFAULT '#{column.default}'" if column.has_default?}"
- }.join(", ")
-
- execute "ALTER TABLE `#{table}` CONVERT TO CHARACTER SET #{encoding} COLLATE #{collation}#{", #{modify_text_columns}" unless modify_text_columns.empty?};"
- end
- end
-
- def shorten_indexes
- remove_index 'aspect_visibilities', :name => 'shareable_and_aspect_id'
- add_index 'aspect_visibilities', ["shareable_id", "shareable_type", "aspect_id"], :name => 'shareable_and_aspect_id', length: {"shareable_type"=>189}, :using => :btree
-
- remove_index 'aspect_visibilities', :name => 'index_aspect_visibilities_on_shareable_id_and_shareable_type'
- add_index 'aspect_visibilities', ["shareable_id", "shareable_type"], :name => 'index_aspect_visibilities_on_shareable_id_and_shareable_type', length: {"shareable_type"=>190}, :using => :btree
-
- remove_index 'chat_contacts', :name => 'index_chat_contacts_on_user_id_and_jid'
- add_index 'chat_contacts', ["user_id", "jid"], :name => 'index_chat_contacts_on_user_id_and_jid', length: {"jid"=>190}, :using => :btree, :unique => true
-
- remove_index 'comments', :name => 'index_comments_on_guid'
- add_index 'comments', ["guid"], :name => 'index_comments_on_guid', length: {"guid"=>191}, :using => :btree, :unique => true
-
- remove_index 'likes', :name => 'index_likes_on_guid'
- add_index 'likes', ["guid"], :name => 'index_likes_on_guid', length: {"guid"=>191}, :using => :btree, :unique => true
-
- remove_index 'o_embed_caches', :name => 'index_o_embed_caches_on_url'
- add_index 'o_embed_caches', ["url"], :name => 'index_o_embed_caches_on_url', length: {"url"=>191}, :using => :btree
-
- remove_index 'participations', :name => 'index_participations_on_guid'
- add_index 'participations', ["guid"], :name => 'index_participations_on_guid', length: {"guid"=>191}, :using => :btree
-
- remove_index 'people', :name => 'index_people_on_diaspora_handle'
- add_index "people", ["diaspora_handle"], :name => "index_people_on_diaspora_handle", :unique => true, :length => {"diaspora_handle" => 191}
-
- remove_index 'people', :name => 'index_people_on_guid'
- add_index 'people', ["guid"], :name => 'index_people_on_guid', length: {"guid"=>191}, :using => :btree, :unique => true
-
- remove_index 'photos', :name => 'index_photos_on_status_message_guid'
- add_index 'photos', ["status_message_guid"], :name => 'index_photos_on_status_message_guid', length: {"status_message_guid"=>191}, :using => :btree
-
- remove_index 'posts', :name => 'index_posts_on_guid'
- add_index 'posts', ["guid"], :name => 'index_posts_on_guid', length: {"guid"=>191}, :using => :btree, :unique => true
-
- remove_index 'posts', :name => 'index_posts_on_status_message_guid_and_pending'
- add_index 'posts', ["status_message_guid", "pending"], :name => 'index_posts_on_status_message_guid_and_pending', length: {"status_message_guid"=>190}, :using => :btree
-
- remove_index 'posts', :name => 'index_posts_on_status_message_guid'
- add_index 'posts', ["status_message_guid"], :name => 'index_posts_on_status_message_guid', length: {"status_message_guid"=>191}, :using => :btree
-
- remove_index 'posts', :name => 'index_posts_on_author_id_and_root_guid'
- add_index 'posts', ["author_id", "root_guid"], :name => 'index_posts_on_author_id_and_root_guid', length: {"root_guid"=>190}, :using => :btree, :unique => true
-
- remove_index 'posts', :name => 'index_posts_on_root_guid'
- add_index 'posts', ["root_guid"], :name => 'index_posts_on_root_guid', length: {"root_guid"=>191}
-
- remove_index 'posts', :name => 'index_posts_on_tweet_id'
- add_index 'posts', ['tweet_id'], :name => 'index_posts_on_tweet_id', length: {"tweet_id"=>191}, :using => :btree
-
- remove_index 'rails_admin_histories', :name => 'index_rails_admin_histories'
- add_index 'rails_admin_histories', ["item", "table", "month", "year"], :name => 'index_rails_admin_histories', length: {"table"=>188}, :using => :btree
-
- remove_index 'schema_migrations', :name => 'unique_schema_migrations'
- add_index 'schema_migrations', ["version"], :name => 'unique_schema_migrations', length: {"version"=>191}, :using => :btree
-
- remove_index 'services', :name => 'index_services_on_type_and_uid'
- add_index 'services', ["type", "uid"], :name => 'index_services_on_type_and_uid', length: {"type"=>64, "uid"=>127}, :using => :btree
-
- remove_index 'taggings', :name => 'index_taggings_on_taggable_id_and_taggable_type_and_context'
- add_index 'taggings', ["taggable_id", "taggable_type", "context"], :name => 'index_taggings_on_taggable_id_and_taggable_type_and_context', length: {"taggable_type"=>95, "context"=>95}, :using => :btree
-
- remove_index 'tags', :name => 'index_tags_on_name'
- add_index 'tags', ["name"], :name => 'index_tags_on_name', length: {"name"=>191}, :using => :btree, :unique => true
-
- remove_index 'users', :name => 'index_users_on_invitation_service_and_invitation_identifier'
- add_index 'users', ["invitation_service", "invitation_identifier"], :name => 'index_users_on_invitation_service_and_invitation_identifier', length: {"invitation_service"=>64, "invitation_identifier"=>127}, :using => :btree, :unique => true
-
- remove_index 'users', :name => 'index_users_on_username'
- add_index 'users', ["username"], :name => 'index_users_on_username', length: {"username"=>191}, :using => :btree, :unique => true
-
- remove_index 'users', :name => 'index_users_on_email'
- add_index 'users', ["email"], :name => 'index_users_on_email', length: {"email"=>191}, :using => :btree
-
- remove_index 'notifications', :name => 'index_notifications_on_target_type_and_target_id'
- add_index 'notifications', ["target_type", "target_id"], name: 'index_notifications_on_target_type_and_target_id', length: {"target_type"=>190}, using: :btree
- end
-end
diff --git a/db/migrate/20150209230946_disable_mail_for_closed_account.rb b/db/migrate/20150209230946_disable_mail_for_closed_account.rb
index 575b16cfc..2dd573745 100644
--- a/db/migrate/20150209230946_disable_mail_for_closed_account.rb
+++ b/db/migrate/20150209230946_disable_mail_for_closed_account.rb
@@ -1,4 +1,4 @@
-class DisableMailForClosedAccount < ActiveRecord::Migration
+class DisableMailForClosedAccount < ActiveRecord::Migration[4.2]
def up
User.joins(:person).where(people: {closed_account: true}).update_all(disable_mail: true)
end
diff --git a/db/migrate/20150220001357_add_photos_export_to_user.rb b/db/migrate/20150220001357_add_photos_export_to_user.rb
index f19349723..6bec80420 100644
--- a/db/migrate/20150220001357_add_photos_export_to_user.rb
+++ b/db/migrate/20150220001357_add_photos_export_to_user.rb
@@ -1,4 +1,4 @@
-class AddPhotosExportToUser < ActiveRecord::Migration
+class AddPhotosExportToUser < ActiveRecord::Migration[4.2]
def up
add_column :users, :exported_photos_file, :string
add_column :users, :exported_photos_at, :datetime
diff --git a/db/migrate/20150403192408_remove_deleted_aspects_from_auto_follow_back.rb b/db/migrate/20150403192408_remove_deleted_aspects_from_auto_follow_back.rb
index d0d12058d..f5f19e750 100644
--- a/db/migrate/20150403192408_remove_deleted_aspects_from_auto_follow_back.rb
+++ b/db/migrate/20150403192408_remove_deleted_aspects_from_auto_follow_back.rb
@@ -1,4 +1,4 @@
-class RemoveDeletedAspectsFromAutoFollowBack < ActiveRecord::Migration
+class RemoveDeletedAspectsFromAutoFollowBack < ActiveRecord::Migration[4.2]
def up
User.where.not(auto_follow_back_aspect_id: Aspect.select(:id))
.where(auto_follow_back: true)
diff --git a/db/migrate/20150403212139_fix_wrong_only_sharing.rb b/db/migrate/20150403212139_fix_wrong_only_sharing.rb
index 8299ea88b..c02f4bba6 100644
--- a/db/migrate/20150403212139_fix_wrong_only_sharing.rb
+++ b/db/migrate/20150403212139_fix_wrong_only_sharing.rb
@@ -1,4 +1,4 @@
-class FixWrongOnlySharing < ActiveRecord::Migration
+class FixWrongOnlySharing < ActiveRecord::Migration[4.2]
def up
Contact.where(sharing: true, receiving: false)
.where(id: AspectMembership.select(:contact_id))
diff --git a/db/migrate/20150523004437_enable_color_themes.rb b/db/migrate/20150523004437_enable_color_themes.rb
index d9cea868d..816fd1fbf 100644
--- a/db/migrate/20150523004437_enable_color_themes.rb
+++ b/db/migrate/20150523004437_enable_color_themes.rb
@@ -1,4 +1,4 @@
-class EnableColorThemes < ActiveRecord::Migration
+class EnableColorThemes < ActiveRecord::Migration[4.2]
def up
add_column(:users, :color_theme, :string)
end
diff --git a/db/migrate/20150531005120_cleanup_default_avatars.rb b/db/migrate/20150531005120_cleanup_default_avatars.rb
index 93010fb2a..f3dcee9a2 100644
--- a/db/migrate/20150531005120_cleanup_default_avatars.rb
+++ b/db/migrate/20150531005120_cleanup_default_avatars.rb
@@ -1,4 +1,4 @@
-class CleanupDefaultAvatars < ActiveRecord::Migration
+class CleanupDefaultAvatars < ActiveRecord::Migration[4.2]
def up
Profile.where("image_url LIKE ?", "%user/default%")
.update_all(image_url: nil, image_url_small: nil, image_url_medium: nil)
diff --git a/db/migrate/20150607143809_fix_photo_public_flag.rb b/db/migrate/20150607143809_fix_photo_public_flag.rb
index fa75167ef..ee223cd6a 100644
--- a/db/migrate/20150607143809_fix_photo_public_flag.rb
+++ b/db/migrate/20150607143809_fix_photo_public_flag.rb
@@ -1,4 +1,4 @@
-class FixPhotoPublicFlag < ActiveRecord::Migration
+class FixPhotoPublicFlag < ActiveRecord::Migration[4.2]
def up
Photo.joins(:status_message).where(posts: {public: true}).update_all(public: true)
end
diff --git a/db/migrate/20150613202109_create_o_auth_applications.rb b/db/migrate/20150613202109_create_o_auth_applications.rb
index 1170b5c9e..a39f0ace9 100644
--- a/db/migrate/20150613202109_create_o_auth_applications.rb
+++ b/db/migrate/20150613202109_create_o_auth_applications.rb
@@ -1,6 +1,6 @@
# Inspired by https://github.com/nov/openid_connect_sample/blob/master/db/migrate/20110829023826_create_clients.rb
-class CreateOAuthApplications < ActiveRecord::Migration
+class CreateOAuthApplications < ActiveRecord::Migration[4.2]
def change
create_table :o_auth_applications do |t|
t.belongs_to :user, index: true
diff --git a/db/migrate/20150630221004_add_public_to_profiles.rb b/db/migrate/20150630221004_add_public_to_profiles.rb
index 06973e027..4797c1f38 100644
--- a/db/migrate/20150630221004_add_public_to_profiles.rb
+++ b/db/migrate/20150630221004_add_public_to_profiles.rb
@@ -1,4 +1,4 @@
-class AddPublicToProfiles < ActiveRecord::Migration
+class AddPublicToProfiles < ActiveRecord::Migration[4.2]
def change
add_column :profiles, :public_details, :boolean, default: false
end
diff --git a/db/migrate/20150708153926_create_authorizations.rb b/db/migrate/20150708153926_create_authorizations.rb
index ee88ab017..b9e06dd2c 100644
--- a/db/migrate/20150708153926_create_authorizations.rb
+++ b/db/migrate/20150708153926_create_authorizations.rb
@@ -1,4 +1,4 @@
-class CreateAuthorizations < ActiveRecord::Migration
+class CreateAuthorizations < ActiveRecord::Migration[4.2]
def change
create_table :authorizations do |t|
t.belongs_to :user, index: true
diff --git a/db/migrate/20150708153928_create_o_auth_access_tokens.rb b/db/migrate/20150708153928_create_o_auth_access_tokens.rb
index d833011c5..779283cbe 100644
--- a/db/migrate/20150708153928_create_o_auth_access_tokens.rb
+++ b/db/migrate/20150708153928_create_o_auth_access_tokens.rb
@@ -1,6 +1,6 @@
# Inspired by https://github.com/nov/openid_connect_sample/blob/master/db/migrate/20110829023837_create_access_tokens.rb
-class CreateOAuthAccessTokens < ActiveRecord::Migration
+class CreateOAuthAccessTokens < ActiveRecord::Migration[4.2]
def change
create_table :o_auth_access_tokens do |t|
t.belongs_to :authorization, index: true
diff --git a/db/migrate/20150714055110_create_id_tokens.rb b/db/migrate/20150714055110_create_id_tokens.rb
index b1e3abdfa..df98206a4 100644
--- a/db/migrate/20150714055110_create_id_tokens.rb
+++ b/db/migrate/20150714055110_create_id_tokens.rb
@@ -1,6 +1,6 @@
# Inspired by https://github.com/nov/openid_connect_sample/blob/master/db/migrate/20110829024010_create_id_tokens.rb
-class CreateIdTokens < ActiveRecord::Migration
+class CreateIdTokens < ActiveRecord::Migration[4.2]
def change
create_table :id_tokens do |t|
t.belongs_to :authorization, index: true
diff --git a/db/migrate/20150724152052_remove_favorites_from_posts.rb b/db/migrate/20150724152052_remove_favorites_from_posts.rb
index 8d4bd873f..737d3c593 100644
--- a/db/migrate/20150724152052_remove_favorites_from_posts.rb
+++ b/db/migrate/20150724152052_remove_favorites_from_posts.rb
@@ -1,4 +1,4 @@
-class RemoveFavoritesFromPosts < ActiveRecord::Migration
+class RemoveFavoritesFromPosts < ActiveRecord::Migration[4.2]
def self.up
remove_column :posts, :favorite
end
diff --git a/db/migrate/20150731123113_create_pairwise_pseudonymous_identifiers.rb b/db/migrate/20150731123113_create_pairwise_pseudonymous_identifiers.rb
index 0c8690848..12ed8597f 100644
--- a/db/migrate/20150731123113_create_pairwise_pseudonymous_identifiers.rb
+++ b/db/migrate/20150731123113_create_pairwise_pseudonymous_identifiers.rb
@@ -1,6 +1,6 @@
# Inspired by https://github.com/nov/openid_connect_sample/blob/master/db/migrate/20110829024140_create_pairwise_pseudonymous_identifiers.rb
-class CreatePairwisePseudonymousIdentifiers < ActiveRecord::Migration
+class CreatePairwisePseudonymousIdentifiers < ActiveRecord::Migration[4.2]
def change
create_table :ppid do |t|
t.belongs_to :o_auth_application, index: true
diff --git a/db/migrate/20150731123114_add_status_to_pods.rb b/db/migrate/20150731123114_add_status_to_pods.rb
index b53051f06..e94a011b1 100644
--- a/db/migrate/20150731123114_add_status_to_pods.rb
+++ b/db/migrate/20150731123114_add_status_to_pods.rb
@@ -1,4 +1,4 @@
-class AddStatusToPods < ActiveRecord::Migration
+class AddStatusToPods < ActiveRecord::Migration[4.2]
def change
add_column :pods, :status, :integer, default: 0
add_column :pods, :checked_at, :datetime, default: Time.zone.at(0)
diff --git a/db/migrate/20150828132451_remove_duplicate_and_empty_pods.rb b/db/migrate/20150828132451_remove_duplicate_and_empty_pods.rb
index e93acf722..f3d434474 100644
--- a/db/migrate/20150828132451_remove_duplicate_and_empty_pods.rb
+++ b/db/migrate/20150828132451_remove_duplicate_and_empty_pods.rb
@@ -1,4 +1,4 @@
-class RemoveDuplicateAndEmptyPods < ActiveRecord::Migration
+class RemoveDuplicateAndEmptyPods < ActiveRecord::Migration[4.2]
def up
remove_dupes
remove_empty_or_nil
diff --git a/db/migrate/20151003142048_update_report_item_types.rb b/db/migrate/20151003142048_update_report_item_types.rb
index 9a318edff..3d4972537 100644
--- a/db/migrate/20151003142048_update_report_item_types.rb
+++ b/db/migrate/20151003142048_update_report_item_types.rb
@@ -1,4 +1,4 @@
-class UpdateReportItemTypes < ActiveRecord::Migration
+class UpdateReportItemTypes < ActiveRecord::Migration[4.2]
def change
Report.all.each do |report|
report.update_attribute :item_type, report[:item_type].capitalize
diff --git a/db/migrate/20151210213023_remove_signatures_from_relayables.rb b/db/migrate/20151210213023_remove_signatures_from_relayables.rb
index 1d2cb485c..c9b7a45fa 100644
--- a/db/migrate/20151210213023_remove_signatures_from_relayables.rb
+++ b/db/migrate/20151210213023_remove_signatures_from_relayables.rb
@@ -1,4 +1,4 @@
-class RemoveSignaturesFromRelayables < ActiveRecord::Migration
+class RemoveSignaturesFromRelayables < ActiveRecord::Migration[4.2]
def change
remove_column :comments, :parent_author_signature, :text
remove_column :poll_participations, :parent_author_signature, :text
diff --git a/db/migrate/20160124234712_extend_pods.rb b/db/migrate/20160124234712_extend_pods.rb
index 17fb6c215..9f2dc7ebc 100644
--- a/db/migrate/20160124234712_extend_pods.rb
+++ b/db/migrate/20160124234712_extend_pods.rb
@@ -1,5 +1,5 @@
-class ExtendPods < ActiveRecord::Migration
- class Pod < ActiveRecord::Base
+class ExtendPods < ActiveRecord::Migration[4.2]
+ class Pod < ApplicationRecord
has_many :people
DEFAULT_PORTS = [URI::HTTP::DEFAULT_PORT, URI::HTTPS::DEFAULT_PORT]
@@ -18,7 +18,7 @@ class ExtendPods < ActiveRecord::Migration
end
end
- class Person < ActiveRecord::Base
+ class Person < ApplicationRecord
belongs_to :owner, class_name: "User"
belongs_to :pod
@@ -27,7 +27,7 @@ class ExtendPods < ActiveRecord::Migration
end
end
- class User < ActiveRecord::Base
+ class User < ApplicationRecord
has_one :person, inverse_of: :owner, foreign_key: :owner_id
end
@@ -52,7 +52,7 @@ class ExtendPods < ActiveRecord::Migration
end
# cleanup unused pods
- Pod.joins("LEFT OUTER JOIN people ON pods.id = people.pod_id").delete_all("people.id is NULL")
+ Pod.joins("LEFT OUTER JOIN people ON pods.id = people.pod_id").where("people.id is NULL").delete_all
remove_column :people, :url
end
diff --git a/db/migrate/20160225232049_link_share_visibilities_with_user.rb b/db/migrate/20160225232049_link_share_visibilities_with_user.rb
index 3292b0503..8a6f0f5ea 100644
--- a/db/migrate/20160225232049_link_share_visibilities_with_user.rb
+++ b/db/migrate/20160225232049_link_share_visibilities_with_user.rb
@@ -1,5 +1,5 @@
-class LinkShareVisibilitiesWithUser < ActiveRecord::Migration
- class ShareVisibility < ActiveRecord::Base
+class LinkShareVisibilitiesWithUser < ActiveRecord::Migration[4.2]
+ class ShareVisibility < ApplicationRecord
end
def up
@@ -26,7 +26,7 @@ class LinkShareVisibilitiesWithUser < ActiveRecord::Migration
remove_column :share_visibilities, :contact_id
ShareVisibility.joins("LEFT OUTER JOIN users ON users.id = share_visibilities.user_id")
- .delete_all("users.id is NULL")
+ .where("users.id is NULL").delete_all
change_column :share_visibilities, :user_id, :integer, null: false
@@ -73,8 +73,8 @@ class LinkShareVisibilitiesWithUser < ActiveRecord::Migration
def cleanup_deleted_share_visibilities
ShareVisibility.joins("LEFT OUTER JOIN posts ON posts.id = share_visibilities.shareable_id")
- .where(shareable_type: "Post").delete_all("posts.id is NULL")
+ .where(shareable_type: "Post").where("posts.id is NULL").delete_all
ShareVisibility.joins("LEFT OUTER JOIN photos ON photos.id = share_visibilities.shareable_id")
- .where(shareable_type: "Photo").delete_all("photos.id is NULL")
+ .where(shareable_type: "Photo").where("photos.id is NULL").delete_all
end
end
diff --git a/db/migrate/20160302025129_cleanup_aspect_visibility.rb b/db/migrate/20160302025129_cleanup_aspect_visibility.rb
index c937ac4df..7d3ae9c5f 100644
--- a/db/migrate/20160302025129_cleanup_aspect_visibility.rb
+++ b/db/migrate/20160302025129_cleanup_aspect_visibility.rb
@@ -1,16 +1,16 @@
-class CleanupAspectVisibility < ActiveRecord::Migration
- class AspectVisibility < ActiveRecord::Base
+class CleanupAspectVisibility < ActiveRecord::Migration[4.2]
+ class AspectVisibility < ApplicationRecord
end
def up
AspectVisibility.joins("LEFT OUTER JOIN posts ON posts.id = aspect_visibilities.shareable_id")
- .where(shareable_type: "Post").delete_all("posts.id is NULL")
+ .where(shareable_type: "Post").where("posts.id is NULL").delete_all
AspectVisibility.joins("LEFT OUTER JOIN photos ON photos.id = aspect_visibilities.shareable_id")
- .where(shareable_type: "Photo").delete_all("photos.id is NULL")
+ .where(shareable_type: "Photo").where("photos.id is NULL").delete_all
AspectVisibility.joins("INNER JOIN posts ON posts.id = aspect_visibilities.shareable_id")
- .where(shareable_type: "Post").delete_all(posts: {public: true})
+ .where(shareable_type: "Post").where(posts: {public: true}).delete_all
AspectVisibility.joins("INNER JOIN photos ON photos.id = aspect_visibilities.shareable_id")
- .where(shareable_type: "Photo").delete_all(photos: {public: true})
+ .where(shareable_type: "Photo").where(photos: {public: true}).delete_all
remove_columns :aspect_visibilities, :created_at, :updated_at
end
diff --git a/db/migrate/20160307142216_cleanup_handles.rb b/db/migrate/20160307142216_cleanup_handles.rb
index b2ed8fc8a..e39be2279 100644
--- a/db/migrate/20160307142216_cleanup_handles.rb
+++ b/db/migrate/20160307142216_cleanup_handles.rb
@@ -1,4 +1,4 @@
-class CleanupHandles < ActiveRecord::Migration
+class CleanupHandles < ActiveRecord::Migration[4.2]
def change
remove_column :photos, :tmp_old_id, :integer
remove_column :photos, :diaspora_handle, :string
diff --git a/db/migrate/20160327103605_add_author_id_index_to_participations.rb b/db/migrate/20160327103605_add_author_id_index_to_participations.rb
index 8a6382aeb..c41607981 100644
--- a/db/migrate/20160327103605_add_author_id_index_to_participations.rb
+++ b/db/migrate/20160327103605_add_author_id_index_to_participations.rb
@@ -1,4 +1,4 @@
-class AddAuthorIdIndexToParticipations < ActiveRecord::Migration
+class AddAuthorIdIndexToParticipations < ActiveRecord::Migration[4.2]
def change
add_index :participations, :author_id, :using => :btree
end
diff --git a/db/migrate/20160509232726_cleanup_duplicates_and_add_unique_indexes.rb b/db/migrate/20160509232726_cleanup_duplicates_and_add_unique_indexes.rb
index 26b79067b..4e17deb71 100644
--- a/db/migrate/20160509232726_cleanup_duplicates_and_add_unique_indexes.rb
+++ b/db/migrate/20160509232726_cleanup_duplicates_and_add_unique_indexes.rb
@@ -1,4 +1,4 @@
-class CleanupDuplicatesAndAddUniqueIndexes < ActiveRecord::Migration
+class CleanupDuplicatesAndAddUniqueIndexes < ActiveRecord::Migration[4.2]
def up
# temporary index to speed up the migration
add_index :photos, :guid, length: 191
diff --git a/db/migrate/20160531170531_remove_duplicate_aspect_visibilities.rb b/db/migrate/20160531170531_remove_duplicate_aspect_visibilities.rb
index 8269606be..40306c898 100644
--- a/db/migrate/20160531170531_remove_duplicate_aspect_visibilities.rb
+++ b/db/migrate/20160531170531_remove_duplicate_aspect_visibilities.rb
@@ -1,4 +1,4 @@
-class RemoveDuplicateAspectVisibilities < ActiveRecord::Migration
+class RemoveDuplicateAspectVisibilities < ActiveRecord::Migration[4.2]
def up
where = "WHERE a1.aspect_id = a2.aspect_id AND a1.shareable_id = a2.shareable_id AND "\
"a1.shareable_type = a2.shareable_type AND a1.id > a2.id"
diff --git a/db/migrate/20160618033455_cleanup_participations.rb b/db/migrate/20160618033455_cleanup_participations.rb
index ffe857885..df27d04a7 100644
--- a/db/migrate/20160618033455_cleanup_participations.rb
+++ b/db/migrate/20160618033455_cleanup_participations.rb
@@ -1,5 +1,5 @@
-class CleanupParticipations < ActiveRecord::Migration
- class Participation < ActiveRecord::Base
+class CleanupParticipations < ActiveRecord::Migration[4.2]
+ class Participation < ApplicationRecord
end
def up
@@ -39,6 +39,6 @@ class CleanupParticipations < ActiveRecord::Migration
end
Participation.joins("LEFT OUTER JOIN posts ON posts.id = participations.target_id")
- .where(target_type: "Post").delete_all("posts.id is NULL")
+ .where(target_type: "Post").where("posts.id is NULL").delete_all
end
end
diff --git a/db/migrate/20160720212620_create_signature_tables.rb b/db/migrate/20160720212620_create_signature_tables.rb
index f9e2d6c05..fa843fcdd 100644
--- a/db/migrate/20160720212620_create_signature_tables.rb
+++ b/db/migrate/20160720212620_create_signature_tables.rb
@@ -1,5 +1,5 @@
-class CreateSignatureTables < ActiveRecord::Migration
- class SignatureOrder < ActiveRecord::Base
+class CreateSignatureTables < ActiveRecord::Migration[4.2]
+ class SignatureOrder < ApplicationRecord
end
RELAYABLES = %i(comment like poll_participation).freeze
diff --git a/db/migrate/20160802212635_cleanup_posts_table.rb b/db/migrate/20160802212635_cleanup_posts_table.rb
index 79e473e8e..ffab18c7d 100644
--- a/db/migrate/20160802212635_cleanup_posts_table.rb
+++ b/db/migrate/20160802212635_cleanup_posts_table.rb
@@ -1,4 +1,4 @@
-class CleanupPostsTable < ActiveRecord::Migration
+class CleanupPostsTable < ActiveRecord::Migration[4.2]
def change
remove_index :posts, column: %i(status_message_guid pending),
name: :index_posts_on_status_message_guid_and_pending, length: {status_message_guid: 190}
diff --git a/db/migrate/20160807212443_participation_counter.rb b/db/migrate/20160807212443_participation_counter.rb
index 871a1197f..719458ec7 100644
--- a/db/migrate/20160807212443_participation_counter.rb
+++ b/db/migrate/20160807212443_participation_counter.rb
@@ -1,18 +1,18 @@
-class ParticipationCounter < ActiveRecord::Migration
- class Comment < ActiveRecord::Base
+class ParticipationCounter < ActiveRecord::Migration[4.2]
+ class Comment < ApplicationRecord
end
- class Like < ActiveRecord::Base
+ class Like < ApplicationRecord
end
- class Participation < ActiveRecord::Base
+ class Participation < ApplicationRecord
belongs_to :author, class_name: "Person"
end
- class Poll < ActiveRecord::Base
+ class Poll < ApplicationRecord
end
- class PollParticipation < ActiveRecord::Base
+ class PollParticipation < ApplicationRecord
belongs_to :poll
end
diff --git a/db/migrate/20160810230114_cleanup_invitation_columns_from_users.rb b/db/migrate/20160810230114_cleanup_invitation_columns_from_users.rb
index f51312b2f..2022589fc 100644
--- a/db/migrate/20160810230114_cleanup_invitation_columns_from_users.rb
+++ b/db/migrate/20160810230114_cleanup_invitation_columns_from_users.rb
@@ -1,8 +1,8 @@
-class CleanupInvitationColumnsFromUsers < ActiveRecord::Migration
- class InvitationCode < ActiveRecord::Base
+class CleanupInvitationColumnsFromUsers < ActiveRecord::Migration[4.2]
+ class InvitationCode < ApplicationRecord
end
- class User < ActiveRecord::Base
+ class User < ApplicationRecord
end
def change
@@ -34,7 +34,7 @@ class CleanupInvitationColumnsFromUsers < ActiveRecord::Migration
InvitationCode.where("count < 0").update_all(count: new_counter)
# remove old invitation-users
- User.delete_all(username: nil)
+ User.where(username: nil).delete_all
change_column :users, :username, :string, null: false
end
@@ -47,7 +47,7 @@ class CleanupInvitationColumnsFromUsers < ActiveRecord::Migration
end
def create_invitations_table
- # rubocop:disable Style/ExtraSpacing
+ # rubocop:disable Layout/ExtraSpacing
create_table :invitations, force: :cascade do |t|
t.text :message, limit: 65_535
t.integer :sender_id, limit: 4
@@ -60,7 +60,7 @@ class CleanupInvitationColumnsFromUsers < ActiveRecord::Migration
t.boolean :admin, default: false
t.string :language, limit: 255, default: "en"
end
- # rubocop:enable Style/ExtraSpacing
+ # rubocop:enable Layout/ExtraSpacing
add_index :invitations, :aspect_id, name: :index_invitations_on_aspect_id, using: :btree
add_index :invitations, :recipient_id, name: :index_invitations_on_recipient_id, using: :btree
diff --git a/db/migrate/20160813115514_remove_id_tokens.rb b/db/migrate/20160813115514_remove_id_tokens.rb
index 36689d688..346b2a24b 100644
--- a/db/migrate/20160813115514_remove_id_tokens.rb
+++ b/db/migrate/20160813115514_remove_id_tokens.rb
@@ -1,6 +1,6 @@
require_relative "20150714055110_create_id_tokens"
-class RemoveIdTokens < ActiveRecord::Migration
+class RemoveIdTokens < ActiveRecord::Migration[4.2]
def change
revert CreateIdTokens
end
diff --git a/db/migrate/20160822212739_remove_started_sharing_notifications_without_contact.rb b/db/migrate/20160822212739_remove_started_sharing_notifications_without_contact.rb
index 70a62f68f..ddd1f5b3a 100644
--- a/db/migrate/20160822212739_remove_started_sharing_notifications_without_contact.rb
+++ b/db/migrate/20160822212739_remove_started_sharing_notifications_without_contact.rb
@@ -1,5 +1,5 @@
-class RemoveStartedSharingNotificationsWithoutContact < ActiveRecord::Migration
- class Notification < ActiveRecord::Base
+class RemoveStartedSharingNotificationsWithoutContact < ActiveRecord::Migration[4.2]
+ class Notification < ApplicationRecord
end
def up
@@ -7,6 +7,7 @@ class RemoveStartedSharingNotificationsWithoutContact < ActiveRecord::Migration
.joins("INNER JOIN people ON people.id = notifications.target_id")
.joins("LEFT OUTER JOIN contacts ON contacts.person_id = people.id " \
"AND contacts.user_id = notifications.recipient_id")
- .delete_all("contacts.id IS NULL")
+ .where("contacts.id IS NULL")
+ .delete_all
end
end
diff --git a/db/migrate/20160829170244_add_post_default_to_aspects.rb b/db/migrate/20160829170244_add_post_default_to_aspects.rb
index dcc2d76c6..e86193346 100644
--- a/db/migrate/20160829170244_add_post_default_to_aspects.rb
+++ b/db/migrate/20160829170244_add_post_default_to_aspects.rb
@@ -1,4 +1,4 @@
-class AddPostDefaultToAspects < ActiveRecord::Migration
+class AddPostDefaultToAspects < ActiveRecord::Migration[4.2]
def change
add_column :aspects, :post_default, :boolean, default: true
add_column :users, :post_default_public, :boolean, default: false
diff --git a/db/migrate/20160901072443_add_video_url_to_open_graph_cache.rb b/db/migrate/20160901072443_add_video_url_to_open_graph_cache.rb
index 487248a26..eb123a6b3 100644
--- a/db/migrate/20160901072443_add_video_url_to_open_graph_cache.rb
+++ b/db/migrate/20160901072443_add_video_url_to_open_graph_cache.rb
@@ -1,4 +1,4 @@
-class AddVideoUrlToOpenGraphCache < ActiveRecord::Migration
+class AddVideoUrlToOpenGraphCache < ActiveRecord::Migration[4.2]
def change
add_column :open_graph_caches, :video_url, :text
end
diff --git a/db/migrate/20160902180630_remove_invalid_unconfirmed_emails.rb b/db/migrate/20160902180630_remove_invalid_unconfirmed_emails.rb
index 086531c16..27a7feecf 100644
--- a/db/migrate/20160902180630_remove_invalid_unconfirmed_emails.rb
+++ b/db/migrate/20160902180630_remove_invalid_unconfirmed_emails.rb
@@ -1,5 +1,5 @@
-class RemoveInvalidUnconfirmedEmails < ActiveRecord::Migration
- class User < ActiveRecord::Base
+class RemoveInvalidUnconfirmedEmails < ActiveRecord::Migration[4.2]
+ class User < ApplicationRecord
end
def up
diff --git a/db/migrate/20160906225138_fix_photos_share_visibilities.rb b/db/migrate/20160906225138_fix_photos_share_visibilities.rb
index 3621fe28b..ff382a7d5 100644
--- a/db/migrate/20160906225138_fix_photos_share_visibilities.rb
+++ b/db/migrate/20160906225138_fix_photos_share_visibilities.rb
@@ -1,8 +1,8 @@
-class FixPhotosShareVisibilities < ActiveRecord::Migration
- class Photo < ActiveRecord::Base
+class FixPhotosShareVisibilities < ActiveRecord::Migration[4.2]
+ class Photo < ApplicationRecord
end
- class ShareVisibility < ActiveRecord::Base
+ class ShareVisibility < ApplicationRecord
end
def up
diff --git a/db/migrate/20161015174300_remove_empty_pod.rb b/db/migrate/20161015174300_remove_empty_pod.rb
index 482b4f5db..ba7369bc1 100644
--- a/db/migrate/20161015174300_remove_empty_pod.rb
+++ b/db/migrate/20161015174300_remove_empty_pod.rb
@@ -1,6 +1,6 @@
-class RemoveEmptyPod < ActiveRecord::Migration
+class RemoveEmptyPod < ActiveRecord::Migration[4.2]
def up
- Pod.delete_all("host IS NULL")
+ Pod.where("host IS NULL").delete_all
change_column :pods, :host, :string, null: false
end
diff --git a/db/migrate/20161024231443_add_scheduled_check_to_pod.rb b/db/migrate/20161024231443_add_scheduled_check_to_pod.rb
index 6d18ba228..b080564b7 100644
--- a/db/migrate/20161024231443_add_scheduled_check_to_pod.rb
+++ b/db/migrate/20161024231443_add_scheduled_check_to_pod.rb
@@ -1,4 +1,4 @@
-class AddScheduledCheckToPod < ActiveRecord::Migration
+class AddScheduledCheckToPod < ActiveRecord::Migration[4.2]
def change
add_column :pods, :scheduled_check, :boolean, default: false, null: false
end
diff --git a/db/migrate/20161107100840_polymorphic_mentions.rb b/db/migrate/20161107100840_polymorphic_mentions.rb
new file mode 100644
index 000000000..99f65d822
--- /dev/null
+++ b/db/migrate/20161107100840_polymorphic_mentions.rb
@@ -0,0 +1,39 @@
+class PolymorphicMentions < ActiveRecord::Migration[4.2]
+ def change
+ remove_index :mentions, column: %i(post_id)
+ remove_index :mentions, column: %i(person_id post_id), unique: true
+ rename_column :mentions, :post_id, :mentions_container_id
+ add_column :mentions, :mentions_container_type, :string
+ add_index :mentions,
+ %i(mentions_container_id mentions_container_type),
+ name: "index_mentions_on_mc_id_and_mc_type",
+ length: {mentions_container_type: 191}
+ add_index :mentions,
+ %i(person_id mentions_container_id mentions_container_type),
+ name: "index_mentions_on_person_and_mc_id_and_mc_type",
+ length: {mentions_container_type: 191},
+ unique: true
+
+ reversible(&method(:up_down))
+ end
+
+ class Mention < ApplicationRecord
+ end
+
+ class Notification < ApplicationRecord
+ end
+
+ def up_down(change)
+ change.up do
+ Mention.update_all(mentions_container_type: "Post")
+ change_column :mentions, :mentions_container_type, :string, null: false
+ Notification.where(type: "Notifications::Mentioned").update_all(type: "Notifications::MentionedInPost")
+ end
+
+ change.down do
+ Notification.where(type: "Notifications::MentionedInPost").update_all(type: "Notifications::Mentioned")
+ Mention.where(mentions_container_type: "Comment").destroy_all
+ Notification.where(type: "Notifications::MentionedInComment").destroy_all
+ end
+ end
+end
diff --git a/db/migrate/20170430022507_remove_message_signature.rb b/db/migrate/20170430022507_remove_message_signature.rb
new file mode 100644
index 000000000..a8e65c2e0
--- /dev/null
+++ b/db/migrate/20170430022507_remove_message_signature.rb
@@ -0,0 +1,5 @@
+class RemoveMessageSignature < ActiveRecord::Migration[4.2]
+ def change
+ remove_column :messages, :author_signature, :text
+ end
+end
diff --git a/db/migrate/20170730154117_create_account_migrations.rb b/db/migrate/20170730154117_create_account_migrations.rb
new file mode 100644
index 000000000..b01eadbc6
--- /dev/null
+++ b/db/migrate/20170730154117_create_account_migrations.rb
@@ -0,0 +1,14 @@
+class CreateAccountMigrations < ActiveRecord::Migration[5.1]
+ def change
+ create_table :account_migrations do |t|
+ t.integer :old_person_id, null: false
+ t.integer :new_person_id, null: false
+ end
+
+ add_foreign_key :account_migrations, :people, column: :old_person_id
+ add_foreign_key :account_migrations, :people, column: :new_person_id
+
+ add_index :account_migrations, %i[old_person_id new_person_id], unique: true
+ add_index :account_migrations, :old_person_id, unique: true
+ end
+end
diff --git a/db/migrate/20170813141631_cleanup_account_deletions_and_add_unique_index.rb b/db/migrate/20170813141631_cleanup_account_deletions_and_add_unique_index.rb
new file mode 100644
index 000000000..6d188278d
--- /dev/null
+++ b/db/migrate/20170813141631_cleanup_account_deletions_and_add_unique_index.rb
@@ -0,0 +1,19 @@
+class CleanupAccountDeletionsAndAddUniqueIndex < ActiveRecord::Migration[5.1]
+ def up
+ remove_column :account_deletions, :diaspora_handle
+
+ duplicate_query = "WHERE a1.person_id = a2.person_id AND a1.id > a2.id"
+ if AppConfig.postgres?
+ execute("DELETE FROM account_deletions AS a1 USING account_deletions AS a2 #{duplicate_query}")
+ else
+ execute("DELETE a1 FROM account_deletions a1, account_deletions a2 #{duplicate_query}")
+ end
+
+ add_index :account_deletions, :person_id, name: :index_account_deletions_on_person_id, unique: true
+ end
+
+ def down
+ remove_index :account_deletions, name: :index_account_deletions_on_person_id
+ add_column :account_deletions, :diaspora_handle, :string
+ end
+end
diff --git a/db/migrate/20170813153048_add_missing_indexes.rb b/db/migrate/20170813153048_add_missing_indexes.rb
new file mode 100644
index 000000000..9da177a30
--- /dev/null
+++ b/db/migrate/20170813153048_add_missing_indexes.rb
@@ -0,0 +1,7 @@
+class AddMissingIndexes < ActiveRecord::Migration[5.1]
+ def change
+ add_index :photos, :author_id
+ add_index :user_preferences, %i[user_id email_type], length: {email_type: 190}
+ add_index :locations, :status_message_id
+ end
+end
diff --git a/db/migrate/20170813160104_cleanup_aspects_and_add_unique_index.rb b/db/migrate/20170813160104_cleanup_aspects_and_add_unique_index.rb
new file mode 100644
index 000000000..324f43a09
--- /dev/null
+++ b/db/migrate/20170813160104_cleanup_aspects_and_add_unique_index.rb
@@ -0,0 +1,21 @@
+class CleanupAspectsAndAddUniqueIndex < ActiveRecord::Migration[5.1]
+ class Aspect < ApplicationRecord
+ end
+
+ def up
+ cleanup_aspects
+ add_index :aspects, %i[user_id name], name: :index_aspects_on_user_id_and_name, length: {name: 190}, unique: true
+ end
+
+ def down
+ remove_index :aspects, name: :index_aspects_on_user_id_and_name
+ end
+
+ def cleanup_aspects
+ Aspect.where(user_id: 0).delete_all
+ Aspect.joins("INNER JOIN aspects as a2 ON aspects.user_id = a2.user_id AND aspects.name = a2.name")
+ .where("aspects.id > a2.id").each do |aspect|
+ aspect.update_attributes(name: "#{aspect.name}_#{UUID.generate(:compact)}")
+ end
+ end
+end
diff --git a/db/migrate/20170813164435_add_missing_unique_indexes.rb b/db/migrate/20170813164435_add_missing_unique_indexes.rb
new file mode 100644
index 000000000..4c853fbf1
--- /dev/null
+++ b/db/migrate/20170813164435_add_missing_unique_indexes.rb
@@ -0,0 +1,41 @@
+class AddMissingUniqueIndexes < ActiveRecord::Migration[5.1]
+ def up
+ cleanup
+
+ remove_index :aspect_visibilities, name: :shareable_and_aspect_id
+ add_index :aspect_visibilities, %i[shareable_id shareable_type aspect_id],
+ name: :index_aspect_visibilities_on_shareable_and_aspect_id,
+ length: {shareable_type: 189}, unique: true
+
+ add_index :blocks, %i[user_id person_id], name: :index_blocks_on_user_id_and_person_id, unique: true
+
+ add_index :roles, %i[person_id name], name: :index_roles_on_person_id_and_name, length: {name: 190}, unique: true
+ end
+
+ def down
+ remove_index :aspect_visibilities, name: :index_aspect_visibilities_on_shareable_and_aspect_id
+ add_index :aspect_visibilities, %i[shareable_id shareable_type aspect_id], name: :shareable_and_aspect_id,
+ length: {shareable_type: 189}, unique: true
+
+ remove_index :blocks, name: :index_blocks_on_user_id_and_person_id
+
+ remove_index :roles, name: :index_roles_on_person_id_and_name
+ end
+
+ def cleanup
+ aspect_visibilities_where = "WHERE a1.shareable_id = a2.shareable_id AND a1.shareable_type = a2.shareable_type " \
+ "AND a1.aspect_id = a2.aspect_id AND a1.id > a2.id"
+ blocks_where = "WHERE b1.user_id = b2.user_id AND b1.person_id = b2.person_id AND b1.id > b2.id"
+ roles_where = "WHERE r1.person_id = r2.person_id AND r1.name = r2.name AND r1.id > r2.id"
+
+ if AppConfig.postgres?
+ execute "DELETE FROM aspect_visibilities AS a1 USING aspect_visibilities AS a2 #{aspect_visibilities_where}"
+ execute "DELETE FROM blocks AS b1 USING blocks AS b2 #{blocks_where}"
+ execute "DELETE FROM roles AS r1 USING roles AS r2 #{roles_where}"
+ else
+ execute "DELETE a1 FROM aspect_visibilities a1, aspect_visibilities a2 #{aspect_visibilities_where}"
+ execute "DELETE b1 FROM blocks b1, blocks b2 #{blocks_where}"
+ execute "DELETE r1 FROM roles r1, roles r2 #{roles_where}"
+ end
+ end
+end
diff --git a/db/migrate/20170813222333_reset_export_states.rb b/db/migrate/20170813222333_reset_export_states.rb
new file mode 100644
index 000000000..12a7e5789
--- /dev/null
+++ b/db/migrate/20170813222333_reset_export_states.rb
@@ -0,0 +1,12 @@
+class ResetExportStates < ActiveRecord::Migration[5.1]
+ class User < ApplicationRecord
+ end
+
+ def up
+ # rubocop:disable Rails/SkipsModelValidations
+ User.where(exporting: true).update_all(exporting: false, export: nil, exported_at: nil)
+ User.where(exporting_photos: true)
+ .update_all(exporting_photos: false, exported_photos_file: nil, exported_photos_at: nil)
+ # rubocop:enable Rails/SkipsModelValidations
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
deleted file mode 100644
index 402f53db2..000000000
--- a/db/schema.rb
+++ /dev/null
@@ -1,675 +0,0 @@
-# encoding: UTF-8
-# This file is auto-generated from the current state of the database. Instead
-# of editing this file, please use the migrations feature of Active Record to
-# incrementally modify your database, and then regenerate this schema definition.
-#
-# Note that this schema.rb definition is the authoritative source for your
-# database schema. If you need to create the application database on another
-# system, you should be using db:schema:load, not running all the migrations
-# from scratch. The latter is a flawed and unsustainable approach (the more migrations
-# you'll amass, the slower it'll run and the greater likelihood for issues).
-#
-# It's strongly recommended that you check this file into your version control system.
-
-ActiveRecord::Schema.define(version: 20161024231443) do
-
- create_table "account_deletions", force: :cascade do |t|
- t.string "diaspora_handle", limit: 255
- t.integer "person_id", limit: 4
- t.datetime "completed_at"
- end
-
- create_table "aspect_memberships", force: :cascade do |t|
- t.integer "aspect_id", limit: 4, null: false
- t.integer "contact_id", limit: 4, null: false
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
- end
-
- add_index "aspect_memberships", ["aspect_id", "contact_id"], name: "index_aspect_memberships_on_aspect_id_and_contact_id", unique: true, using: :btree
- add_index "aspect_memberships", ["aspect_id"], name: "index_aspect_memberships_on_aspect_id", using: :btree
- add_index "aspect_memberships", ["contact_id"], name: "index_aspect_memberships_on_contact_id", using: :btree
-
- create_table "aspect_visibilities", force: :cascade do |t|
- t.integer "shareable_id", limit: 4, null: false
- t.integer "aspect_id", limit: 4, null: false
- t.string "shareable_type", limit: 255, default: "Post", null: false
- end
-
- add_index "aspect_visibilities", ["aspect_id"], name: "index_aspect_visibilities_on_aspect_id", using: :btree
- add_index "aspect_visibilities", ["shareable_id", "shareable_type", "aspect_id"], name: "shareable_and_aspect_id", length: {"shareable_id"=>nil, "shareable_type"=>189, "aspect_id"=>nil}, using: :btree
- add_index "aspect_visibilities", ["shareable_id", "shareable_type"], name: "index_aspect_visibilities_on_shareable_id_and_shareable_type", length: {"shareable_id"=>nil, "shareable_type"=>190}, using: :btree
-
- create_table "aspects", force: :cascade do |t|
- t.string "name", limit: 255, null: false
- t.integer "user_id", limit: 4, null: false
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
- t.boolean "contacts_visible", default: true, null: false
- t.integer "order_id", limit: 4
- t.boolean "chat_enabled", default: false
- t.boolean "post_default", default: true
- end
-
- add_index "aspects", ["user_id", "contacts_visible"], name: "index_aspects_on_user_id_and_contacts_visible", using: :btree
- add_index "aspects", ["user_id"], name: "index_aspects_on_user_id", using: :btree
-
- create_table "authorizations", force: :cascade do |t|
- t.integer "user_id", limit: 4
- t.integer "o_auth_application_id", limit: 4
- t.string "refresh_token", limit: 255
- t.string "code", limit: 255
- t.string "redirect_uri", limit: 255
- t.string "nonce", limit: 255
- t.string "scopes", limit: 255
- t.boolean "code_used", default: false
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
- end
-
- add_index "authorizations", ["o_auth_application_id"], name: "index_authorizations_on_o_auth_application_id", using: :btree
- add_index "authorizations", ["user_id"], name: "index_authorizations_on_user_id", using: :btree
-
- create_table "blocks", force: :cascade do |t|
- t.integer "user_id", limit: 4
- t.integer "person_id", limit: 4
- end
-
- create_table "chat_contacts", force: :cascade do |t|
- t.integer "user_id", limit: 4, null: false
- t.string "jid", limit: 255, null: false
- t.string "name", limit: 255
- t.string "ask", limit: 128
- t.string "subscription", limit: 128, null: false
- end
-
- add_index "chat_contacts", ["user_id", "jid"], name: "index_chat_contacts_on_user_id_and_jid", unique: true, length: {"user_id"=>nil, "jid"=>190}, using: :btree
-
- create_table "chat_fragments", force: :cascade do |t|
- t.integer "user_id", limit: 4, null: false
- t.string "root", limit: 256, null: false
- t.string "namespace", limit: 256, null: false
- t.text "xml", limit: 65535, null: false
- end
-
- add_index "chat_fragments", ["user_id"], name: "index_chat_fragments_on_user_id", unique: true, using: :btree
-
- create_table "chat_offline_messages", force: :cascade do |t|
- t.string "from", limit: 255, null: false
- t.string "to", limit: 255, null: false
- t.text "message", limit: 65535, null: false
- t.datetime "created_at", null: false
- end
-
- create_table "comment_signatures", id: false, force: :cascade do |t|
- t.integer "comment_id", limit: 4, null: false
- t.text "author_signature", limit: 65535, null: false
- t.integer "signature_order_id", limit: 4, null: false
- t.text "additional_data", limit: 65535
- end
-
- add_index "comment_signatures", ["comment_id"], name: "index_comment_signatures_on_comment_id", unique: true, using: :btree
- add_index "comment_signatures", ["signature_order_id"], name: "comment_signatures_signature_orders_id_fk", using: :btree
-
- create_table "comments", force: :cascade do |t|
- t.text "text", limit: 65535, null: false
- t.integer "commentable_id", limit: 4, null: false
- t.integer "author_id", limit: 4, null: false
- t.string "guid", limit: 255, null: false
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
- t.integer "likes_count", limit: 4, default: 0, null: false
- t.string "commentable_type", limit: 60, default: "Post", null: false
- end
-
- add_index "comments", ["author_id"], name: "index_comments_on_person_id", using: :btree
- add_index "comments", ["commentable_id", "commentable_type"], name: "index_comments_on_commentable_id_and_commentable_type", using: :btree
- add_index "comments", ["guid"], name: "index_comments_on_guid", unique: true, length: {"guid"=>191}, using: :btree
-
- create_table "contacts", force: :cascade do |t|
- t.integer "user_id", limit: 4, null: false
- t.integer "person_id", limit: 4, null: false
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
- t.boolean "sharing", default: false, null: false
- t.boolean "receiving", default: false, null: false
- end
-
- add_index "contacts", ["person_id"], name: "index_contacts_on_person_id", using: :btree
- add_index "contacts", ["user_id", "person_id"], name: "index_contacts_on_user_id_and_person_id", unique: true, using: :btree
-
- create_table "conversation_visibilities", force: :cascade do |t|
- t.integer "conversation_id", limit: 4, null: false
- t.integer "person_id", limit: 4, null: false
- t.integer "unread", limit: 4, default: 0, null: false
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
- end
-
- add_index "conversation_visibilities", ["conversation_id", "person_id"], name: "index_conversation_visibilities_usefully", unique: true, using: :btree
- add_index "conversation_visibilities", ["conversation_id"], name: "index_conversation_visibilities_on_conversation_id", using: :btree
- add_index "conversation_visibilities", ["person_id"], name: "index_conversation_visibilities_on_person_id", using: :btree
-
- create_table "conversations", force: :cascade do |t|
- t.string "subject", limit: 255
- t.string "guid", limit: 255, null: false
- t.integer "author_id", limit: 4, null: false
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
- end
-
- add_index "conversations", ["author_id"], name: "conversations_author_id_fk", using: :btree
- add_index "conversations", ["guid"], name: "index_conversations_on_guid", unique: true, length: {"guid"=>191}, using: :btree
-
- create_table "invitation_codes", force: :cascade do |t|
- t.string "token", limit: 255
- t.integer "user_id", limit: 4
- t.integer "count", limit: 4
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
- end
-
- create_table "like_signatures", id: false, force: :cascade do |t|
- t.integer "like_id", limit: 4, null: false
- t.text "author_signature", limit: 65535, null: false
- t.integer "signature_order_id", limit: 4, null: false
- t.text "additional_data", limit: 65535
- end
-
- add_index "like_signatures", ["like_id"], name: "index_like_signatures_on_like_id", unique: true, using: :btree
- add_index "like_signatures", ["signature_order_id"], name: "like_signatures_signature_orders_id_fk", using: :btree
-
- create_table "likes", force: :cascade do |t|
- t.boolean "positive", default: true
- t.integer "target_id", limit: 4
- t.integer "author_id", limit: 4
- t.string "guid", limit: 255
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
- t.string "target_type", limit: 60, null: false
- end
-
- add_index "likes", ["author_id"], name: "likes_author_id_fk", using: :btree
- add_index "likes", ["guid"], name: "index_likes_on_guid", unique: true, length: {"guid"=>191}, using: :btree
- add_index "likes", ["target_id", "author_id", "target_type"], name: "index_likes_on_target_id_and_author_id_and_target_type", unique: true, using: :btree
- add_index "likes", ["target_id"], name: "index_likes_on_post_id", using: :btree
-
- create_table "locations", force: :cascade do |t|
- t.string "address", limit: 255
- t.string "lat", limit: 255
- t.string "lng", limit: 255
- t.integer "status_message_id", limit: 4
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
- end
-
- create_table "mentions", force: :cascade do |t|
- t.integer "post_id", limit: 4, null: false
- t.integer "person_id", limit: 4, null: false
- end
-
- add_index "mentions", ["person_id", "post_id"], name: "index_mentions_on_person_id_and_post_id", unique: true, using: :btree
- add_index "mentions", ["person_id"], name: "index_mentions_on_person_id", using: :btree
- add_index "mentions", ["post_id"], name: "index_mentions_on_post_id", using: :btree
-
- create_table "messages", force: :cascade do |t|
- t.integer "conversation_id", limit: 4, null: false
- t.integer "author_id", limit: 4, null: false
- t.string "guid", limit: 255, null: false
- t.text "text", limit: 65535, null: false
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
- t.text "author_signature", limit: 65535
- end
-
- add_index "messages", ["author_id"], name: "index_messages_on_author_id", using: :btree
- add_index "messages", ["conversation_id"], name: "messages_conversation_id_fk", using: :btree
- add_index "messages", ["guid"], name: "index_messages_on_guid", unique: true, length: {"guid"=>191}, using: :btree
-
- create_table "notification_actors", force: :cascade do |t|
- t.integer "notification_id", limit: 4
- t.integer "person_id", limit: 4
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
- end
-
- add_index "notification_actors", ["notification_id", "person_id"], name: "index_notification_actors_on_notification_id_and_person_id", unique: true, using: :btree
- add_index "notification_actors", ["notification_id"], name: "index_notification_actors_on_notification_id", using: :btree
- add_index "notification_actors", ["person_id"], name: "index_notification_actors_on_person_id", using: :btree
-
- create_table "notifications", force: :cascade do |t|
- t.string "target_type", limit: 255
- t.integer "target_id", limit: 4
- t.integer "recipient_id", limit: 4, null: false
- t.boolean "unread", default: true, null: false
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
- t.string "type", limit: 255
- end
-
- add_index "notifications", ["recipient_id"], name: "index_notifications_on_recipient_id", using: :btree
- add_index "notifications", ["target_id"], name: "index_notifications_on_target_id", using: :btree
- add_index "notifications", ["target_type", "target_id"], name: "index_notifications_on_target_type_and_target_id", length: {"target_type"=>190, "target_id"=>nil}, using: :btree
-
- create_table "o_auth_access_tokens", force: :cascade do |t|
- t.integer "authorization_id", limit: 4
- t.string "token", limit: 255
- t.datetime "expires_at"
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
- end
-
- add_index "o_auth_access_tokens", ["authorization_id"], name: "index_o_auth_access_tokens_on_authorization_id", using: :btree
- add_index "o_auth_access_tokens", ["token"], name: "index_o_auth_access_tokens_on_token", unique: true, length: {"token"=>191}, using: :btree
-
- create_table "o_auth_applications", force: :cascade do |t|
- t.integer "user_id", limit: 4
- t.string "client_id", limit: 255
- t.string "client_secret", limit: 255
- t.string "client_name", limit: 255
- t.text "redirect_uris", limit: 65535
- t.string "response_types", limit: 255
- t.string "grant_types", limit: 255
- t.string "application_type", limit: 255, default: "web"
- t.string "contacts", limit: 255
- t.string "logo_uri", limit: 255
- t.string "client_uri", limit: 255
- t.string "policy_uri", limit: 255
- t.string "tos_uri", limit: 255
- t.string "sector_identifier_uri", limit: 255
- t.string "token_endpoint_auth_method", limit: 255
- t.text "jwks", limit: 65535
- t.string "jwks_uri", limit: 255
- t.boolean "ppid", default: false
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
- end
-
- add_index "o_auth_applications", ["client_id"], name: "index_o_auth_applications_on_client_id", unique: true, length: {"client_id"=>191}, using: :btree
- add_index "o_auth_applications", ["user_id"], name: "index_o_auth_applications_on_user_id", using: :btree
-
- create_table "o_embed_caches", force: :cascade do |t|
- t.string "url", limit: 1024, null: false
- t.text "data", limit: 65535, null: false
- end
-
- add_index "o_embed_caches", ["url"], name: "index_o_embed_caches_on_url", length: {"url"=>191}, using: :btree
-
- create_table "open_graph_caches", force: :cascade do |t|
- t.string "title", limit: 255
- t.string "ob_type", limit: 255
- t.text "image", limit: 65535
- t.text "url", limit: 65535
- t.text "description", limit: 65535
- t.text "video_url", limit: 65535
- end
-
- create_table "participations", force: :cascade do |t|
- t.string "guid", limit: 255
- t.integer "target_id", limit: 4
- t.string "target_type", limit: 60, null: false
- t.integer "author_id", limit: 4
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
- t.integer "count", limit: 4, default: 1, null: false
- end
-
- add_index "participations", ["author_id"], name: "index_participations_on_author_id", using: :btree
- add_index "participations", ["guid"], name: "index_participations_on_guid", length: {"guid"=>191}, using: :btree
- add_index "participations", ["target_id", "target_type", "author_id"], name: "index_participations_on_target_id_and_target_type_and_author_id", unique: true, using: :btree
-
- create_table "people", force: :cascade do |t|
- t.string "guid", limit: 255, null: false
- t.string "diaspora_handle", limit: 255, null: false
- t.text "serialized_public_key", limit: 65535, null: false
- t.integer "owner_id", limit: 4
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
- t.boolean "closed_account", default: false
- t.integer "fetch_status", limit: 4, default: 0
- t.integer "pod_id", limit: 4
- end
-
- add_index "people", ["diaspora_handle"], name: "index_people_on_diaspora_handle", unique: true, length: {"diaspora_handle"=>191}, using: :btree
- add_index "people", ["guid"], name: "index_people_on_guid", unique: true, length: {"guid"=>191}, using: :btree
- add_index "people", ["owner_id"], name: "index_people_on_owner_id", unique: true, using: :btree
- add_index "people", ["pod_id"], name: "people_pod_id_fk", using: :btree
-
- create_table "photos", force: :cascade do |t|
- t.integer "author_id", limit: 4, null: false
- t.boolean "public", default: false, null: false
- t.string "guid", limit: 255, null: false
- t.boolean "pending", default: false, null: false
- t.text "text", limit: 65535
- t.text "remote_photo_path", limit: 65535
- t.string "remote_photo_name", limit: 255
- t.string "random_string", limit: 255
- t.string "processed_image", limit: 255
- t.datetime "created_at"
- t.datetime "updated_at"
- t.string "unprocessed_image", limit: 255
- t.string "status_message_guid", limit: 255
- t.integer "comments_count", limit: 4
- t.integer "height", limit: 4
- t.integer "width", limit: 4
- end
-
- add_index "photos", ["guid"], name: "index_photos_on_guid", unique: true, length: {"guid"=>191}, using: :btree
- add_index "photos", ["status_message_guid"], name: "index_photos_on_status_message_guid", length: {"status_message_guid"=>191}, using: :btree
-
- create_table "pods", force: :cascade do |t|
- t.string "host", limit: 255, null: false
- t.boolean "ssl"
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
- t.integer "status", limit: 4, default: 0
- t.datetime "checked_at", default: '1970-01-01 00:00:00'
- t.datetime "offline_since"
- t.integer "response_time", limit: 4, default: -1
- t.string "software", limit: 255
- t.string "error", limit: 255
- t.integer "port", limit: 4
- t.boolean "blocked", default: false
- t.boolean "scheduled_check", default: false, null: false
- end
-
- add_index "pods", ["checked_at"], name: "index_pods_on_checked_at", using: :btree
- add_index "pods", ["host", "port"], name: "index_pods_on_host_and_port", unique: true, length: {"host"=>190, "port"=>nil}, using: :btree
- add_index "pods", ["offline_since"], name: "index_pods_on_offline_since", using: :btree
- add_index "pods", ["status"], name: "index_pods_on_status", using: :btree
-
- create_table "poll_answers", force: :cascade do |t|
- t.string "answer", limit: 255, null: false
- t.integer "poll_id", limit: 4, null: false
- t.string "guid", limit: 255
- t.integer "vote_count", limit: 4, default: 0
- end
-
- add_index "poll_answers", ["guid"], name: "index_poll_answers_on_guid", unique: true, length: {"guid"=>191}, using: :btree
- add_index "poll_answers", ["poll_id"], name: "index_poll_answers_on_poll_id", using: :btree
-
- create_table "poll_participation_signatures", id: false, force: :cascade do |t|
- t.integer "poll_participation_id", limit: 4, null: false
- t.text "author_signature", limit: 65535, null: false
- t.integer "signature_order_id", limit: 4, null: false
- t.text "additional_data", limit: 65535
- end
-
- add_index "poll_participation_signatures", ["poll_participation_id"], name: "index_poll_participation_signatures_on_poll_participation_id", unique: true, using: :btree
- add_index "poll_participation_signatures", ["signature_order_id"], name: "poll_participation_signatures_signature_orders_id_fk", using: :btree
-
- create_table "poll_participations", force: :cascade do |t|
- t.integer "poll_answer_id", limit: 4, null: false
- t.integer "author_id", limit: 4, null: false
- t.integer "poll_id", limit: 4, null: false
- t.string "guid", limit: 255
- t.datetime "created_at"
- t.datetime "updated_at"
- end
-
- add_index "poll_participations", ["guid"], name: "index_poll_participations_on_guid", unique: true, length: {"guid"=>191}, using: :btree
- add_index "poll_participations", ["poll_id"], name: "index_poll_participations_on_poll_id", using: :btree
-
- create_table "polls", force: :cascade do |t|
- t.string "question", limit: 255, null: false
- t.integer "status_message_id", limit: 4, null: false
- t.boolean "status"
- t.string "guid", limit: 255
- t.datetime "created_at"
- t.datetime "updated_at"
- end
-
- add_index "polls", ["guid"], name: "index_polls_on_guid", unique: true, length: {"guid"=>191}, using: :btree
- add_index "polls", ["status_message_id"], name: "index_polls_on_status_message_id", using: :btree
-
- create_table "posts", force: :cascade do |t|
- t.integer "author_id", limit: 4, null: false
- t.boolean "public", default: false, null: false
- t.string "guid", limit: 255, null: false
- t.string "type", limit: 40, null: false
- t.text "text", limit: 65535
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
- t.string "provider_display_name", limit: 255
- t.string "root_guid", limit: 255
- t.integer "likes_count", limit: 4, default: 0
- t.integer "comments_count", limit: 4, default: 0
- t.integer "o_embed_cache_id", limit: 4
- t.integer "reshares_count", limit: 4, default: 0
- t.datetime "interacted_at"
- t.string "facebook_id", limit: 255
- t.string "tweet_id", limit: 255
- t.integer "open_graph_cache_id", limit: 4
- t.text "tumblr_ids", limit: 65535
- end
-
- add_index "posts", ["author_id", "root_guid"], name: "index_posts_on_author_id_and_root_guid", unique: true, length: {"author_id"=>nil, "root_guid"=>190}, using: :btree
- add_index "posts", ["author_id"], name: "index_posts_on_person_id", using: :btree
- add_index "posts", ["guid"], name: "index_posts_on_guid", unique: true, length: {"guid"=>191}, using: :btree
- add_index "posts", ["id", "type", "created_at"], name: "index_posts_on_id_and_type_and_created_at", using: :btree
- add_index "posts", ["id", "type"], name: "index_posts_on_id_and_type", using: :btree
- add_index "posts", ["root_guid"], name: "index_posts_on_root_guid", length: {"root_guid"=>191}, using: :btree
- add_index "posts", ["tweet_id"], name: "index_posts_on_tweet_id", length: {"tweet_id"=>191}, using: :btree
-
- create_table "ppid", force: :cascade do |t|
- t.integer "o_auth_application_id", limit: 4
- t.integer "user_id", limit: 4
- t.string "guid", limit: 32
- t.string "string", limit: 32
- t.string "identifier", limit: 255
- end
-
- add_index "ppid", ["o_auth_application_id"], name: "index_ppid_on_o_auth_application_id", using: :btree
- add_index "ppid", ["user_id"], name: "index_ppid_on_user_id", using: :btree
-
- create_table "profiles", force: :cascade do |t|
- t.string "diaspora_handle", limit: 255
- t.string "first_name", limit: 127
- t.string "last_name", limit: 127
- t.string "image_url", limit: 255
- t.string "image_url_small", limit: 255
- t.string "image_url_medium", limit: 255
- t.date "birthday"
- t.string "gender", limit: 255
- t.text "bio", limit: 65535
- t.boolean "searchable", default: true, null: false
- t.integer "person_id", limit: 4, null: false
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
- t.string "location", limit: 255
- t.string "full_name", limit: 70
- t.boolean "nsfw", default: false
- t.boolean "public_details", default: false
- end
-
- add_index "profiles", ["full_name", "searchable"], name: "index_profiles_on_full_name_and_searchable", using: :btree
- add_index "profiles", ["full_name"], name: "index_profiles_on_full_name", using: :btree
- add_index "profiles", ["person_id"], name: "index_profiles_on_person_id", using: :btree
-
- create_table "rails_admin_histories", force: :cascade do |t|
- t.text "message", limit: 65535
- t.string "username", limit: 255
- t.integer "item", limit: 4
- t.string "table", limit: 255
- t.integer "month", limit: 2
- t.integer "year", limit: 8
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
- end
-
- add_index "rails_admin_histories", ["item", "table", "month", "year"], name: "index_rails_admin_histories", length: {"item"=>nil, "table"=>188, "month"=>nil, "year"=>nil}, using: :btree
-
- create_table "reports", force: :cascade do |t|
- t.integer "item_id", limit: 4, null: false
- t.string "item_type", limit: 255, null: false
- t.boolean "reviewed", default: false
- t.text "text", limit: 65535
- t.datetime "created_at"
- t.datetime "updated_at"
- t.integer "user_id", limit: 4, null: false
- end
-
- add_index "reports", ["item_id"], name: "index_reports_on_item_id", using: :btree
-
- create_table "roles", force: :cascade do |t|
- t.integer "person_id", limit: 4
- t.string "name", limit: 255
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
- end
-
- create_table "services", force: :cascade do |t|
- t.string "type", limit: 127, null: false
- t.integer "user_id", limit: 4, null: false
- t.string "uid", limit: 127
- t.string "access_token", limit: 255
- t.string "access_secret", limit: 255
- t.string "nickname", limit: 255
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
- end
-
- add_index "services", ["type", "uid"], name: "index_services_on_type_and_uid", length: {"type"=>64, "uid"=>nil}, using: :btree
- add_index "services", ["user_id"], name: "index_services_on_user_id", using: :btree
-
- create_table "share_visibilities", force: :cascade do |t|
- t.integer "shareable_id", limit: 4, null: false
- t.boolean "hidden", default: false, null: false
- t.string "shareable_type", limit: 60, default: "Post", null: false
- t.integer "user_id", limit: 4, null: false
- end
-
- add_index "share_visibilities", ["shareable_id", "shareable_type", "hidden", "user_id"], name: "shareable_and_hidden_and_user_id", using: :btree
- add_index "share_visibilities", ["shareable_id", "shareable_type", "user_id"], name: "shareable_and_user_id", unique: true, using: :btree
- add_index "share_visibilities", ["shareable_id"], name: "index_post_visibilities_on_post_id", using: :btree
- add_index "share_visibilities", ["user_id"], name: "index_share_visibilities_on_user_id", using: :btree
-
- create_table "signature_orders", force: :cascade do |t|
- t.string "order", limit: 255, null: false
- end
-
- add_index "signature_orders", ["order"], name: "index_signature_orders_on_order", unique: true, length: {"order"=>191}, using: :btree
-
- create_table "simple_captcha_data", force: :cascade do |t|
- t.string "key", limit: 40
- t.string "value", limit: 12
- t.datetime "created_at"
- t.datetime "updated_at"
- end
-
- add_index "simple_captcha_data", ["key"], name: "idx_key", using: :btree
-
- create_table "tag_followings", force: :cascade do |t|
- t.integer "tag_id", limit: 4, null: false
- t.integer "user_id", limit: 4, null: false
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
- end
-
- add_index "tag_followings", ["tag_id", "user_id"], name: "index_tag_followings_on_tag_id_and_user_id", unique: true, using: :btree
- add_index "tag_followings", ["tag_id"], name: "index_tag_followings_on_tag_id", using: :btree
- add_index "tag_followings", ["user_id"], name: "index_tag_followings_on_user_id", using: :btree
-
- create_table "taggings", force: :cascade do |t|
- t.integer "tag_id", limit: 4
- t.integer "taggable_id", limit: 4
- t.string "taggable_type", limit: 127
- t.integer "tagger_id", limit: 4
- t.string "tagger_type", limit: 127
- t.string "context", limit: 127
- t.datetime "created_at"
- end
-
- add_index "taggings", ["created_at"], name: "index_taggings_on_created_at", using: :btree
- add_index "taggings", ["tag_id"], name: "index_taggings_on_tag_id", using: :btree
- add_index "taggings", ["taggable_id", "taggable_type", "context"], name: "index_taggings_on_taggable_id_and_taggable_type_and_context", length: {"taggable_id"=>nil, "taggable_type"=>95, "context"=>95}, using: :btree
- add_index "taggings", ["taggable_id", "taggable_type", "tag_id"], name: "index_taggings_uniquely", unique: true, using: :btree
-
- create_table "tags", force: :cascade do |t|
- t.string "name", limit: 255
- t.integer "taggings_count", limit: 4, default: 0
- end
-
- add_index "tags", ["name"], name: "index_tags_on_name", unique: true, length: {"name"=>191}, using: :btree
-
- create_table "user_preferences", force: :cascade do |t|
- t.string "email_type", limit: 255
- t.integer "user_id", limit: 4
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
- end
-
- create_table "users", force: :cascade do |t|
- t.string "username", limit: 255, null: false
- t.text "serialized_private_key", limit: 65535
- t.boolean "getting_started", default: true, null: false
- t.boolean "disable_mail", default: false, null: false
- t.string "language", limit: 255
- t.string "email", limit: 255, default: "", null: false
- t.string "encrypted_password", limit: 255, default: "", null: false
- t.string "reset_password_token", limit: 255
- t.datetime "remember_created_at"
- t.integer "sign_in_count", limit: 4, default: 0
- t.datetime "current_sign_in_at"
- t.datetime "last_sign_in_at"
- t.string "current_sign_in_ip", limit: 255
- t.string "last_sign_in_ip", limit: 255
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
- t.integer "invited_by_id", limit: 4
- t.string "authentication_token", limit: 30
- t.string "unconfirmed_email", limit: 255
- t.string "confirm_email_token", limit: 30
- t.datetime "locked_at"
- t.boolean "show_community_spotlight_in_stream", default: true, null: false
- t.boolean "auto_follow_back", default: false
- t.integer "auto_follow_back_aspect_id", limit: 4
- t.text "hidden_shareables", limit: 65535
- t.datetime "reset_password_sent_at"
- t.datetime "last_seen"
- t.datetime "remove_after"
- t.string "export", limit: 255
- t.datetime "exported_at"
- t.boolean "exporting", default: false
- t.boolean "strip_exif", default: true
- t.string "exported_photos_file", limit: 255
- t.datetime "exported_photos_at"
- t.boolean "exporting_photos", default: false
- t.string "color_theme", limit: 255
- t.boolean "post_default_public", default: false
- end
-
- add_index "users", ["authentication_token"], name: "index_users_on_authentication_token", unique: true, using: :btree
- add_index "users", ["email"], name: "index_users_on_email", unique: true, length: {"email"=>191}, using: :btree
- add_index "users", ["username"], name: "index_users_on_username", unique: true, length: {"username"=>191}, using: :btree
-
- add_foreign_key "aspect_memberships", "aspects", name: "aspect_memberships_aspect_id_fk", on_delete: :cascade
- add_foreign_key "aspect_memberships", "contacts", name: "aspect_memberships_contact_id_fk", on_delete: :cascade
- add_foreign_key "aspect_visibilities", "aspects", name: "aspect_visibilities_aspect_id_fk", on_delete: :cascade
- add_foreign_key "authorizations", "o_auth_applications"
- add_foreign_key "authorizations", "users"
- add_foreign_key "comment_signatures", "comments", name: "comment_signatures_comment_id_fk", on_delete: :cascade
- add_foreign_key "comment_signatures", "signature_orders", name: "comment_signatures_signature_orders_id_fk"
- add_foreign_key "comments", "people", column: "author_id", name: "comments_author_id_fk", on_delete: :cascade
- add_foreign_key "contacts", "people", name: "contacts_person_id_fk", on_delete: :cascade
- add_foreign_key "conversation_visibilities", "conversations", name: "conversation_visibilities_conversation_id_fk", on_delete: :cascade
- add_foreign_key "conversation_visibilities", "people", name: "conversation_visibilities_person_id_fk", on_delete: :cascade
- add_foreign_key "conversations", "people", column: "author_id", name: "conversations_author_id_fk", on_delete: :cascade
- add_foreign_key "like_signatures", "likes", name: "like_signatures_like_id_fk", on_delete: :cascade
- add_foreign_key "like_signatures", "signature_orders", name: "like_signatures_signature_orders_id_fk"
- add_foreign_key "likes", "people", column: "author_id", name: "likes_author_id_fk", on_delete: :cascade
- add_foreign_key "messages", "conversations", name: "messages_conversation_id_fk", on_delete: :cascade
- add_foreign_key "messages", "people", column: "author_id", name: "messages_author_id_fk", on_delete: :cascade
- add_foreign_key "notification_actors", "notifications", name: "notification_actors_notification_id_fk", on_delete: :cascade
- add_foreign_key "o_auth_access_tokens", "authorizations"
- add_foreign_key "o_auth_applications", "users"
- add_foreign_key "people", "pods", name: "people_pod_id_fk", on_delete: :cascade
- add_foreign_key "poll_participation_signatures", "poll_participations", name: "poll_participation_signatures_poll_participation_id_fk", on_delete: :cascade
- add_foreign_key "poll_participation_signatures", "signature_orders", name: "poll_participation_signatures_signature_orders_id_fk"
- add_foreign_key "posts", "people", column: "author_id", name: "posts_author_id_fk", on_delete: :cascade
- add_foreign_key "ppid", "o_auth_applications"
- add_foreign_key "ppid", "users"
- add_foreign_key "profiles", "people", name: "profiles_person_id_fk", on_delete: :cascade
- add_foreign_key "services", "users", name: "services_user_id_fk", on_delete: :cascade
- add_foreign_key "share_visibilities", "users", name: "share_visibilities_user_id_fk", on_delete: :cascade
-end
diff --git a/features/desktop/change_settings.feature b/features/desktop/change_settings.feature
index ba0543908..6bc8ae641 100644
--- a/features/desktop/change_settings.feature
+++ b/features/desktop/change_settings.feature
@@ -22,6 +22,10 @@ Feature: Change settings
And I press "change_email_preferences"
Then I should see "Email notifications changed"
And the "user_email_preferences_mentioned" checkbox should not be checked
+ When I uncheck "user_email_preferences_mentioned_in_comment"
+ And I press "change_email_preferences"
+ Then I should see "Email notifications changed"
+ And the "user_email_preferences_mentioned_in_comment" checkbox should not be checked
Scenario: Change my preferred language
When I select "polski" from "user_language"
@@ -49,3 +53,8 @@ Feature: Change settings
And I go to the stream page
And I expand the publisher
Then I should see "Public" within ".aspect_dropdown"
+
+ Scenario: exporting profile data
+ When I click on the first selector "#account_data a"
+ Then I should see "Download my profile"
+ And I should have 1 email delivery
diff --git a/features/desktop/connects_users.feature b/features/desktop/connects_users.feature
index 60a514e4a..b9f934735 100644
--- a/features/desktop/connects_users.feature
+++ b/features/desktop/connects_users.feature
@@ -35,8 +35,8 @@ Feature: following and being followed
And I fill in "aspect_name" with "Super People" in the aspect creation modal
And I click on selector ".btn-primary" in the aspect creation modal
+ And I wait until ajax requests finished
- When I go to the home page
Then I should have 1 contact in "Super People"
Then I sign out
diff --git a/features/desktop/follows_tags.feature b/features/desktop/follows_tags.feature
index 78692e71c..fcdfbf3a5 100644
--- a/features/desktop/follows_tags.feature
+++ b/features/desktop/follows_tags.feature
@@ -16,7 +16,7 @@ Feature: posting
Then I should see a ".tag-following-action .followed"
Scenario: can post a message from the tag page
- Then I should see "#boss" within "#publisher"
+ Then I should see "#boss " in the publisher
When I click the publisher and post "#boss from the tag page"
And I go to the tag page for "boss"
Then I should see "#boss from the tag page"
diff --git a/features/desktop/invitations.feature b/features/desktop/invitations.feature
index dd38873cc..f01e194e3 100644
--- a/features/desktop/invitations.feature
+++ b/features/desktop/invitations.feature
@@ -52,13 +52,15 @@ Feature: Invitations
Scenario: sends an invitation from the stream
When I sign in as "alice@alice.alice"
- And I press the first "a.invitations-link" within "#no_contacts"
+ Then I should see "There are no posts to display here yet." within ".no-posts-info"
+ When I press the first "a.invitations-link" within "#no_contacts"
Then I should see "Invite someone to join diaspora*!" within "#invitationsModalLabel"
And I fill in the following:
| email_inviter_emails | alex@example.com |
And I press "Send an invitation"
Then I should see a flash message indicating success
And I should have 1 Devise email delivery
+ And I should see "You have been invited to join diaspora* by Alice Smith" in the last sent email
And I should not see "change your notification settings" in the last sent email
Scenario: sends an invitation from the people search page
diff --git a/features/desktop/mentions.feature b/features/desktop/mentions.feature
index 01791180f..d68358b58 100644
--- a/features/desktop/mentions.feature
+++ b/features/desktop/mentions.feature
@@ -54,3 +54,34 @@ Feature: Mentions
Then I should see "Bob Jones" within ".stream-element"
When I follow "Bob Jones"
Then I should see "Bob Jones"
+
+ Scenario: A user mentions another user in a comment and it displays correctly
+ Given following users exist:
+ | username | email |
+ | Bob Jones | bob@bob.bob |
+ | Alice Smith | alice@alice.alice |
+ And a user with email "bob@bob.bob" is connected with "alice@alice.alice"
+ And "alice@alice.alice" has a public post with text "check this out!"
+ And "alice@alice.alice" has commented mentioning "bob@bob.bob" on "check this out!"
+ When I sign in as "alice@alice.alice"
+ And I follow "Bob Jones"
+ Then I should see "Bob Jones"
+
+ Scenario: A user mentions another user in a comment using mention suggestions
+ Given following users exist:
+ | username | email |
+ | Bob Jones | bob@bob.bob |
+ | Alice Smith | alice@alice.alice |
+ And a user with email "bob@bob.bob" is connected with "alice@alice.alice"
+ And "alice@alice.alice" has a public post with text "check this out!"
+ When I sign in as "alice@alice.alice"
+ Then I should see "check this out!"
+ When I focus the comment field
+ And I enter "@Bob" in the comment field
+ Then I should see "Bob Jones" within ".tt-suggestion"
+ When I click on the first user in the mentions dropdown list
+ And I press the "A" key in the publisher
+ And I append "@Bob" to the publisher
+ Then I should not see the mentions dropdown list
+ When I press "Comment"
+ Then I should see "Bob Jones" within ".comments .comment:last-child"
diff --git a/features/desktop/notifications.feature b/features/desktop/notifications.feature
index 2dd5eaee4..7726d3d87 100644
--- a/features/desktop/notifications.feature
+++ b/features/desktop/notifications.feature
@@ -101,6 +101,26 @@ Feature: Notifications
Then I should see "mentioned you in the post"
And I should have 1 email delivery
+ Scenario: someone mentioned me in a comment
+ Given "alice@alice.alice" has a public post with text "check this out!"
+ And "bob@bob.bob" has commented mentioning "alice@alice.alice" on "check this out!"
+ When I sign in as "alice@alice.alice"
+ And I follow "Notifications" in the header
+ Then the notification dropdown should be visible
+ And I should see "mentioned you in a comment"
+ And I should have 1 email delivery
+
+ Scenario: I mark a notification as read
+ Given a user with email "bob@bob.bob" is connected with "alice@alice.alice"
+ And Alice has a post mentioning Bob
+ When I sign in as "bob@bob.bob"
+ And I follow "Notifications" in the header
+ Then the notification dropdown should be visible
+ And I wait for notifications to load
+ And I should see a ".unread .unread-toggle .entypo-eye"
+ When I click on selector ".unread .unread-toggle .entypo-eye"
+ Then I should see a ".read .unread-toggle"
+
Scenario: filter notifications
Given a user with email "bob@bob.bob" is connected with "alice@alice.alice"
And Alice has a post mentioning Bob
@@ -157,6 +177,5 @@ Feature: Notifications
When I wait for notifications to load
Then there should be 10 notifications loaded
When I scroll down on the notifications dropdown
- Then the notification dropdown should load more notifications
When I wait for notifications to load
Then there should be 15 notifications loaded
diff --git a/features/desktop/post_preview.feature b/features/desktop/post_preview.feature
index 827b36d36..d2a69b687 100644
--- a/features/desktop/post_preview.feature
+++ b/features/desktop/post_preview.feature
@@ -44,7 +44,7 @@ Feature: preview posts in the stream
Given I expand the publisher
And I attach "spec/fixtures/button.png" to the publisher
When I fill in the following:
- | status_message_fake_text | Look at this dog |
+ | status_message_text | Look at this dog |
And I preview the post
Then I should see a "img" within ".md-preview .stream-element .photo_attachments"
And I should see "Look at this dog" within ".md-preview .stream-element"
@@ -63,7 +63,7 @@ Feature: preview posts in the stream
Then I should see "Samuel Beckett"
When I expand the publisher
And I fill in the following:
- | status_message_fake_text | This preview rocks |
+ | status_message_text | This preview rocks |
And I preview the post
Then I should see "This preview rocks" in the preview
And I close the publisher
@@ -71,11 +71,11 @@ Feature: preview posts in the stream
Scenario: preview a post with the poll
Given I expand the publisher
When I fill in the following:
- | status_message_fake_text | I am eating yogurt |
+ | status_message_text | I am eating yogurt |
And I click on selector "#poll_creator"
When I fill in the following:
- | status_message_fake_text | I am eating yogurt |
- | poll_question | What kind of yogurt do you like? |
+ | status_message_text | I am eating yogurt |
+ | poll_question | What kind of yogurt do you like? |
And I fill in the following for the options:
| normal |
| not normal |
@@ -87,12 +87,12 @@ Feature: preview posts in the stream
Scenario: preview a post with location
Given I expand the publisher
When I fill in the following:
- | status_message_fake_text | I am eating yogurt |
+ | status_message_text | I am eating yogurt |
And I allow geolocation
And I click on selector "#locator"
When I fill in the following:
- | status_message_fake_text | I am eating yogurt |
- | location_address | Some cool place |
+ | status_message_text | I am eating yogurt |
+ | location_address | Some cool place |
And I preview the post
Then I should see a ".near-from" within ".md-preview .stream-element"
And I should see "Some cool place" within ".md-preview .stream-element .near-from"
diff --git a/features/desktop/post_with_a_poll.feature b/features/desktop/post_with_a_poll.feature
index b5b3a0ff8..5a27fc7ee 100644
--- a/features/desktop/post_with_a_poll.feature
+++ b/features/desktop/post_with_a_poll.feature
@@ -40,8 +40,8 @@ Feature: posting with a poll
Given I expand the publisher
And I click on selector "#poll_creator"
When I fill in the following:
- | status_message_fake_text | I am eating yogurt |
- | poll_question | What kind of yogurt do you like? |
+ | status_message_text | I am eating yogurt |
+ | poll_question | What kind of yogurt do you like? |
And I fill in the following for the options:
| normal |
| not normal |
@@ -53,8 +53,8 @@ Feature: posting with a poll
Given I expand the publisher
And I click on selector "#poll_creator"
When I fill in the following:
- | status_message_fake_text | I am eating yogurt |
- | poll_question | What kind of yogurt do you like? |
+ | status_message_text | I am eating yogurt |
+ | poll_question | What kind of yogurt do you like? |
And I fill in the following for the options:
| normal |
| not normal |
@@ -70,8 +70,8 @@ Feature: posting with a poll
Given I expand the publisher
And I click on selector "#poll_creator"
When I fill in the following:
- | status_message_fake_text | I am eating yogurt |
- | poll_question | What kind of yogurt do you like? |
+ | status_message_text | I am eating yogurt |
+ | poll_question | What kind of yogurt do you like? |
And I fill in the following for the options:
| normal |
| not normal |
@@ -83,8 +83,8 @@ Feature: posting with a poll
Given I expand the publisher
And I click on selector "#poll_creator"
When I fill in the following:
- | status_message_fake_text | I am eating yogurt |
- | poll_question | What kind of yogurt do you like? |
+ | status_message_text | I am eating yogurt |
+ | poll_question | What kind of yogurt do you like? |
And I fill in the following for the options:
| normal |
| |
diff --git a/features/desktop/signs_up.feature b/features/desktop/signs_up.feature
index d68c58f19..bed865064 100644
--- a/features/desktop/signs_up.feature
+++ b/features/desktop/signs_up.feature
@@ -58,6 +58,7 @@ Feature: new user registration
| profile_first_name | some name |
And I fill in "tags" with "#rockstar"
And I press the first ".as-result-item" within "#as-results-tags"
+ And I wait until ajax requests finished
And I follow "awesome_button"
Then I should be on the stream page
And the publisher should be expanded
diff --git a/features/mobile/activity_stream.feature b/features/mobile/activity_stream.feature
index 27475abcd..823b4f7ad 100644
--- a/features/mobile/activity_stream.feature
+++ b/features/mobile/activity_stream.feature
@@ -21,7 +21,8 @@ Feature: Viewing my activity on the stream mobile page
Scenario: Show liked post on my activity
When I sign in as "bob@bob.bob" on the mobile website
When I click on selector "a.like-action.inactive"
- And I go to the activity stream page
+ Then I should see an element "a.like-action.active"
+ When I go to the activity stream page
Then I should see "My activity" within "#main"
And I should see "Hello! I am #newhere" within ".ltr"
diff --git a/features/mobile/drawer.feature b/features/mobile/drawer.feature
index 42f934581..700fc95b8 100644
--- a/features/mobile/drawer.feature
+++ b/features/mobile/drawer.feature
@@ -9,7 +9,7 @@ Feature: Navigate between pages using the header menu and the drawer
Scenario: navigate to the stream page
When I go to the activity stream page
- And I click on selector "#header-title"
+ And I click on selector ".header-title"
Then I should be on the stream page
Scenario: navigate to the notification page
diff --git a/features/mobile/posts_from_main_page.feature b/features/mobile/posts_from_main_page.feature
index 22fb6195a..9afee520d 100644
--- a/features/mobile/posts_from_main_page.feature
+++ b/features/mobile/posts_from_main_page.feature
@@ -20,7 +20,7 @@ Feature: posting from the mobile main page
Scenario: post and delete some text
Given I visit the mobile publisher page
- And I append "I am eating yogurt" to the mobile publisher
+ And I append "I am eating yogurt" to the publisher
And I select "Unicorns" from "aspect_ids_"
And I press "Share"
When I go to the stream page
@@ -52,7 +52,7 @@ Feature: posting from the mobile main page
Scenario: back out of uploading a picture when another has been attached
Given I visit the mobile publisher page
- And I append "I am eating yogurt" to the mobile publisher
+ And I append "I am eating yogurt" to the publisher
And I attach the file "spec/fixtures/button.gif" to hidden "qqfile" within "#file-upload-publisher"
And I attach the file "spec/fixtures/button.png" to hidden "qqfile" within "#file-upload-publisher"
And I click to delete the first uploaded photo
diff --git a/features/step_definitions/aspects_steps.rb b/features/step_definitions/aspects_steps.rb
index 8881cd946..39726a308 100644
--- a/features/step_definitions/aspects_steps.rb
+++ b/features/step_definitions/aspects_steps.rb
@@ -46,8 +46,13 @@ end
When /^I select only "([^"]*)" aspect$/ do |aspect_name|
click_link "My aspects"
+ expect(find("#aspect_stream_container")).to have_css(".loader.hidden", visible: false)
within("#aspects_list") do
- all(".selected").each {|node| node.find(:xpath, "..").click }
+ all(".selected").each do |node|
+ aspect_item = node.find(:xpath, "..")
+ aspect_item.click
+ expect(aspect_item).to have_no_css ".selected"
+ end
expect(current_scope).to have_no_css ".selected"
end
step %Q(I select "#{aspect_name}" aspect as well)
diff --git a/features/step_definitions/comment_steps.rb b/features/step_definitions/comment_steps.rb
index 0d669f1ac..0679e7b3d 100644
--- a/features/step_definitions/comment_steps.rb
+++ b/features/step_definitions/comment_steps.rb
@@ -3,12 +3,12 @@ When /^I focus the comment field$/ do
end
Then /^the first comment field should be open/ do
- find("#main_stream .stream-element .new_comment").should be_visible
+ find("#main_stream .stream-element .new-comment").should be_visible
end
Then /^the first comment field should be closed$/ do
page.should have_css(".stream-element .media")
- page.should_not have_selector("#main_stream .stream-element .new_comment", match: :first)
+ page.should_not have_selector("#main_stream .stream-element .new-comment", match: :first)
end
When /^I make a show page comment "([^"]*)"$/ do |comment_text|
@@ -21,6 +21,12 @@ Given /^"([^"]*)" has commented "([^"]*)" on "([^"]*)"$/ do |email, comment_text
user.comment!(post, comment_text)
end
+Given /^"([^"]*)" has commented mentioning "([^"]*)" on "([^"]*)"$/ do |email, mentionee_email, post_text|
+ user = User.find_by(email: email)
+ post = StatusMessage.find_by(text: post_text)
+ user.comment!(post, text_mentioning(User.find_by(email: mentionee_email)))
+end
+
Given /^"([^"]*)" has commented a lot on "([^"]*)"$/ do |email, post_text|
user = User.find_by(email: email)
post = StatusMessage.find_by(text: post_text)
@@ -32,3 +38,7 @@ Given /^"([^"]*)" has commented a lot on "([^"]*)"$/ do |email, post_text|
end
end
end
+
+When /^I enter "([^"]*)" in the comment field$/ do |comment_text|
+ find("textarea.comment_box.mention-textarea").native.send_keys(comment_text)
+end
diff --git a/features/step_definitions/custom_web_steps.rb b/features/step_definitions/custom_web_steps.rb
index c72deff6a..812a66f34 100644
--- a/features/step_definitions/custom_web_steps.rb
+++ b/features/step_definitions/custom_web_steps.rb
@@ -109,6 +109,7 @@ When /^I click to delete the first post$/ do
accept_alert do
step "I prepare the deletion of the first post"
end
+ expect(find(".stream")).to have_no_css(".stream-element.loaded.deleting")
end
When /^I click to hide the first post$/ do
@@ -176,7 +177,7 @@ end
Then /^(?:|I )should see a "([^\"]*)"(?: within "([^\"]*)")?$/ do |selector, scope_selector|
with_scope(scope_selector) do
- current_scope.should have_css selector
+ expect(current_scope).to have_css(selector)
end
end
diff --git a/features/step_definitions/keyboard_navigation_steps.rb b/features/step_definitions/keyboard_navigation_steps.rb
index e0109902d..32188aff3 100644
--- a/features/step_definitions/keyboard_navigation_steps.rb
+++ b/features/step_definitions/keyboard_navigation_steps.rb
@@ -5,7 +5,7 @@ When /^I press the "([^\"]*)" key somewhere$/ do |key|
end
When /^I press the "([^\"]*)" key in the publisher$/ do |key|
- find("#status_message_fake_text").native.send_key(key)
+ find("#status_message_text").native.send_key(key)
end
Then /^post (\d+) should be highlighted$/ do |position|
diff --git a/features/step_definitions/notifications_steps.rb b/features/step_definitions/notifications_steps.rb
index 87c27ceff..bd38c03f0 100644
--- a/features/step_definitions/notifications_steps.rb
+++ b/features/step_definitions/notifications_steps.rb
@@ -3,7 +3,7 @@ When "I filter notifications by likes" do
end
When "I filter notifications by mentions" do
- step %(I follow "Mentioned" within "#notifications_container .list-group")
+ step %(I follow "Mentioned in post" within "#notifications_container .list-group")
end
Then /^I should( not)? have activated notifications for the post( in the single post view)?$/ do |negate, spv|
@@ -25,10 +25,6 @@ And "I scroll down on the notifications dropdown" do
page.execute_script("$('.notifications').scrollTop(350)")
end
-Then "the notification dropdown should load more notifications" do
- expect(find("#notification-dropdown")).to have_css(".loading")
-end
-
Then "the notification dropdown should be visible" do
expect(find(:css, "#notification-dropdown")).to be_visible
end
diff --git a/features/step_definitions/oidc_common_steps.rb b/features/step_definitions/oidc_common_steps.rb
index 24f543754..0f7ae95a8 100644
--- a/features/step_definitions/oidc_common_steps.rb
+++ b/features/step_definitions/oidc_common_steps.rb
@@ -1,5 +1,5 @@
Given /^a client with a provided picture exists for user "([^\"]*)"$/ do |email|
- app = FactoryGirl.create(:o_auth_application_with_image)
+ app = FactoryGirl.create(:o_auth_application, logo_uri: "/assets/user/default.png")
user = User.find_by(email: email)
FactoryGirl.create(:auth_with_read, user: user, o_auth_application: app)
end
diff --git a/features/step_definitions/posts_steps.rb b/features/step_definitions/posts_steps.rb
index b0b8e62b1..a13779a2c 100644
--- a/features/step_definitions/posts_steps.rb
+++ b/features/step_definitions/posts_steps.rb
@@ -32,6 +32,10 @@ Then /^I should not be able to submit the publisher$/ do
expect(publisher_submittable?).to be false
end
+Then /^I should see "([^"]*)" in the publisher$/ do |text|
+ expect(page).to have_field("status_message[text]", with: text)
+end
+
Given /^I have a limited post with text "([^\"]*)" in the aspect "([^"]*)"$/ do |text, aspect_name|
@me.post :status_message, text: text, to: @me.aspects.where(name: aspect_name).first.id
end
@@ -114,10 +118,6 @@ When /^I append "([^"]*)" to the publisher$/ do |text|
append_to_publisher(text)
end
-When /^I append "([^"]*)" to the mobile publisher$/ do |text|
- append_to_publisher(text, '#status_message_text')
-end
-
When /^I attach "([^"]*)" to the publisher$/ do |path|
upload_file_with_publisher(path)
end
diff --git a/features/step_definitions/user_steps.rb b/features/step_definitions/user_steps.rb
index f01025a07..7eb0e2b6e 100644
--- a/features/step_definitions/user_steps.rb
+++ b/features/step_definitions/user_steps.rb
@@ -168,10 +168,14 @@ Then /^I should have (\d+) email delivery$/ do |n|
ActionMailer::Base.deliveries.length.should == n.to_i
end
-Then /^I should not see "([^\"]*)" in the last sent email$/ do |text|
+Then /^I should( not)? see "([^\"]*)" in the last sent email$/ do |negate, text|
email_text = Devise.mailer.deliveries.first.body.to_s
email_text = Devise.mailer.deliveries.first.html_part.body.raw_source if email_text.blank?
- email_text.should_not match(text)
+ if negate
+ expect(email_text).to_not have_content(text)
+ else
+ expect(email_text).to have_content(text)
+ end
end
When /^"([^\"]+)" has posted a (public )?status message with a photo$/ do |email, public_status|
diff --git a/features/step_definitions/web_steps.rb b/features/step_definitions/web_steps.rb
index f2c564c8f..2ffdd4829 100644
--- a/features/step_definitions/web_steps.rb
+++ b/features/step_definitions/web_steps.rb
@@ -93,6 +93,8 @@ When /^(?:|I )attach the file "([^"]*)" to (?:hidden )?"([^"]*)"(?: within "([^"
page.execute_script("$(\"input[name='#{field}']\").css('opacity', '1');")
attach_file(field, Rails.root.join(path).to_s)
end
+ # wait for the image to be ready
+ page.assert_selector(".loading", count: 0)
end
Then /^(?:|I )should see (\".+?\"[\s]*)(?:[\s]+within[\s]* "([^"]*)")?$/ do |vars, selector|
@@ -186,3 +188,9 @@ end
Then /^show me the page$/ do
save_and_open_page
end
+
+Then /^I wait until ajax requests finished$/ do
+ Timeout.timeout(Capybara.default_max_wait_time) do
+ loop until page.evaluate_script("jQuery.active") == 0
+ end
+end
diff --git a/features/support/env.rb b/features/support/env.rb
index 393446b64..cf95b37ef 100644
--- a/features/support/env.rb
+++ b/features/support/env.rb
@@ -23,7 +23,7 @@ Rails.application.routes.default_url_options[:host] = AppConfig.pod_uri.host
Rails.application.routes.default_url_options[:port] = AppConfig.pod_uri.port
Capybara.register_driver :poltergeist do |app|
- Capybara::Poltergeist::Driver.new(app, timeout: 80)
+ Capybara::Poltergeist::Driver.new(app, timeout: 30)
end
Capybara.javascript_driver = :poltergeist
@@ -52,7 +52,7 @@ Capybara.default_max_wait_time = 30
ActionController::Base.allow_rescue = false
Cucumber::Rails::Database.autorun_database_cleaner = true
-Cucumber::Rails::World.use_transactional_fixtures = false
+Cucumber::Rails::World.use_transactional_tests = false
require File.join(File.dirname(__FILE__), "integration_sessions_controller")
require File.join(File.dirname(__FILE__), "poor_mans_webmock")
diff --git a/features/support/publishing_cuke_helpers.rb b/features/support/publishing_cuke_helpers.rb
index a3fc5c02e..a6e0593ff 100644
--- a/features/support/publishing_cuke_helpers.rb
+++ b/features/support/publishing_cuke_helpers.rb
@@ -1,21 +1,13 @@
module PublishingCukeHelpers
def write_in_publisher(txt)
- fill_in 'status_message_fake_text', with: txt
+ fill_in "status_message_text", with: txt
end
- def append_to_publisher(txt, input_selector='#status_message_fake_text')
- status_message_text = find("#status_message_text", visible: false).value
- find(input_selector).native.send_key(" #{txt}")
-
- # make sure the other text field got the new contents
- if input_selector == "#status_message_fake_text"
- begin
- expect(page).to have_selector("#status_message_text[value='#{status_message_text} #{txt}']", visible: false)
- rescue RSpec::Expectations::ExpectationNotMetError
- puts "Value was instead: #{find('#status_message_text', visible: false).value.inspect}"
- raise
- end
- end
+ def append_to_publisher(txt)
+ status_message_text = find("#status_message_text").value
+ fill_in id: "status_message_text", with: "#{status_message_text} #{txt}"
+ # trigger JavaScript event listeners
+ find("#status_message_text").native.send_key(:end)
end
def upload_file_with_publisher(path)
@@ -33,7 +25,7 @@ module PublishingCukeHelpers
end
def submit_publisher
- txt = find("#publisher #status_message_fake_text").value
+ txt = find("#publisher #status_message_text").value
find("#publisher .btn-primary").click
# wait for the publisher to be closed
expect(find("#publisher")["class"]).to include("closed")
@@ -47,7 +39,7 @@ module PublishingCukeHelpers
end
def click_publisher
- find("#status_message_fake_text").click
+ find("#status_message_text").click
expect(find("#publisher")).to have_css(".publisher-textarea-wrapper.active")
end
@@ -103,7 +95,9 @@ module PublishingCukeHelpers
def like_stream_post(post_text)
within_post(post_text) do
- find(:css, 'a.like').click
+ action = find(:css, "a.like").text
+ find(:css, "a.like").click
+ expect(find(:css, "a.like")).not_to have_text(action)
end
end
diff --git a/features/support/user_cuke_helpers.rb b/features/support/user_cuke_helpers.rb
index 5ec5e3abb..b7014b0ac 100644
--- a/features/support/user_cuke_helpers.rb
+++ b/features/support/user_cuke_helpers.rb
@@ -47,7 +47,7 @@ module UserCukeHelpers
if mobile
expect(page).to have_css "#menu-badge"
else
- expect(find("#user_menu")).to have_content "#{@me.first_name} #{@me.last_name}"
+ expect(find("#user-menu")).to have_content "#{@me.first_name} #{@me.last_name}"
end
end
@@ -58,8 +58,8 @@ module UserCukeHelpers
# go to user menu, expand it, and click logout
def manual_logout
- find("#user_menu .dropdown-toggle").click
- find("#user_menu li:last-child a").click
+ find("#user-menu .dropdown-toggle").click
+ find("#user-menu li:last-child a").click
end
def manual_logout_mobile
@@ -69,8 +69,8 @@ module UserCukeHelpers
def fill_in_new_user_form
@username = "ohai"
- fill_in('user_username', with: @username)
fill_in('user_email', with: "#{@username}@example.com")
+ fill_in('user_username', with: @username)
fill_in('user_password', with: 'secret')
fill_in('user_password_confirmation', with: 'secret')
diff --git a/lib/account_deleter.rb b/lib/account_deleter.rb
index 83c31c528..95a5c9130 100644
--- a/lib/account_deleter.rb
+++ b/lib/account_deleter.rb
@@ -17,9 +17,9 @@ class AccountDeleter
attr_accessor :person, :user
- def initialize(diaspora_handle)
- self.person = Person.where(:diaspora_handle => diaspora_handle).first
- self.user = self.person.owner
+ def initialize(person)
+ self.person = person
+ self.user = person.owner
end
def perform!
@@ -30,31 +30,33 @@ class AccountDeleter
delete_contacts_of_me
tombstone_person_and_profile
- if self.user
- #user deletion methods
- remove_share_visibilities_on_contacts_posts
- delete_standard_user_associations
- disconnect_contacts
- tombstone_user
- end
+ close_user if user
mark_account_deletion_complete
end
end
+ # user deletion methods
+ def close_user
+ remove_share_visibilities_on_contacts_posts
+ disconnect_contacts
+ delete_standard_user_associations
+ tombstone_user
+ end
+
#user deletions
def normal_ar_user_associates_to_delete
- %i(tag_followings services aspects user_preferences
- notifications blocks authorizations o_auth_applications pairwise_pseudonymous_identifiers)
+ %i[tag_followings services aspects user_preferences
+ notifications blocks authorizations o_auth_applications pairwise_pseudonymous_identifiers]
end
def special_ar_user_associations
- %i(person profile contacts auto_follow_back_aspect)
+ %i[person profile contacts auto_follow_back_aspect]
end
def ignored_ar_user_associations
- %i(followed_tags invited_by contact_people aspect_memberships
- ignored_people share_visibilities conversation_visibilities conversations reports)
+ %i[followed_tags invited_by invited_users contact_people aspect_memberships
+ ignored_people share_visibilities conversation_visibilities conversations reports]
end
def delete_standard_user_associations
@@ -97,14 +99,15 @@ class AccountDeleter
end
def normal_ar_person_associates_to_delete
- %i(posts photos mentions participations roles)
+ %i[posts photos mentions participations roles blocks]
end
def ignored_or_special_ar_person_associations
- %i(comments contacts notification_actors notifications owner profile conversation_visibilities pod)
+ %i[comments likes poll_participations contacts notification_actors notifications owner profile
+ conversation_visibilities pod conversations messages]
end
def mark_account_deletion_complete
- AccountDeletion.where(:diaspora_handle => self.person.diaspora_handle).where(:person_id => self.person.id).update_all(["completed_at = ?", Time.now])
+ AccountDeletion.find_by(person: person)&.update_attributes(completed_at: Time.now.utc)
end
end
diff --git a/lib/api/openid_connect/token_endpoint.rb b/lib/api/openid_connect/token_endpoint.rb
index a2e8c8ac2..7bde221a9 100644
--- a/lib/api/openid_connect/token_endpoint.rb
+++ b/lib/api/openid_connect/token_endpoint.rb
@@ -50,7 +50,7 @@ module Api
end
def app_valid?(o_auth_app, req)
- o_auth_app.client_secret == req.client_secret
+ o_auth_app.try(:client_secret) == req.client_secret
end
end
end
diff --git a/lib/bookmarklet_renderer.rb b/lib/bookmarklet_renderer.rb
index 3114d5a80..0ecc9cf48 100644
--- a/lib/bookmarklet_renderer.rb
+++ b/lib/bookmarklet_renderer.rb
@@ -2,27 +2,35 @@
class BookmarkletRenderer
class << self
def cached_name
- @cached ||= Rails.root.join("public", "assets", "bookmarklet.js")
+ @cached_name ||= if Rails.application.config.assets.compile
+ "bookmarklet.js"
+ else
+ Rails.application.assets_manifest.assets["bookmarklet.js"]
+ end
end
- def source_name
+ def cached_path
+ @cached_path ||= Rails.root.join("public", "assets", cached_name)
+ end
+
+ def source
@source ||= Rails.application.assets["bookmarklet.js"].pathname.to_s
end
def body
- if !File.exist?(cached_name) && Rails.env.production?
- raise "please run the Rake task to compile the bookmarklet: `bundle exec rake assets:uglify_bookmarklet`"
+ unless File.exist?(cached_path) || Rails.application.config.assets.compile
+ raise "Please run the rake task to compile the bookmarklet: `bin/rake assets:precompile`"
end
- compile unless Rails.env.production? # don't make me re-run rake in development
- @body ||= File.read(cached_name)
+ compile if Rails.application.config.assets.compile
+ @body ||= File.read(cached_path)
end
def compile
- src = File.read(source_name)
+ src = File.read(source)
@body = Uglifier.compile(src)
- FileUtils.mkdir_p cached_name.dirname
- File.open(cached_name, "w") {|f| f.write(@body) }
+ FileUtils.mkdir_p cached_path.dirname
+ File.open(cached_path, "w") {|f| f.write(@body) }
end
end
end
diff --git a/lib/diaspora/exporter.rb b/lib/diaspora/exporter.rb
index e6f65ac7a..2c9e27909 100644
--- a/lib/diaspora/exporter.rb
+++ b/lib/diaspora/exporter.rb
@@ -6,22 +6,23 @@ module Diaspora
class Exporter
- SERIALIZED_VERSION = '1.0'
+ SERIALIZED_VERSION = "2.0".freeze
def initialize(user)
@user = user
end
def execute
- @export ||= JSON.generate serialized_user.merge(version: SERIALIZED_VERSION)
+ JSON.generate full_archive
end
private
- def serialized_user
- @serialized_user ||= Export::UserSerializer.new(@user).as_json
+ def full_archive
+ {version: SERIALIZED_VERSION}
+ .merge(Export::UserSerializer.new(@user).as_json)
+ .merge(Export::OthersDataSerializer.new(@user).as_json)
end
-
end
end
diff --git a/lib/diaspora/exporter/non_contact_authors.rb b/lib/diaspora/exporter/non_contact_authors.rb
new file mode 100644
index 000000000..f3cfc4801
--- /dev/null
+++ b/lib/diaspora/exporter/non_contact_authors.rb
@@ -0,0 +1,36 @@
+module Diaspora
+ class Exporter
+ # This class is capable of quering a list of people from authors of given posts that are non-contacts of a given
+ # user.
+ class NonContactAuthors
+ # @param posts [Post::ActiveRecord_Relation] posts that we fetch authors from to make authors list
+ # @param user [User] a user we fetch a contact list from
+ def initialize(posts, user)
+ @posts = posts
+ @user = user
+ end
+
+ # Create a request of non-contact authors of the posts for the user
+ # @return [Post::ActiveRecord_Relation]
+ def query
+ Person.where(id: non_contact_authors_ids)
+ end
+
+ private
+
+ def non_contact_authors_ids
+ posts_authors_ids - contacts_ids
+ end
+
+ def posts_authors_ids
+ posts.pluck(:author_id).uniq
+ end
+
+ def contacts_ids
+ user.contacts.pluck(:person_id)
+ end
+
+ attr_reader :posts, :user
+ end
+ end
+end
diff --git a/lib/diaspora/exporter/others_relayables.rb b/lib/diaspora/exporter/others_relayables.rb
new file mode 100644
index 000000000..5876c52cd
--- /dev/null
+++ b/lib/diaspora/exporter/others_relayables.rb
@@ -0,0 +1,42 @@
+module Diaspora
+ class Exporter
+ # This class implements methods that allow to query relayables (comments, likes, participations,
+ # poll_participations) of other people for posts of the given person.
+ class OthersRelayables
+ # @param person_id [Integer] Database id of a person for whom we want to request relayalbes
+ def initialize(person_id)
+ @person_id = person_id
+ end
+
+ # Comments of other people to the person's post
+ # @return [Comment::ActiveRecord_Relation]
+ def comments
+ Comment
+ .where.not(author_id: person_id)
+ .joins("INNER JOIN posts ON (commentable_type = 'Post' AND posts.id = commentable_id)")
+ .where("posts.author_id = ?", person_id)
+ end
+
+ # Likes of other people to the person's post
+ # @return [Like::ActiveRecord_Relation]
+ def likes
+ Like
+ .where.not(author_id: person_id)
+ .joins("INNER JOIN posts ON (target_type = 'Post' AND posts.id = target_id)")
+ .where("posts.author_id = ?", person_id)
+ end
+
+ # Poll participations of other people to the person's polls
+ # @return [PollParticipation::ActiveRecord_Relation]
+ def poll_participations
+ PollParticipation
+ .where.not(author_id: person_id).joins(:status_message)
+ .where("posts.author_id = ?", person_id)
+ end
+
+ private
+
+ attr_reader :person_id
+ end
+ end
+end
diff --git a/lib/diaspora/exporter/posts_with_activity.rb b/lib/diaspora/exporter/posts_with_activity.rb
new file mode 100644
index 000000000..00461c55b
--- /dev/null
+++ b/lib/diaspora/exporter/posts_with_activity.rb
@@ -0,0 +1,59 @@
+module Diaspora
+ class Exporter
+ # This class allows to query posts where a person made any activity (submitted comments,
+ # likes, participations or poll participations).
+ class PostsWithActivity
+ # @param user [User] user who the activity belongs to (the one who liked, commented posts, etc)
+ def initialize(user)
+ @user = user
+ end
+
+ # Create a request of posts with activity
+ # @return [Post::ActiveRecord_Relation]
+ def query
+ Post.from("(#{sql_union_all_activities}) AS posts")
+ end
+
+ private
+
+ attr_reader :user
+
+ def person
+ user.person
+ end
+
+ def sql_union_all_activities
+ all_activities.map(&:to_sql).join(" UNION ")
+ end
+
+ def all_activities
+ [comments_activity, likes_activity, subscriptions, polls_activity, reshares_activity]
+ end
+
+ def likes_activity
+ other_people_posts.liked_by(person)
+ end
+
+ def comments_activity
+ other_people_posts.commented_by(person)
+ end
+
+ def subscriptions
+ other_people_posts.subscribed_by(user)
+ end
+
+ def reshares_activity
+ other_people_posts.reshared_by(person)
+ end
+
+ def polls_activity
+ StatusMessage.where.not(author_id: person.id).joins(:poll_participations)
+ .where(poll_participations: {author_id: person.id})
+ end
+
+ def other_people_posts
+ Post.where.not(author_id: person.id)
+ end
+ end
+ end
+end
diff --git a/lib/diaspora/federated.rb b/lib/diaspora/federated.rb
index 348364fa0..e00fbd86a 100644
--- a/lib/diaspora/federated.rb
+++ b/lib/diaspora/federated.rb
@@ -6,5 +6,6 @@ module Diaspora
module Federated
require "diaspora/federated/base"
require "diaspora/federated/retraction"
+ require "diaspora/federated/contact_retraction"
end
end
diff --git a/lib/diaspora/federated/contact_retraction.rb b/lib/diaspora/federated/contact_retraction.rb
new file mode 100644
index 000000000..7ff7cc6f5
--- /dev/null
+++ b/lib/diaspora/federated/contact_retraction.rb
@@ -0,0 +1,18 @@
+class ContactRetraction < Retraction
+ def self.entity_class
+ DiasporaFederation::Entities::Contact
+ end
+
+ def self.retraction_data_for(target)
+ Diaspora::Federation::Entities.contact(target).to_h
+ end
+
+ def self.for(target)
+ target.receiving = false
+ super
+ end
+
+ def public?
+ false
+ end
+end
diff --git a/lib/diaspora/federated/retraction.rb b/lib/diaspora/federated/retraction.rb
index f925bbb9a..d6343c6fc 100644
--- a/lib/diaspora/federated/retraction.rb
+++ b/lib/diaspora/federated/retraction.rb
@@ -14,23 +14,27 @@ class Retraction
@target = target
end
- def self.for(target, sender=nil)
- federation_retraction = case target
- when Diaspora::Relayable
- Diaspora::Federation::Entities.relayable_retraction(target, sender)
- when Post
- Diaspora::Federation::Entities.signed_retraction(target, sender)
- else
- Diaspora::Federation::Entities.retraction(target)
- end
+ def self.entity_class
+ DiasporaFederation::Entities::Retraction
+ end
+
+ def self.retraction_data_for(target)
+ DiasporaFederation::Entities::Retraction.new(
+ target_guid: target.guid,
+ target: Diaspora::Federation::Entities.related_entity(target),
+ target_type: Diaspora::Federation::Mappings.entity_name_for(target),
+ author: target.diaspora_handle
+ ).to_h
+ end
- new(federation_retraction.to_h, target.subscribers.select(&:remote?), target)
+ def self.for(target)
+ federation_retraction_data = retraction_data_for(target)
+ new(federation_retraction_data, target.subscribers.select(&:remote?), target)
end
def defer_dispatch(user, include_target_author=true)
subscribers = dispatch_subscribers(include_target_author)
- sender = dispatch_sender(user)
- Workers::DeferredRetraction.perform_async(sender.id, data, subscribers.map(&:id), service_opts(user))
+ Workers::DeferredRetraction.perform_async(user.id, self.class.to_s, data, subscribers.map(&:id), service_opts(user))
end
def perform
@@ -40,8 +44,7 @@ class Retraction
end
def public?
- # TODO: backward compatibility for pre 0.6 pods, they don't relay public retractions
- data[:target][:public] == "true" && (!data[:target][:parent] || data[:target][:parent][:local] == "true")
+ data[:target][:public]
end
private
@@ -53,11 +56,6 @@ class Retraction
subscribers
end
- # @deprecated This is only needed for pre 0.6 pods
- def dispatch_sender(user)
- target.try(:sender_for_dispatch) || user
- end
-
def service_opts(user)
return {} unless target.is_a?(StatusMessage)
diff --git a/lib/diaspora/federation/dispatcher.rb b/lib/diaspora/federation/dispatcher.rb
index fc79e1092..64b16dae7 100644
--- a/lib/diaspora/federation/dispatcher.rb
+++ b/lib/diaspora/federation/dispatcher.rb
@@ -31,6 +31,16 @@ module Diaspora
attr_reader :sender, :object, :opts
+ def entity
+ @entity ||= Entities.build(object)
+ end
+
+ def magic_envelope
+ @magic_envelope ||= DiasporaFederation::Salmon::MagicEnvelope.new(
+ entity, sender.diaspora_handle
+ ).envelop(sender.encryption_key)
+ end
+
def deliver_to_services
deliver_to_user_services if opts[:service_types]
end
diff --git a/lib/diaspora/federation/dispatcher/private.rb b/lib/diaspora/federation/dispatcher/private.rb
index ab13756fd..456e1dcec 100644
--- a/lib/diaspora/federation/dispatcher/private.rb
+++ b/lib/diaspora/federation/dispatcher/private.rb
@@ -7,22 +7,17 @@ module Diaspora
def deliver_to_remote(people)
return if people.empty?
- entity = Entities.build(object)
- Workers::SendPrivate.perform_async(sender.id, entity.to_s, targets(people, salmon_slap(entity)))
+ Workers::SendPrivate.perform_async(sender.id, entity.to_s, targets(people))
end
- def targets(people, salmon_slap)
+ def targets(people)
active, inactive = people.partition {|person| person.pod.active? }
logger.info "ignoring inactive pods: #{inactive.map(&:diaspora_handle).join(', ')}" if inactive.any?
- active.map {|person| [person.receive_url, salmon_slap.generate_xml(person.public_key)] }.to_h
+ active.map {|person| [person.receive_url, encrypted_magic_envelope(person)] }.to_h
end
- def salmon_slap(entity)
- DiasporaFederation::Salmon::EncryptedSlap.prepare(
- sender.diaspora_handle,
- sender.encryption_key,
- entity
- )
+ def encrypted_magic_envelope(person)
+ DiasporaFederation::Salmon::EncryptedMagicEnvelope.encrypt(magic_envelope, person.public_key)
end
end
end
diff --git a/lib/diaspora/federation/dispatcher/public.rb b/lib/diaspora/federation/dispatcher/public.rb
index c91979c20..b8ad30bff 100644
--- a/lib/diaspora/federation/dispatcher/public.rb
+++ b/lib/diaspora/federation/dispatcher/public.rb
@@ -14,8 +14,7 @@ module Diaspora
return if targets.empty?
- entity = Entities.build(object)
- Workers::SendPublic.perform_async(sender.id, entity.to_s, targets, salmon_xml(entity))
+ Workers::SendPublic.perform_async(sender.id, entity.to_s, targets, magic_envelope.to_xml)
end
def target_urls(people)
@@ -29,14 +28,6 @@ module Diaspora
[AppConfig.relay.outbound.url]
end
- def salmon_xml(entity)
- DiasporaFederation::Salmon::Slap.generate_xml(
- sender.diaspora_handle,
- sender.encryption_key,
- entity
- )
- end
-
def deliver_to_hub
logger.debug "deliver to pubsubhubbub sender: #{sender.diaspora_handle}"
Workers::PublishToHub.perform_async(sender.atom_url)
diff --git a/lib/diaspora/federation/entities.rb b/lib/diaspora/federation/entities.rb
index f806ec158..0a9bd8af4 100644
--- a/lib/diaspora/federation/entities.rb
+++ b/lib/diaspora/federation/entities.rb
@@ -2,18 +2,7 @@ module Diaspora
module Federation
module Entities
def self.build(entity)
- public_send(Mappings.builder_for(entity.class), entity)
- end
-
- def self.build_retraction(retraction)
- case retraction.data[:target_type]
- when "Comment", "Like", "PollParticipation"
- DiasporaFederation::Entities::RelayableRetraction.new(retraction.data)
- when "Post"
- DiasporaFederation::Entities::SignedRetraction.new(retraction.data)
- else
- DiasporaFederation::Entities::Retraction.new(retraction.data)
- end
+ public_send(Mappings.builder_for(entity), entity)
end
def self.post(post)
@@ -33,6 +22,13 @@ module Diaspora
)
end
+ def self.account_migration(account_migration)
+ DiasporaFederation::Entities::AccountMigration.new(
+ author: account_migration.sender.diaspora_handle,
+ profile: profile(account_migration.new_person.profile)
+ )
+ end
+
def self.comment(comment)
DiasporaFederation::Entities::Comment.new(
{
@@ -50,10 +46,11 @@ module Diaspora
end
def self.contact(contact)
- # TODO: use DiasporaFederation::Entities::Contact
- DiasporaFederation::Entities::Request.new(
+ DiasporaFederation::Entities::Contact.new(
author: contact.user.diaspora_handle,
- recipient: contact.person.diaspora_handle
+ recipient: contact.person.diaspora_handle,
+ sharing: contact.receiving,
+ following: contact.receiving
)
end
@@ -98,10 +95,7 @@ module Diaspora
guid: message.guid,
text: message.text,
created_at: message.created_at,
- parent_guid: message.conversation.guid,
- conversation_guid: message.conversation.guid,
- author_signature: message.author_signature,
- parent: related_entity(message.conversation)
+ conversation_guid: message.conversation.guid
)
end
@@ -110,8 +104,7 @@ module Diaspora
author: participation.diaspora_handle,
guid: participation.guid,
parent_guid: participation.target.guid,
- parent_type: Mappings.entity_name_for(participation.target),
- parent: related_entity(participation.target)
+ parent_type: Mappings.entity_name_for(participation.target)
)
end
@@ -174,17 +167,8 @@ module Diaspora
location: profile.location,
searchable: profile.searchable,
nsfw: profile.nsfw,
- tag_string: profile.tag_string
- )
- end
-
- # @deprecated
- def self.relayable_retraction(target, sender)
- DiasporaFederation::Entities::RelayableRetraction.new(
- target_guid: target.guid,
- target_type: Mappings.entity_name_for(target),
- target: related_entity(target),
- author: sender.diaspora_handle
+ tag_string: profile.tag_string,
+ public: profile.public_details
)
end
@@ -200,35 +184,8 @@ module Diaspora
)
end
- def self.retraction(target)
- case target
- when Contact
- # TODO: deprecated
- author = target.user.diaspora_handle
- DiasporaFederation::Entities::Retraction.new(
- target_guid: target.user.guid,
- target_type: "Person",
- target: DiasporaFederation::Entities::RelatedEntity.new(author: author, local: true),
- author: author
- )
- else
- DiasporaFederation::Entities::Retraction.new(
- target_guid: target.guid,
- target_type: Mappings.entity_name_for(target),
- target: related_entity(target),
- author: target.diaspora_handle
- )
- end
- end
-
- # @deprecated
- def self.signed_retraction(target, sender)
- DiasporaFederation::Entities::SignedRetraction.new(
- target_guid: target.guid,
- target_type: Mappings.entity_name_for(target),
- target: related_entity(target),
- author: sender.diaspora_handle
- )
+ def self.retraction(retraction)
+ retraction.class.entity_class.new(retraction.data)
end
def self.status_message(status_message)
diff --git a/lib/diaspora/federation/mappings.rb b/lib/diaspora/federation/mappings.rb
index 2b761b697..ec344cab2 100644
--- a/lib/diaspora/federation/mappings.rb
+++ b/lib/diaspora/federation/mappings.rb
@@ -1,81 +1,82 @@
module Diaspora
module Federation
module Mappings
+ # rubocop:disable Metrics/CyclomaticComplexity
+
# used in Diaspora::Federation::Receive
- def self.receiver_for(federation_class)
- fetch_from(ENTITY_RECEIVERS, federation_class)
+ def self.receiver_for(federation_entity)
+ case federation_entity
+ when DiasporaFederation::Entities::AccountMigration then :account_migration
+ when DiasporaFederation::Entities::Comment then :comment
+ when DiasporaFederation::Entities::Contact then :contact
+ when DiasporaFederation::Entities::Conversation then :conversation
+ when DiasporaFederation::Entities::Like then :like
+ when DiasporaFederation::Entities::Message then :message
+ when DiasporaFederation::Entities::Participation then :participation
+ when DiasporaFederation::Entities::Photo then :photo
+ when DiasporaFederation::Entities::PollParticipation then :poll_participation
+ when DiasporaFederation::Entities::Profile then :profile
+ when DiasporaFederation::Entities::Reshare then :reshare
+ when DiasporaFederation::Entities::StatusMessage then :status_message
+ else not_found(federation_entity.class)
+ end
end
# used in Diaspora::Federation::Entities
- def self.builder_for(diaspora_class)
- fetch_from(ENTITY_BUILDERS, diaspora_class)
+ def self.builder_for(diaspora_entity)
+ case diaspora_entity
+ when AccountMigration then :account_migration
+ when AccountDeletion then :account_deletion
+ when Comment then :comment
+ when Contact then :contact
+ when Conversation then :conversation
+ when Like then :like
+ when Message then :message
+ when Participation then :participation
+ when Photo then :photo
+ when PollParticipation then :poll_participation
+ when Profile then :profile
+ when Reshare then :reshare
+ when Retraction then :retraction
+ when ContactRetraction then :retraction
+ when StatusMessage then :status_message
+ else not_found(diaspora_entity.class)
+ end
end
def self.model_class_for(entity_name)
- fetch_from(ENTITY_MODELS, entity_name)
+ case entity_name
+ when "Comment" then Comment
+ when "Conversation" then Conversation
+ when "Like" then Like
+ when "Participation" then Participation
+ when "PollParticipation" then PollParticipation
+ when "Photo" then Photo
+ when "Poll" then Poll
+ when "Post" then Post
+ when "Person" then Person # TODO: deprecated
+ when "Reshare" then Post
+ when "StatusMessage" then Post
+ else not_found(entity_name)
+ end
end
def self.entity_name_for(model)
- fetch_from(ENTITY_NAMES, model.class.base_class)
+ case model
+ when Comment then "Comment"
+ when Like then "Like"
+ when Participation then "Participation"
+ when PollParticipation then "PollParticipation"
+ when Photo then "Photo"
+ when Post then "Post"
+ else not_found(model.class)
+ end
end
+ # rubocop:enable Metrics/CyclomaticComplexity
- private_class_method def self.fetch_from(mapping, key)
- mapping.fetch(key) { raise DiasporaFederation::Entity::UnknownEntity, "unknown entity: #{key}" }
+ private_class_method def self.not_found(key)
+ raise DiasporaFederation::Entity::UnknownEntity, "unknown entity: #{key}"
end
-
- ENTITY_RECEIVERS = {
- DiasporaFederation::Entities::Comment => :comment,
- DiasporaFederation::Entities::Contact => :contact,
- DiasporaFederation::Entities::Conversation => :conversation,
- DiasporaFederation::Entities::Like => :like,
- DiasporaFederation::Entities::Message => :message,
- DiasporaFederation::Entities::Participation => :participation,
- DiasporaFederation::Entities::Photo => :photo,
- DiasporaFederation::Entities::PollParticipation => :poll_participation,
- DiasporaFederation::Entities::Profile => :profile,
- DiasporaFederation::Entities::Reshare => :reshare,
- DiasporaFederation::Entities::StatusMessage => :status_message
- }.freeze
-
- ENTITY_BUILDERS = {
- AccountDeletion => :account_deletion,
- Comment => :comment,
- Contact => :contact,
- Conversation => :conversation,
- Like => :like,
- Message => :message,
- Participation => :participation,
- Photo => :photo,
- PollParticipation => :poll_participation,
- Profile => :profile,
- Reshare => :reshare,
- Retraction => :build_retraction,
- StatusMessage => :status_message
- }.freeze
-
- ENTITY_MODELS = {
- "Comment" => Comment,
- "Conversation" => Conversation,
- "Like" => Like,
- "Participation" => Participation,
- "PollParticipation" => PollParticipation,
- "Photo" => Photo,
- "Poll" => Poll,
- "Post" => Post,
- # TODO: deprecated
- "Person" => Person,
- "Reshare" => Post,
- "StatusMessage" => Post
- }.freeze
-
- ENTITY_NAMES = {
- Comment => "Comment",
- Like => "Like",
- Participation => "Participation",
- PollParticipation => "PollParticipation",
- Photo => "Photo",
- Post => "Post"
- }.freeze
end
end
end
diff --git a/lib/diaspora/federation/receive.rb b/lib/diaspora/federation/receive.rb
index a61566402..d130cab68 100644
--- a/lib/diaspora/federation/receive.rb
+++ b/lib/diaspora/federation/receive.rb
@@ -4,11 +4,19 @@ module Diaspora
extend Diaspora::Logging
def self.perform(entity)
- public_send(Mappings.receiver_for(entity.class), entity)
+ public_send(Mappings.receiver_for(entity), entity)
end
def self.account_deletion(entity)
- AccountDeletion.create!(person: author_of(entity), diaspora_handle: entity.author)
+ AccountDeletion.create!(person: author_of(entity))
+ end
+
+ def self.account_migration(entity)
+ profile = profile(entity.profile)
+ AccountMigration.create!(
+ old_person: Person.by_account_identifier(entity.author),
+ new_person: profile.person
+ )
end
def self.comment(entity)
@@ -25,7 +33,7 @@ module Diaspora
def self.contact(entity)
recipient = Person.find_by(diaspora_handle: entity.recipient).owner
- if entity.sharing.to_s == "true"
+ if entity.sharing
Contact.create_or_update_sharing_contact(recipient, author_of(entity))
else
recipient.disconnected_by(author_of(entity))
@@ -59,7 +67,9 @@ module Diaspora
end
def self.message(entity)
- save_message(entity).tap {|message| relay_relayable(message) if message }
+ ignore_existing_guid(Message, entity.guid, author_of(entity)) do
+ build_message(entity).tap(&:save!)
+ end
end
def self.participation(entity)
@@ -120,7 +130,8 @@ module Diaspora
location: entity.location,
searchable: entity.searchable,
nsfw: entity.nsfw,
- tag_string: entity.tag_string
+ tag_string: entity.tag_string,
+ public_details: entity.public
)
end
end
@@ -149,7 +160,7 @@ module Diaspora
when Diaspora::Relayable
if object.parent.author.local?
parent_author = object.parent.author.owner
- retraction = Retraction.for(object, parent_author)
+ retraction = Retraction.for(object)
retraction.defer_dispatch(parent_author, false)
retraction.perform
else
@@ -209,21 +220,13 @@ module Diaspora
poll.poll_answers = entity.poll_answers.map do |answer|
PollAnswer.new(
guid: answer.guid,
- answer: answer.answer
+ answer: answer.answer,
+ poll: poll
)
end
end
end
- private_class_method def self.save_message(entity)
- ignore_existing_guid(Message, entity.guid, author_of(entity)) do
- build_message(entity).tap do |message|
- message.author_signature = entity.author_signature if message.conversation.author.local?
- message.save!
- end
- end
- end
-
private_class_method def self.save_photo(entity)
Photo.create!(
author: author_of(entity),
@@ -263,8 +266,8 @@ module Diaspora
private_class_method def self.build_signature(klass, entity)
klass.reflect_on_association(:signature).klass.new(
author_signature: entity.author_signature,
- additional_data: entity.additional_xml_elements,
- signature_order: SignatureOrder.find_or_create_by!(order: entity.xml_order.join(" "))
+ additional_data: entity.additional_data,
+ signature_order: SignatureOrder.find_or_create_by!(order: entity.signature_order.join(" "))
)
end
@@ -272,7 +275,7 @@ module Diaspora
parent_author = relayable.parent.author.owner
return unless parent_author && parent_author.ignored_people.include?(relayable.author)
- retraction = Retraction.for(relayable, parent_author)
+ retraction = Retraction.for(relayable)
Diaspora::Federation::Dispatcher.build(parent_author, retraction, subscribers: [relayable.author]).dispatch
raise Diaspora::Federation::AuthorIgnored
diff --git a/lib/diaspora/fetcher/public.rb b/lib/diaspora/fetcher/public.rb
index 34af2f30e..1a7fbd7ee 100644
--- a/lib/diaspora/fetcher/public.rb
+++ b/lib/diaspora/fetcher/public.rb
@@ -102,25 +102,16 @@ module Diaspora; module Fetcher; class Public
logger.debug "post: #{post.to_s[0..250]}"
- # disable some stuff we don't want for bulk inserts
- StatusMessage.skip_callback :create, :set_guid
-
entry = StatusMessage.diaspora_initialize(
- :author => @person,
- :public => true
- )
- entry.assign_attributes(
+ author: @person,
+ public: true,
guid: post["guid"],
text: post["text"],
provider_display_name: post["provider_display_name"],
created_at: ActiveSupport::TimeZone.new("UTC").parse(post["created_at"]).to_datetime,
- interacted_at: ActiveSupport::TimeZone.new("UTC").parse(post["interacted_at"]).to_datetime
)
entry.save
- # re-enable everything we disabled before
- StatusMessage.set_callback :create, :set_guid
-
end
set_fetch_status Public::Status_Processed
end
diff --git a/lib/diaspora/fields/target.rb b/lib/diaspora/fields/target.rb
index 1fbbf9796..7120c2a84 100644
--- a/lib/diaspora/fields/target.rb
+++ b/lib/diaspora/fields/target.rb
@@ -6,7 +6,6 @@ module Diaspora
belongs_to :target, polymorphic: true
validates :target_id, uniqueness: {scope: %i(target_type author_id)}
- validates :target, presence: true
end
end
end
diff --git a/lib/diaspora/mentionable.rb b/lib/diaspora/mentionable.rb
index 8645d9020..fb6117a45 100644
--- a/lib/diaspora/mentionable.rb
+++ b/lib/diaspora/mentionable.rb
@@ -1,23 +1,20 @@
module Diaspora::Mentionable
- # regex for finding mention markup in plain text
- # ex.
+ # regex for finding mention markup in plain text:
+ # "message @{user@pod.net} text"
+ # it can also contain a name, which gets used as the link text:
# "message @{User Name; user@pod.net} text"
# will yield "User Name" and "user@pod.net"
- REGEX = /(@\{(.+?; [^\}]+)\})/
+ REGEX = /@\{(?:([^\}]+?); )?([^\} ]+)\}/
# class attribute that will be added to all mention html links
PERSON_HREF_CLASS = "mention hovercardable"
def self.mention_attrs(mention_str)
- mention = mention_str.match(REGEX)[2]
- del_pos = mention.rindex(/;/)
+ name, diaspora_id = mention_str.match(REGEX).captures
- name = mention[0..(del_pos - 1)].strip
- handle = mention[(del_pos + 1)..-1].strip
-
- [name, handle]
+ [name.try(:strip).presence, diaspora_id.strip]
end
# takes a message text and returns the text with mentions in (html escaped)
@@ -32,10 +29,10 @@ module Diaspora::Mentionable
people = [*people]
msg_text.to_s.gsub(REGEX) {|match_str|
- name, handle = mention_attrs(match_str)
- person = people.find {|p| p.diaspora_handle == handle }
+ name, diaspora_id = mention_attrs(match_str)
+ person = people.find {|p| p.diaspora_handle == diaspora_id }
- ERB::Util.h(MentionsInternal.mention_link(person, name, opts))
+ "@#{ERB::Util.h(MentionsInternal.mention_link(person, name, diaspora_id, opts))}"
}
end
@@ -45,43 +42,49 @@ module Diaspora::Mentionable
# @param [String] text containing mentions
# @return [Array<Person>] array of people
def self.people_from_string(msg_text)
- identifiers = msg_text.to_s.scan(REGEX).map do |match_str|
- _, identifier = mention_attrs(match_str.first)
- identifier if Validation::Rule::DiasporaId.new.valid_value?(identifier)
- end
+ identifiers = msg_text.to_s.scan(REGEX).map {|match_str| match_str.second.strip }
identifiers.compact.uniq.map {|identifier| find_or_fetch_person_by_identifier(identifier) }.compact
end
# takes a message text and converts mentions for people that are not in the
- # given aspects to simple markdown links, leaving only mentions for people who
+ # given array to simple markdown links, leaving only mentions for people who
# will actually be able to receive notifications for being mentioned.
#
# @param [String] message text
- # @param [User] aspect owner
- # @param [Mixed] array containing aspect ids or "all"
+ # @param [Array] allowed_people ids of people that are allowed to stay
# @return [String] message text with filtered mentions
- def self.filter_for_aspects(msg_text, user, *aspects)
- aspect_ids = MentionsInternal.get_aspect_ids(user, *aspects)
-
+ def self.filter_people(msg_text, allowed_people)
mentioned_ppl = people_from_string(msg_text)
- aspects_ppl = AspectMembership.where(aspect_id: aspect_ids)
- .includes(:contact => :person)
- .map(&:person)
msg_text.to_s.gsub(REGEX) {|match_str|
- name, handle = mention_attrs(match_str)
- person = mentioned_ppl.find {|p| p.diaspora_handle == handle }
- mention = MentionsInternal.profile_link(person, name) unless aspects_ppl.include?(person)
+ name, diaspora_id = mention_attrs(match_str)
+ person = mentioned_ppl.find {|p| p.diaspora_handle == diaspora_id }
- mention || match_str
+ if person && allowed_people.include?(person.id)
+ match_str
+ else
+ "@#{MentionsInternal.profile_link(person, name, diaspora_id)}"
+ end
}
end
- private
+ # Regex to find mentions with new syntax, only used for backporting to old syntax
+ NEW_SYNTAX_REGEX = /@\{[^ ]+\}/
+
+ # replaces new syntax with old syntax, to be compatible with old pods
+ # @deprecated remove when most of the posts can handle the new syntax
+ def self.backport_mention_syntax(text)
+ text.to_s.gsub(NEW_SYNTAX_REGEX) do |match_str|
+ _, diaspora_id = mention_attrs(match_str)
+ person = find_or_fetch_person_by_identifier(diaspora_id)
+ old_syntax = "@{#{person.name.delete('{}')}; #{diaspora_id}}" if person
+ old_syntax || match_str
+ end
+ end
private_class_method def self.find_or_fetch_person_by_identifier(identifier)
- Person.find_or_fetch_by_identifier(identifier)
+ Person.find_or_fetch_by_identifier(identifier) if Validation::Rule::DiasporaId.new.valid_value?(identifier)
rescue DiasporaFederation::Discovery::DiscoveryError
nil
end
@@ -97,11 +100,11 @@ module Diaspora::Mentionable
# @param [Person] AR Person
# @param [String] display name
# @param [Hash] formatting options
- def self.mention_link(person, display_name, opts)
- return display_name unless person.present?
+ def self.mention_link(person, display_name, diaspora_id, opts)
+ return display_name || diaspora_id unless person.present?
if opts[:plain_text]
- display_name.presence || person.name
+ display_name || person.name
else
person_link(person, class: PERSON_HREF_CLASS, display_name: display_name)
end
@@ -113,31 +116,10 @@ module Diaspora::Mentionable
# @param [Person] AR Person
# @param [String] display name
# @return [String] markdown person link
- def self.profile_link(person, display_name)
- return display_name unless person.present?
+ def self.profile_link(person, display_name, diaspora_id)
+ return display_name || diaspora_id unless person.present?
- "[#{display_name.presence || person.name}](#{local_or_remote_person_path(person)})"
- end
-
- # takes a user and an array of aspect ids or an array containing "all" as
- # the first element. will do some checking on ids and return them in an array
- # in case of "all", returns an array with all the users aspect ids
- #
- # @param [User] owner of the aspects
- # @param [Array] aspect ids or "all"
- # @return [Array] aspect ids
- def self.get_aspect_ids(user, *aspects)
- return [] if aspects.empty?
-
- if (!aspects.first.is_a?(Integer)) && aspects.first.to_s == 'all'
- return user.aspects.pluck(:id)
- end
-
- ids = aspects.reject {|id| Integer(id) == nil } # only numeric
-
- #make sure they really belong to the user
- user.aspects.where(id: ids).pluck(:id)
+ "[#{display_name || person.name}](#{local_or_remote_person_path(person)})"
end
end
-
end
diff --git a/lib/diaspora/mentions_container.rb b/lib/diaspora/mentions_container.rb
new file mode 100644
index 000000000..68e8b425c
--- /dev/null
+++ b/lib/diaspora/mentions_container.rb
@@ -0,0 +1,43 @@
+module Diaspora
+ module MentionsContainer
+ extend ActiveSupport::Concern
+
+ included do
+ before_create do
+ # TODO: remove when most of the posts can handle the new syntax
+ self.text = Diaspora::Mentionable.backport_mention_syntax(text) if text && author.local?
+ end
+
+ after_create :create_mentions
+ has_many :mentions, as: :mentions_container, dependent: :destroy
+ end
+
+ def mentioned_people
+ if persisted?
+ mentions.includes(person: :profile).map(&:person)
+ else
+ Diaspora::Mentionable.people_from_string(text)
+ end
+ end
+
+ def add_mention_subscribers?
+ public?
+ end
+
+ def subscribers
+ super.tap {|subscribers|
+ subscribers.concat(mentions.map(&:person).select(&:remote?)) if add_mention_subscribers?
+ }
+ end
+
+ def create_mentions
+ Diaspora::Mentionable.people_from_string(text).each do |person|
+ mentions.find_or_create_by(person_id: person.id)
+ end
+ end
+
+ def message
+ @message ||= Diaspora::MessageRenderer.new text, mentioned_people: mentioned_people
+ end
+ end
+end
diff --git a/lib/diaspora/message_renderer.rb b/lib/diaspora/message_renderer.rb
index 7c39470fb..9540db631 100644
--- a/lib/diaspora/message_renderer.rb
+++ b/lib/diaspora/message_renderer.rb
@@ -72,14 +72,14 @@ module Diaspora
end
if options[:disable_hovercards] || options[:link_all_mentions]
- @message = Diaspora::Mentionable.filter_for_aspects message, nil
+ @message = Diaspora::Mentionable.filter_people message, []
else
make_mentions_plain_text
end
end
def make_mentions_plain_text
- @message = Diaspora::Mentionable.format message, [], plain_text: true
+ @message = Diaspora::Mentionable.format message, options[:mentioned_people], plain_text: true
end
def render_tags
diff --git a/lib/diaspora/relayable.rb b/lib/diaspora/relayable.rb
index c471636db..5753674d4 100644
--- a/lib/diaspora/relayable.rb
+++ b/lib/diaspora/relayable.rb
@@ -6,6 +6,7 @@ module Diaspora
module Relayable
def self.included(model)
model.class_eval do
+ validates :parent, presence: true
validates_associated :parent
validate :author_is_not_ignored
@@ -36,7 +37,6 @@ module Diaspora
end
end
- # @deprecated This is only needed for pre 0.6 pods
def sender_for_dispatch
parent.author.owner if parent.author.local?
end
diff --git a/lib/diaspora/shareable.rb b/lib/diaspora/shareable.rb
index 96895f521..97078dd6a 100644
--- a/lib/diaspora/shareable.rb
+++ b/lib/diaspora/shareable.rb
@@ -50,6 +50,14 @@ module Diaspora
end
end
+ # Remote pods which are known to be subscribed to the post. Must include all pods which received the post in the
+ # past.
+ #
+ # @return [Array<String>] The list of pods' URIs
+ def subscribed_pods_uris
+ Pod.find(subscribers.select(&:remote?).map(&:pod_id).uniq).map {|pod| pod.url_to("") }
+ end
+
module QueryMethods
def owned_or_visible_by_user(user)
with_visibility.where(
diff --git a/lib/evil_query.rb b/lib/evil_query.rb
index 78599ead1..782833a92 100644
--- a/lib/evil_query.rb
+++ b/lib/evil_query.rb
@@ -71,7 +71,7 @@ module EvilQuery
def followed_tags_posts!
logger.debug("[EVIL-QUERY] followed_tags_posts!")
- StatusMessage.public_tag_stream(@user.followed_tag_ids)
+ StatusMessage.public_tag_stream(@user.followed_tag_ids).excluding_hidden_content(@user)
end
def mentioned_posts
diff --git a/lib/schemas/archive-format.json b/lib/schemas/archive-format.json
new file mode 100644
index 000000000..11ba60a72
--- /dev/null
+++ b/lib/schemas/archive-format.json
@@ -0,0 +1,255 @@
+{
+ "$schema": "http://json-schema.org/draft-04/schema#",
+ "id": "https://diaspora.github.io/diaspora/schemas/archive_format.json",
+ "type": "object",
+ "properties": {
+ "user": {
+ "type": "object",
+ "properties": {
+ "email": { "type": "string" },
+ "language": { "type": "string" },
+ "username": { "type": "string" },
+ "private_key": { "type": "string" },
+ "disable_mail": { "type": "boolean" },
+ "show_community_spotlight_in_stream": { "type": "boolean" },
+ "auto_follow_back": { "type": "boolean" },
+ "auto_follow_back_aspect": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "strip_exif": { "type": "boolean" },
+
+ "profile": {
+ "$ref": "https://diaspora.github.io/diaspora_federation/schemas/federation_entities.json#definitions/profile"
+ },
+
+ "contact_groups": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": { "type": "string" },
+ "contacts_visible": { "type": "boolean" },
+ "chat_enabled": { "type": "boolean" }
+ },
+ "required": [
+ "name"
+ ]
+ }
+ },
+
+ "contacts": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "sharing": { "type": "boolean" },
+ "following": { "type": "boolean" },
+ "receiving": { "type": "boolean" },
+ "followed": { "type": "boolean" },
+ "account_id": { "type": "string" },
+ "contact_groups_membership": {
+ "type": "array",
+ "items": { "type": "string" }
+ },
+ "person_name": { "type": "string" },
+ "person_guid": {
+ "$ref": "https://diaspora.github.io/diaspora_federation/schemas/federation_entities.json#/definitions/guid"
+ },
+ "public_key": { "type": "string" }
+ },
+ "required": [
+ "sharing",
+ "following",
+ "receiving",
+ "followed",
+ "account_id",
+ "contact_groups_membership"
+ ]
+ }
+ },
+
+ "posts": {
+ "type": "array",
+ "items": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/posts"
+ },
+ {
+ "oneOf": [
+ { "$ref": "#/definitions/remote_subscription/public" },
+ { "$ref": "#/definitions/remote_subscription/private" }
+ ]
+ }
+ ]
+
+ }
+ },
+
+ "relayables": {
+ "type": "array",
+ "items": {
+ "oneOf": [
+ {
+ "$ref": "https://diaspora.github.io/diaspora_federation/schemas/federation_entities.json#/definitions/comment"
+ },
+ {
+ "$ref": "https://diaspora.github.io/diaspora_federation/schemas/federation_entities.json#/definitions/like"
+ },
+ {
+ "$ref": "https://diaspora.github.io/diaspora_federation/schemas/federation_entities.json#/definitions/poll_participation"
+ }
+ ]
+ }
+ },
+
+ "followed_tags": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+
+ "post_subscriptions": {
+ "type": "array",
+ "description": "GUIDs of posts for which changes we want to be subscribed",
+ "items": {
+ "$ref": "https://diaspora.github.io/diaspora_federation/schemas/federation_entities.json#/definitions/guid"
+ }
+ }
+ },
+ "required": [
+ "username",
+ "email",
+ "private_key",
+ "profile"
+ ]
+ },
+ "others_data": {
+ "type": "object",
+ "properties": {
+ "relayables": {
+ "type": "array",
+ "items": {
+ "allOf": [
+ {
+ "oneOf": [
+ {
+ "$ref": "https://diaspora.github.io/diaspora_federation/schemas/federation_entities.json#/definitions/comment"
+ },
+ {
+ "$ref": "https://diaspora.github.io/diaspora_federation/schemas/federation_entities.json#/definitions/like"
+ },
+ {
+ "$ref": "https://diaspora.github.io/diaspora_federation/schemas/federation_entities.json#/definitions/poll_participation"
+ }
+ ]
+ }
+ ]
+ }
+ },
+
+ "non_contact_authors": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "account_id": {
+ "type": "string"
+ },
+ "guid": {
+ "type": "string"
+ },
+ "public_key": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "account_id",
+ "guid",
+ "public_key"
+ ]
+ }
+ },
+
+ "posts": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/posts"
+ }
+ }
+ }
+ },
+ "version": {
+ "type": "string",
+ "pattern": "^2\.0$"
+ }
+ },
+ "required": [
+ "user",
+ "version"
+ ],
+ "definitions": {
+ "posts": {
+ "oneOf": [
+ { "$ref": "https://diaspora.github.io/diaspora_federation/schemas/federation_entities.json#/definitions/status_message" },
+ { "$ref": "https://diaspora.github.io/diaspora_federation/schemas/federation_entities.json#/definitions/reshare" }
+ ]
+ },
+
+ "remote_subscription": {
+ "public": {
+ "type": "object",
+ "properties": {
+ "subscribed_pods_uris": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "entity_data": {
+ "type": "object",
+ "properties": {
+ "public": {
+ "enum": [ true ]
+ }
+ },
+ "required": [
+ "public"
+ ]
+ }
+ },
+ "required": [
+ "entity_data"
+ ]
+ },
+
+ "private": {
+ "type": "object",
+ "properties": {
+ "subscribed_users_ids": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+
+ "entity_data": {
+ "type": "object",
+ "properties": {
+ "public": {
+ "enum": [ false ]
+ }
+ },
+ "required": [
+ "public"
+ ]
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/lib/share_visibility_converter.rb b/lib/share_visibility_converter.rb
index c044570d3..82b9e2d23 100644
--- a/lib/share_visibility_converter.rb
+++ b/lib/share_visibility_converter.rb
@@ -1,24 +1,24 @@
#we dont have the environment, and it is not carring over from the migration
unless defined?(Person)
- class Person < ActiveRecord::Base
+ class Person < ApplicationRecord
belongs_to :owner, :class_name => 'User'
end
end
unless defined?(User)
- class User < ActiveRecord::Base
+ class User < ApplicationRecord
serialize :hidden_shareables, Hash
end
end
unless defined?(Contact)
- class Contact < ActiveRecord::Base
+ class Contact < ApplicationRecord
belongs_to :user
end
end
unless defined?(ShareVisibility)
- class ShareVisibility < ActiveRecord::Base
+ class ShareVisibility < ApplicationRecord
belongs_to :contact
end
end
@@ -28,14 +28,14 @@ class ShareVisibilityConverter
def self.copy_hidden_share_visibilities_to_users(only_recent = false)
query = ShareVisibility.where(:hidden => true).includes(:contact => :user)
query = query.where('share_visibilities.updated_at > ?', RECENT.weeks.ago) if only_recent
- count = query.count
+ count = query.count
puts "Updating #{count} records in batches of 1000..."
batch_count = 1
query.find_in_batches do |visibilities|
puts "Updating batch ##{batch_count} of #{(count/1000)+1}..."
batch_count += 1
- visibilities.each do |visibility|
+ visibilities.each do |visibility|
begin
type = visibility.shareable_type
id = visibility.shareable_id.to_s
diff --git a/lib/tasks/assets.rake b/lib/tasks/assets.rake
index 9cbd410e2..39083eea3 100644
--- a/lib/tasks/assets.rake
+++ b/lib/tasks/assets.rake
@@ -5,24 +5,18 @@ namespace :assets do
renderer.render
end
- desc "Uglify bookmarklet snippet"
- task :uglify_bookmarklet => :environment do
- BookmarkletRenderer.compile
- end
-
desc "Create non digest assets"
task non_digest_assets: :environment do
logger = ::Logging::Logger["assets:non_digest_assets"]
non_digest_assets = Diaspora::Application.config.assets.non_digest_assets
- manifest_path = Dir.glob(File.join(Rails.root, "public/assets/manifest-*.json")).first
- JSON.load(File.new(manifest_path))["assets"].each do |logical_path, digested_path|
+ Rails.application.assets_manifest.assets.each do |logical_path, digested_path|
logical_pathname = Pathname.new(logical_path)
next unless non_digest_assets.any? {|testpath| logical_pathname.fnmatch?(testpath, File::FNM_PATHNAME) }
- full_digested_path = File.join(Rails.root, "public/assets", digested_path)
- full_non_digested_path = File.join(Rails.root, "public/assets", logical_path)
+ full_digested_path = Rails.root.join("public", "assets", digested_path)
+ full_non_digested_path = Rails.root.join("public", "assets", logical_path)
next unless FileUtils.uptodate?(full_digested_path, [full_non_digested_path])
@@ -35,7 +29,6 @@ namespace :assets do
# Augment precompile with error page generation
task :precompile do
Rake::Task["assets:generate_error_pages"].invoke
- Rake::Task["assets:uglify_bookmarklet"].invoke
Rake::Task["assets:non_digest_assets"].invoke
end
end
diff --git a/lib/tasks/tests.rake b/lib/tasks/tests.rake
index 11c9bf3c5..b6e2bcfcf 100644
--- a/lib/tasks/tests.rake
+++ b/lib/tasks/tests.rake
@@ -1,14 +1,13 @@
namespace :ci do
namespace :travis do
- task prepare_db: %w(db:create db:test:load)
- task prepare: %w(prepare_db assets:generate_error_pages)
+ task prepare_db: %w[db:create db:migrate]
+ task prepare: %w[prepare_db assets:generate_error_pages]
desc "Run everyhting except cucumber"
- task other: %w(prepare tests:generate_fixtures spec jasmine:ci)
+ task other: %w[prepare tests:generate_fixtures spec jasmine:ci]
desc "Run cucumber"
- task cucumber: %w(prepare rake:cucumber)
-
+ task cucumber: %w[prepare rake:cucumber]
end
end
diff --git a/script/server b/script/server
index 715697d44..46b492353 100755
--- a/script/server
+++ b/script/server
@@ -150,7 +150,7 @@ then
fi
# Check if assets are precompiled
-if [ "$RAILS_ENV" = "production" -a -z "$(find public/assets -maxdepth 1 -name 'main-*.js' -print -quit 2>/dev/null)" ]
+if [ "$RAILS_ENV" = "production" -a -z "$(find public/assets/ -maxdepth 1 -name 'main-*.js' -print -quit 2>/dev/null)" ]
then
fatal "You're running in production mode without having assets
precompiled. Now and after each update before you restart the
diff --git a/spec/controllers/admin/pods_controller_spec.rb b/spec/controllers/admin/pods_controller_spec.rb
index 9244351ee..784e29c6e 100644
--- a/spec/controllers/admin/pods_controller_spec.rb
+++ b/spec/controllers/admin/pods_controller_spec.rb
@@ -38,12 +38,12 @@ describe Admin::PodsController, type: :controller do
end
it "performs a connection test" do
- post :recheck, pod_id: 1
+ post :recheck, params: {pod_id: 1}
expect(response).to be_redirect
end
it "performs a connection test (format: json)" do
- post :recheck, pod_id: 1, format: :json
+ post :recheck, params: {pod_id: 1}, format: :json
expect(response.body).to eql(PodPresenter.new(@pod).to_json)
end
end
diff --git a/spec/controllers/admin/users_controller_spec.rb b/spec/controllers/admin/users_controller_spec.rb
index e96fa750e..7293ffab2 100644
--- a/spec/controllers/admin/users_controller_spec.rb
+++ b/spec/controllers/admin/users_controller_spec.rb
@@ -12,7 +12,7 @@ describe Admin::UsersController, :type => :controller do
expect(other_user).to receive(:close_account!)
allow(User).to receive(:find).and_return(other_user)
- post :close_account, id: other_user.id
+ post :close_account, params: {id: other_user.id}
end
end
diff --git a/spec/controllers/admins_controller_spec.rb b/spec/controllers/admins_controller_spec.rb
index 4dfdd0ef5..e9580a5d2 100644
--- a/spec/controllers/admins_controller_spec.rb
+++ b/spec/controllers/admins_controller_spec.rb
@@ -70,12 +70,12 @@ describe AdminsController, :type => :controller do
end
it 'searches on username' do
- get :user_search, admins_controller_user_search: { username: @user.username }
+ get :user_search, params: {admins_controller_user_search: {username: @user.username}}
expect(assigns[:users]).to eq([@user])
end
it 'searches on email' do
- get :user_search, admins_controller_user_search: { email: @user.email }
+ get :user_search, params: {admins_controller_user_search: {email: @user.email}}
expect(assigns[:users]).to eq([@user])
end
@@ -88,7 +88,7 @@ describe AdminsController, :type => :controller do
o_13.profile.birthday = 20.years.ago.to_date
o_13.profile.save!
- get :user_search, admins_controller_user_search: { under13: '1' }
+ get :user_search, params: {admins_controller_user_search: {under13: "1"}}
expect(assigns[:users]).to include(u_13)
expect(assigns[:users]).not_to include(o_13)
@@ -110,20 +110,20 @@ describe AdminsController, :type => :controller do
end
it 'does not die if you do it twice' do
- get :admin_inviter, :identifier => 'bob@moms.com'
- get :admin_inviter, :identifier => 'bob@moms.com'
+ get :admin_inviter, params: {identifier: "bob@moms.com"}
+ get :admin_inviter, params: {identifier: "bob@moms.com"}
expect(response).to be_redirect
end
it 'invites a new user' do
expect(EmailInviter).to receive(:new).and_return(double.as_null_object)
- get :admin_inviter, :identifier => 'bob@moms.com'
+ get :admin_inviter, params: {identifier: "bob@moms.com"}
expect(response).to redirect_to user_search_path
expect(flash.notice).to include("invitation sent")
end
it "doesn't invite an existing user" do
- get :admin_inviter, identifier: bob.email
+ get :admin_inviter, params: {identifier: bob.email}
expect(response).to redirect_to user_search_path
expect(flash.notice).to include("error sending invite")
end
@@ -148,7 +148,7 @@ describe AdminsController, :type => :controller do
it "succeeds and renders stats for different ranges" do
%w(week 2weeks month).each do |range|
- get :stats, range: range
+ get :stats, params: {range: range}
expect(response).to be_success
expect(response).to render_template(:stats)
expect(response.body).not_to include(
diff --git a/spec/controllers/api/openid_connect/authorizations_controller_spec.rb b/spec/controllers/api/openid_connect/authorizations_controller_spec.rb
index f32ae0957..54435e0b3 100644
--- a/spec/controllers/api/openid_connect/authorizations_controller_spec.rb
+++ b/spec/controllers/api/openid_connect/authorizations_controller_spec.rb
@@ -1,7 +1,5 @@
describe Api::OpenidConnect::AuthorizationsController, type: :request do
let!(:client) { FactoryGirl.create(:o_auth_application) }
- let!(:client_with_xss) { FactoryGirl.create(:o_auth_application_with_xss) }
- let!(:client_with_multiple_redirects) { FactoryGirl.create(:o_auth_application_with_multiple_redirects) }
before do
sign_in alice, scope: :user
@@ -12,19 +10,19 @@ describe Api::OpenidConnect::AuthorizationsController, type: :request do
context "when valid parameters are passed" do
context "as GET request" do
it "should return a form page" do
- get new_api_openid_connect_authorization_path, client_id: client.client_id,
+ get new_api_openid_connect_authorization_path, params: {client_id: client.client_id,
redirect_uri: "http://localhost:3000/", response_type: "id_token",
- scope: "openid", nonce: SecureRandom.hex(16), state: SecureRandom.hex(16)
+ scope: "openid", nonce: SecureRandom.hex(16), state: SecureRandom.hex(16)}
expect(response.body).to match("Diaspora Test Client")
end
end
context "using claims" do
it "should return a form page" do
- get new_api_openid_connect_authorization_path, client_id: client.client_id,
+ get new_api_openid_connect_authorization_path, params: {client_id: client.client_id,
redirect_uri: "http://localhost:3000/", response_type: "id_token",
scope: "openid", claims: "{\"userinfo\": {\"name\": {\"essential\": true}}}",
- nonce: SecureRandom.hex(16), state: SecureRandom.hex(16)
+ nonce: SecureRandom.hex(16), state: SecureRandom.hex(16)}
expect(response.body).to match("Diaspora Test Client")
end
end
@@ -37,9 +35,9 @@ describe Api::OpenidConnect::AuthorizationsController, type: :request do
claims: {userinfo: {name: {essential: true}}}}
payload = JWT.encoded_payload(JSON.parse(payload_hash.to_json))
request_object = header + "." + payload + "."
- get new_api_openid_connect_authorization_path, client_id: client.client_id,
+ get new_api_openid_connect_authorization_path, params: {client_id: client.client_id,
redirect_uri: "http://localhost:3000/", response_type: "id_token",
- scope: "openid", nonce: "hello", state: "hello", request: request_object
+ scope: "openid", nonce: "hello", state: "hello", request: request_object}
expect(response.body).to match("Diaspora Test Client")
end
end
@@ -51,18 +49,18 @@ describe Api::OpenidConnect::AuthorizationsController, type: :request do
response_type: "id_token", scope: "openid", nonce: "hello", state: "hello"}
payload = JWT.encoded_payload(JSON.parse(payload_hash.to_json))
request_object = header + "." + payload + "."
- get new_api_openid_connect_authorization_path, client_id: client.client_id,
+ get new_api_openid_connect_authorization_path, params: {client_id: client.client_id,
redirect_uri: "http://localhost:3000/", response_type: "id_token",
- scope: "openid", nonce: "hello", state: "hello", request: request_object
+ scope: "openid", nonce: "hello", state: "hello", request: request_object}
expect(response.body).to match("Diaspora Test Client")
end
end
context "as POST request" do
it "should return a form page" do
- post api_openid_connect_authorizations_new_path, client_id: client.client_id,
+ post api_openid_connect_authorizations_new_path, params: {client_id: client.client_id,
redirect_uri: "http://localhost:3000/", response_type: "id_token",
- scope: "openid", nonce: SecureRandom.hex(16), state: SecureRandom.hex(16)
+ scope: "openid", nonce: SecureRandom.hex(16), state: SecureRandom.hex(16)}
expect(response.body).to match("Diaspora Test Client")
end
end
@@ -70,9 +68,8 @@ describe Api::OpenidConnect::AuthorizationsController, type: :request do
context "when client id is missing" do
it "should return an bad request error" do
- post api_openid_connect_authorizations_new_path,
- redirect_uri: "http://localhost:3000/", response_type: "id_token",
- scope: "openid", nonce: SecureRandom.hex(16), state: SecureRandom.hex(16)
+ post api_openid_connect_authorizations_new_path, params: {redirect_uri: "http://localhost:3000/",
+ response_type: "id_token", scope: "openid", nonce: SecureRandom.hex(16), state: SecureRandom.hex(16)}
expect(response.body).to include("The request was malformed")
end
end
@@ -84,8 +81,8 @@ describe Api::OpenidConnect::AuthorizationsController, type: :request do
# When client has only one redirect uri registered, only that redirect uri can be used. Hence,
# we should implicitly assume the client wants to use that registered URI.
# See https://github.com/nov/rack-oauth2/blob/master/lib/rack/oauth2/server/authorize.rb#L63
- post api_openid_connect_authorizations_new_path, client_id: client.client_id, response_type: "id_token",
- scope: "openid", nonce: SecureRandom.hex(16), state: SecureRandom.hex(16)
+ post api_openid_connect_authorizations_new_path, params: {client_id: client.client_id,
+ response_type: "id_token", scope: "openid", nonce: SecureRandom.hex(16), state: SecureRandom.hex(16)}
expect(response.body).to match("Diaspora Test Client")
end
end
@@ -93,45 +90,46 @@ describe Api::OpenidConnect::AuthorizationsController, type: :request do
context "when multiple redirect URLs are pre-registered" do
it "should return an invalid request error" do
- post api_openid_connect_authorizations_new_path, client_id: client_with_multiple_redirects.client_id,
- response_type: "id_token",
- scope: "openid", nonce: SecureRandom.hex(16), state: SecureRandom.hex(16)
+ client_with_multiple_redirects =
+ FactoryGirl.create(:o_auth_application, redirect_uris: %w[http://localhost:3000/ http://localhost/])
+ post api_openid_connect_authorizations_new_path, params: {client_id: client_with_multiple_redirects.client_id,
+ response_type: "id_token", scope: "openid", nonce: SecureRandom.hex(16), state: SecureRandom.hex(16)}
expect(response.body).to include("The request was malformed")
end
end
context "when redirect URI does not match pre-registered URIs" do
it "should return an invalid request error" do
- post api_openid_connect_authorizations_new_path, client_id: client.client_id,
+ post api_openid_connect_authorizations_new_path, params: {client_id: client.client_id,
redirect_uri: "http://localhost:2000/",
- response_type: "id_token", scope: "openid", nonce: SecureRandom.hex(16)
+ response_type: "id_token", scope: "openid", nonce: SecureRandom.hex(16)}
expect(response.body).to include("Invalid client id or redirect uri")
end
end
context "when an unsupported scope is passed in" do
it "should return an invalid scope error" do
- post api_openid_connect_authorizations_new_path, client_id: client.client_id,
+ post api_openid_connect_authorizations_new_path, params: {client_id: client.client_id,
redirect_uri: "http://localhost:3000/", response_type: "id_token",
- scope: "random", nonce: SecureRandom.hex(16), state: SecureRandom.hex(16)
+ scope: "random", nonce: SecureRandom.hex(16), state: SecureRandom.hex(16)}
expect(response.body).to match("error=invalid_scope")
end
end
context "when nonce is missing" do
it "should return an invalid request error" do
- post api_openid_connect_authorizations_new_path, client_id: client.client_id,
+ post api_openid_connect_authorizations_new_path, params: {client_id: client.client_id,
redirect_uri: "http://localhost:3000/",
- response_type: "id_token", scope: "openid", state: SecureRandom.hex(16)
+ response_type: "id_token", scope: "openid", state: SecureRandom.hex(16)}
expect(response.location).to match("error=invalid_request")
end
end
context "when prompt is none" do
it "should return an interaction required error" do
- post api_openid_connect_authorizations_new_path, client_id: client.client_id,
+ post api_openid_connect_authorizations_new_path, params: {client_id: client.client_id,
redirect_uri: "http://localhost:3000/",
- response_type: "id_token", scope: "openid", state: 1234, display: "page", prompt: "none"
+ response_type: "id_token", scope: "openid", state: 1234, display: "page", prompt: "none"}
expect(response.body).to include("User must already be authorized when `prompt` is `none`")
end
end
@@ -142,27 +140,27 @@ describe Api::OpenidConnect::AuthorizationsController, type: :request do
end
it "should return an interaction required error" do
- post api_openid_connect_authorizations_new_path, client_id: client.client_id,
+ post api_openid_connect_authorizations_new_path, params: {client_id: client.client_id,
redirect_uri: "http://localhost:3000/",
- response_type: "id_token", scope: "openid", state: 1234, display: "page", prompt: "none"
+ response_type: "id_token", scope: "openid", state: 1234, display: "page", prompt: "none"}
expect(response.body).to include("User must already be logged in when `prompt` is `none`")
end
end
context "when prompt is none and consent" do
it "should return an interaction required error" do
- post api_openid_connect_authorizations_new_path, client_id: client.client_id,
+ post api_openid_connect_authorizations_new_path, params: {client_id: client.client_id,
redirect_uri: "http://localhost:3000/",
- response_type: "id_token", scope: "openid", state: 1234, display: "page", prompt: "none consent"
+ response_type: "id_token", scope: "openid", state: 1234, display: "page", prompt: "none consent"}
expect(response.location).to match("error=invalid_request")
end
end
context "when prompt is select_account" do
it "should return an account_selection_required error" do
- post api_openid_connect_authorizations_new_path, client_id: client.client_id,
+ post api_openid_connect_authorizations_new_path, params: {client_id: client.client_id,
redirect_uri: "http://localhost:3000/",
- response_type: "id_token", scope: "openid", state: 1234, display: "page", prompt: "select_account"
+ response_type: "id_token", scope: "openid", state: 1234, display: "page", prompt: "select_account"}
expect(response.location).to match("error=account_selection_required")
expect(response.location).to match("state=1234")
end
@@ -170,26 +168,28 @@ describe Api::OpenidConnect::AuthorizationsController, type: :request do
context "when prompt is none and client ID is invalid" do
it "should return an account_selection_required error" do
- post api_openid_connect_authorizations_new_path, client_id: "random", redirect_uri: "http://localhost:3000/",
- response_type: "id_token", scope: "openid", state: 1234, display: "page", prompt: "none"
+ post api_openid_connect_authorizations_new_path, params: {client_id: "random",
+ redirect_uri: "http://localhost:3000/", response_type: "id_token", scope: "openid", state: 1234,
+ display: "page", prompt: "none"}
expect(response.body).to include("Invalid client id or redirect uri")
end
end
context "when prompt is none and redirect URI does not match pre-registered URIs" do
it "should return an account_selection_required error" do
- post api_openid_connect_authorizations_new_path, client_id: client.client_id,
+ post api_openid_connect_authorizations_new_path, params: {client_id: client.client_id,
redirect_uri: "http://randomuri:3000/",
- response_type: "id_token", scope: "openid", state: 1234, display: "page", prompt: "none"
+ response_type: "id_token", scope: "openid", state: 1234, display: "page", prompt: "none"}
expect(response.body).to include("Invalid client id or redirect uri")
end
end
context "when XSS script is passed as name" do
it "should escape html" do
- post api_openid_connect_authorizations_new_path, client_id: client_with_xss.client_id,
+ client_with_xss = FactoryGirl.create(:o_auth_application_with_xss)
+ post api_openid_connect_authorizations_new_path, params: {client_id: client_with_xss.client_id,
redirect_uri: "http://localhost:3000/",
- response_type: "id_token", scope: "openid", nonce: SecureRandom.hex(16), state: SecureRandom.hex(16)
+ response_type: "id_token", scope: "openid", nonce: SecureRandom.hex(16), state: SecureRandom.hex(16)}
expect(response.body).to_not include("<script>alert(0);</script>")
end
end
@@ -203,9 +203,9 @@ describe Api::OpenidConnect::AuthorizationsController, type: :request do
context "when valid parameters are passed" do
before do
- get new_api_openid_connect_authorization_path, client_id: client.client_id,
+ get new_api_openid_connect_authorization_path, params: {client_id: client.client_id,
redirect_uri: "http://localhost:3000/", response_type: "id_token",
- scope: "openid", nonce: 413_093_098_3, state: 413_093_098_3
+ scope: "openid", nonce: 413_093_098_3, state: 413_093_098_3}
end
it "should return the id token in a fragment" do
@@ -224,10 +224,10 @@ describe Api::OpenidConnect::AuthorizationsController, type: :request do
context "when prompt is none" do
it "should return the id token in a fragment" do
- post api_openid_connect_authorizations_new_path, client_id: client.client_id,
+ post api_openid_connect_authorizations_new_path, params: {client_id: client.client_id,
redirect_uri: "http://localhost:3000/",
response_type: "id_token", scope: "openid", nonce: 413_093_098_3, state: 413_093_098_3,
- display: "page", prompt: "none"
+ display: "page", prompt: "none"}
expect(response.location).to include("id_token=")
encoded_id_token = response.location[/(?<=id_token=)[^&]+/]
decoded_token = OpenIDConnect::ResponseObject::IdToken.decode encoded_id_token,
@@ -239,19 +239,19 @@ describe Api::OpenidConnect::AuthorizationsController, type: :request do
context "when prompt contains consent" do
it "should return a consent form page" do
- get new_api_openid_connect_authorization_path, client_id: client.client_id,
+ get new_api_openid_connect_authorization_path, params: {client_id: client.client_id,
redirect_uri: "http://localhost:3000/",
response_type: "id_token", scope: "openid", nonce: 413_093_098_3, state: 413_093_098_3,
- display: "page", prompt: "consent"
+ display: "page", prompt: "consent"}
expect(response.body).to match("Diaspora Test Client")
end
end
context "when scopes are escalated" do
before do
- get new_api_openid_connect_authorization_path, client_id: client.client_id,
+ get new_api_openid_connect_authorization_path, params: {client_id: client.client_id,
redirect_uri: "http://localhost:3000/", response_type: "id_token",
- scope: "openid read", nonce: 413_093_098_3, state: 413_093_098_3
+ scope: "openid read", nonce: 413_093_098_3, state: 413_093_098_3}
end
it "should receive another authorization request" do
@@ -259,7 +259,7 @@ describe Api::OpenidConnect::AuthorizationsController, type: :request do
end
it "should overwrite old authorization scope after approval" do
- post api_openid_connect_authorizations_path, approve: "true"
+ post api_openid_connect_authorizations_path, params: {approve: "true"}
authorization_with_old_scope =
Api::OpenidConnect::Authorization.find_by_client_id_user_and_scopes(client.client_id, alice, ["openid"])
expect(authorization_with_old_scope).to be_nil
@@ -271,14 +271,14 @@ describe Api::OpenidConnect::AuthorizationsController, type: :request do
describe "#create" do
context "when id_token token" do
before do
- get new_api_openid_connect_authorization_path, client_id: client.client_id,
+ get new_api_openid_connect_authorization_path, params: {client_id: client.client_id,
redirect_uri: "http://localhost:3000/", response_type: "id_token token",
- scope: "openid", nonce: 418_093_098_3, state: 418_093_098_3
+ scope: "openid", nonce: 418_093_098_3, state: 418_093_098_3}
end
context "when authorization is approved" do
before do
- post api_openid_connect_authorizations_path, approve: "true"
+ post api_openid_connect_authorizations_path, params: {approve: "true"}
end
it "should return the id token in a fragment" do
@@ -302,14 +302,14 @@ describe Api::OpenidConnect::AuthorizationsController, type: :request do
context "when id_token" do
before do
- get new_api_openid_connect_authorization_path, client_id: client.client_id,
+ get new_api_openid_connect_authorization_path, params: {client_id: client.client_id,
redirect_uri: "http://localhost:3000/", response_type: "id_token",
- scope: "openid", nonce: 418_093_098_3, state: 418_093_098_3
+ scope: "openid", nonce: 418_093_098_3, state: 418_093_098_3}
end
context "when authorization is approved" do
before do
- post api_openid_connect_authorizations_path, approve: "true"
+ post api_openid_connect_authorizations_path, params: {approve: "true"}
end
it "should return the id token in a fragment" do
@@ -328,7 +328,7 @@ describe Api::OpenidConnect::AuthorizationsController, type: :request do
context "when authorization is denied" do
before do
- post api_openid_connect_authorizations_path, approve: "false"
+ post api_openid_connect_authorizations_path, params: {approve: "false"}
end
it "should return an error in the fragment" do
@@ -343,14 +343,14 @@ describe Api::OpenidConnect::AuthorizationsController, type: :request do
context "when code" do
before do
- get new_api_openid_connect_authorization_path, client_id: client.client_id,
+ get new_api_openid_connect_authorization_path, params: {client_id: client.client_id,
redirect_uri: "http://localhost:3000/", response_type: "code",
- scope: "openid", nonce: 418_093_098_3, state: 418_093_098_3
+ scope: "openid", nonce: 418_093_098_3, state: 418_093_098_3}
end
context "when authorization is approved" do
before do
- post api_openid_connect_authorizations_path, approve: "true"
+ post api_openid_connect_authorizations_path, params: {approve: "true"}
end
it "should return the code" do
@@ -364,7 +364,7 @@ describe Api::OpenidConnect::AuthorizationsController, type: :request do
context "when authorization is denied" do
before do
- post api_openid_connect_authorizations_path, approve: "false"
+ post api_openid_connect_authorizations_path, params: {approve: "false"}
end
it "should return an error" do
@@ -379,14 +379,10 @@ describe Api::OpenidConnect::AuthorizationsController, type: :request do
end
describe "#destroy" do
- let!(:auth_with_read) { FactoryGirl.create(:auth_with_read) }
-
context "with existent authorization" do
- before do
- delete api_openid_connect_authorization_path(auth_with_read.id)
- end
-
it "removes the authorization" do
+ auth_with_read = FactoryGirl.create(:auth_with_read, o_auth_application: client)
+ delete api_openid_connect_authorization_path(auth_with_read.id)
expect(Api::OpenidConnect::Authorization.find_by(id: auth_with_read.id)).to be_nil
end
end
diff --git a/spec/controllers/api/openid_connect/clients_controller_spec.rb b/spec/controllers/api/openid_connect/clients_controller_spec.rb
index a12ad43b8..33776fdfb 100644
--- a/spec/controllers/api/openid_connect/clients_controller_spec.rb
+++ b/spec/controllers/api/openid_connect/clients_controller_spec.rb
@@ -9,11 +9,11 @@ describe Api::OpenidConnect::ClientsController, type: :controller, suppress_csrf
"User-Agent" => "Faraday v0.11.0"
})
.to_return(status: 200, body: "[\"http://localhost\"]", headers: {})
- post :create, redirect_uris: ["http://localhost"], client_name: "diaspora client",
+ post :create, params: {redirect_uris: ["http://localhost"], client_name: "diaspora client",
response_types: [], grant_types: [], application_type: "web", contacts: [],
logo_uri: "http://example.com/logo.png", client_uri: "http://example.com/client",
policy_uri: "http://example.com/policy", tos_uri: "http://example.com/tos",
- sector_identifier_uri: "http://example.com/uris", subject_type: "pairwise"
+ sector_identifier_uri: "http://example.com/uris", subject_type: "pairwise"}
client_json = JSON.parse(response.body)
expect(client_json["client_id"].length).to eq(32)
expect(client_json["ppid"]).to eq(true)
@@ -29,7 +29,7 @@ describe Api::OpenidConnect::ClientsController, type: :controller, suppress_csrf
"User-Agent" => "Faraday v0.11.0"
})
.to_return(status: 200, body: "[\"http://localhost\"]", headers: {})
- post :create, redirect_uris: ["http://localhost"], client_name: "diaspora client",
+ post :create, params: {redirect_uris: ["http://localhost"], client_name: "diaspora client",
response_types: [], grant_types: [], application_type: "web", contacts: [],
logo_uri: "http://example.com/logo.png", client_uri: "http://example.com/client",
policy_uri: "http://example.com/policy", tos_uri: "http://example.com/tos",
@@ -74,7 +74,7 @@ describe Api::OpenidConnect::ClientsController, type: :controller, suppress_csrf
kid: "a3"
}
]
- }
+ }}
client_json = JSON.parse(response.body)
expect(client_json["client_id"].length).to eq(32)
expect(client_json["ppid"]).to eq(true)
@@ -98,13 +98,13 @@ describe Api::OpenidConnect::ClientsController, type: :controller, suppress_csrf
})
.to_return(status: 200,
body: "{\"keys\":[{\"kty\":\"RSA\",\"e\":\"AQAB\",\"n\":\"qpW\",\"use\":\"sig\"}]}", headers: {})
- post :create, redirect_uris: ["http://localhost"], client_name: "diaspora client",
+ post :create, params: {redirect_uris: ["http://localhost"], client_name: "diaspora client",
response_types: [], grant_types: [], application_type: "web", contacts: [],
logo_uri: "http://example.com/logo.png", client_uri: "http://example.com/client",
policy_uri: "http://example.com/policy", tos_uri: "http://example.com/tos",
sector_identifier_uri: "http://example.com/uris", subject_type: "pairwise",
token_endpoint_auth_method: "private_key_jwt",
- jwks_uri: "https://kentshikama.com/api/openid_connect/jwks.json"
+ jwks_uri: "https://kentshikama.com/api/openid_connect/jwks.json"}
client_json = JSON.parse(response.body)
expect(client_json["client_id"].length).to eq(32)
expect(client_json["ppid"]).to eq(true)
@@ -113,9 +113,9 @@ describe Api::OpenidConnect::ClientsController, type: :controller, suppress_csrf
context "when redirect uri is missing" do
it "should return a invalid_client_metadata error" do
- post :create, response_types: [], grant_types: [], application_type: "web", contacts: [],
+ post :create, params: {response_types: [], grant_types: [], application_type: "web", contacts: [],
logo_uri: "http://example.com/logo.png", client_uri: "http://example.com/client",
- policy_uri: "http://example.com/policy", tos_uri: "http://example.com/tos"
+ policy_uri: "http://example.com/policy", tos_uri: "http://example.com/tos"}
client_json = JSON.parse(response.body)
expect(client_json["error"]).to have_content("invalid_client_metadata")
end
@@ -127,7 +127,7 @@ describe Api::OpenidConnect::ClientsController, type: :controller, suppress_csrf
context "when an OIDC client already exists" do
it "should return a client id" do
- get :find, client_name: client.client_name
+ get :find, params: {client_name: client.client_name}
client_id_json = JSON.parse(response.body)
expect(client_id_json["client_id"]).to eq(client.client_id)
end
@@ -135,7 +135,7 @@ describe Api::OpenidConnect::ClientsController, type: :controller, suppress_csrf
context "when an OIDC client doesn't already exist" do
it "should return the appropriate error" do
- get :find, client_name: "random_name"
+ get :find, params: {client_name: "random_name"}
client_id_json = JSON.parse(response.body)
expect(client_id_json["error"]).to eq("Client with name random_name does not exist")
end
diff --git a/spec/controllers/api/openid_connect/discovery_controller_spec.rb b/spec/controllers/api/openid_connect/discovery_controller_spec.rb
index 9d2ff4526..73d6e51fd 100644
--- a/spec/controllers/api/openid_connect/discovery_controller_spec.rb
+++ b/spec/controllers/api/openid_connect/discovery_controller_spec.rb
@@ -1,20 +1,4 @@
describe Api::OpenidConnect::DiscoveryController, type: :controller do
- describe "#webfinger" do
- before do
- get :webfinger, resource: "http://example.com/bob"
- end
-
- it "should return a url to the openid-configuration" do
- json_body = JSON.parse(response.body)
- expect(json_body["links"].first["href"]).to eq(root_url)
- end
-
- it "should return the resource in the subject" do
- json_body = JSON.parse(response.body)
- expect(json_body["subject"]).to eq("http://example.com/bob")
- end
- end
-
describe "#configuration" do
before do
get :configuration
diff --git a/spec/controllers/api/openid_connect/token_endpoint_controller_spec.rb b/spec/controllers/api/openid_connect/token_endpoint_controller_spec.rb
index c3a484085..766a3c806 100644
--- a/spec/controllers/api/openid_connect/token_endpoint_controller_spec.rb
+++ b/spec/controllers/api/openid_connect/token_endpoint_controller_spec.rb
@@ -3,13 +3,14 @@ describe Api::OpenidConnect::TokenEndpointController, type: :controller, suppres
describe "#create" do
it "returns 200 on success" do
- post :create,
- grant_type: "authorization_code",
- code: auth.create_code,
- redirect_uri: auth.redirect_uri,
- scope: auth.scopes.join(" "),
- client_id: auth.o_auth_application.client_id,
- client_secret: auth.o_auth_application.client_secret
+ post :create, params: {
+ grant_type: "authorization_code",
+ code: auth.create_code,
+ redirect_uri: auth.redirect_uri,
+ scope: auth.scopes.join(" "),
+ client_id: auth.o_auth_application.client_id,
+ client_secret: auth.o_auth_application.client_secret
+ }
expect(response.code).to eq("200")
end
end
diff --git a/spec/controllers/aspect_memberships_controller_spec.rb b/spec/controllers/aspect_memberships_controller_spec.rb
index 90e706e29..a577a613a 100644
--- a/spec/controllers/aspect_memberships_controller_spec.rb
+++ b/spec/controllers/aspect_memberships_controller_spec.rb
@@ -22,13 +22,13 @@ describe AspectMembershipsController, type: :controller do
end
it "succeeds" do
- post :create, format: :json, person_id: bob.person.id, aspect_id: @aspect1.id
+ post :create, params: {person_id: bob.person.id, aspect_id: @aspect1.id}, format: :json
expect(response).to be_success
end
it "creates an aspect membership" do
expect {
- post :create, format: :json, person_id: bob.person.id, aspect_id: @aspect1.id
+ post :create, params: {person_id: bob.person.id, aspect_id: @aspect1.id}, format: :json
}.to change {
alice.contact_for(bob.person).aspect_memberships.count
}.by(1)
@@ -38,29 +38,23 @@ describe AspectMembershipsController, type: :controller do
# argggg why?
alice.contacts.reload
expect {
- post :create, format: :json, person_id: @person.id, aspect_id: @aspect0.id
+ post :create, params: {person_id: @person.id, aspect_id: @aspect0.id}, format: :json
}.to change {
alice.contacts.size
}.by(1)
end
- it "failure flashes error" do
- expect(alice).to receive(:share_with).and_return(nil)
- post :create, format: :mobile, person_id: @person.id, aspect_id: @aspect0.id
- expect(flash[:error]).not_to be_blank
- end
-
it "does not 500 on a duplicate key error" do
- params = {format: :json, person_id: @person.id, aspect_id: @aspect0.id}
- post :create, params
- post :create, params
+ params = {person_id: @person.id, aspect_id: @aspect0.id}
+ post :create, params: params, format: :json
+ post :create, params: params, format: :json
expect(response.status).to eq(400)
expect(response.body).to eq(I18n.t("aspect_memberships.destroy.invalid_statement"))
end
context "json" do
it "returns the aspect membership" do
- post :create, format: :json, person_id: @person.id, aspect_id: @aspect0.id
+ post :create, params: {person_id: @person.id, aspect_id: @aspect0.id}, format: :json
contact = @controller.current_user.contact_for(@person)
expect(response.body).to eq(AspectMembershipPresenter.new(contact.aspect_memberships.first).base_hash.to_json)
@@ -68,7 +62,7 @@ describe AspectMembershipsController, type: :controller do
it "responds with an error message when the request failed" do
expect(alice).to receive(:share_with).and_return(nil)
- post :create, format: :json, person_id: @person.id, aspect_id: @aspect0.id
+ post :create, params: {person_id: @person.id, aspect_id: @aspect0.id}, format: :json
expect(response.status).to eq(409)
expect(response.body).to eq(I18n.t("aspects.add_to_aspect.failure"))
end
@@ -78,22 +72,14 @@ describe AspectMembershipsController, type: :controller do
describe "#destroy" do
it "removes contacts from an aspect" do
membership = alice.add_contact_to_aspect(@contact, @aspect1)
- delete :destroy, format: :json, id: membership.id
+ delete :destroy, params: {id: membership.id}, format: :json
expect(response).to be_success
@aspect1.reload
expect(@aspect1.contacts.to_a).not_to include @contact
end
- it "does not 500 on an html request" do
- membership = alice.add_contact_to_aspect(@contact, @aspect1)
- delete :destroy, id: membership.id
- expect(response).to redirect_to :back
- @aspect1.reload
- expect(@aspect1.contacts.to_a).not_to include @contact
- end
-
it "aspect membership does not exist" do
- delete :destroy, format: :json, id: 123
+ delete :destroy, params: {id: 123}, format: :json
expect(response).not_to be_success
expect(response.body).to eq(I18n.t("aspect_memberships.destroy.no_membership"))
end
diff --git a/spec/controllers/aspects_controller_spec.rb b/spec/controllers/aspects_controller_spec.rb
index 4278b078d..1f39d7312 100644
--- a/spec/controllers/aspects_controller_spec.rb
+++ b/spec/controllers/aspects_controller_spec.rb
@@ -16,11 +16,11 @@ describe AspectsController, :type => :controller do
describe "#show" do
it "succeeds" do
- get :show, 'id' => @alices_aspect_1.id.to_s
+ get :show, params: {id: @alices_aspect_1.id.to_s}
expect(response).to be_redirect
end
it 'redirects on an invalid id' do
- get :show, 'id' => 0
+ get :show, params: {id: 0}
expect(response).to be_redirect
end
end
@@ -29,12 +29,12 @@ describe AspectsController, :type => :controller do
context "with valid params" do
it "creates an aspect" do
expect(alice.aspects.count).to eq(2)
- post :create, aspect: {name: "new aspect"}
+ post :create, params: {aspect: {name: "new aspect"}}
expect(alice.reload.aspects.count).to eq(3)
end
it "returns the created aspect as json" do
- post :create, aspect: {name: "new aspect"}
+ post :create, params: {aspect: {name: "new aspect"}}
expect(JSON.parse(response.body)["id"]).to eq Aspect.find_by_name("new aspect").id
expect(JSON.parse(response.body)["name"]).to eq "new aspect"
end
@@ -42,19 +42,19 @@ describe AspectsController, :type => :controller do
context "with person_id param" do
it "creates a contact if one does not already exist" do
expect {
- post :create, format: "js", person_id: eve.person.id, aspect: {name: "new"}
+ post :create, params: {person_id: eve.person.id, aspect: {name: "new"}}, format: :js
}.to change {
alice.contacts.count
}.by(1)
end
it "adds a new contact to the new aspect" do
- post :create, format: "js", person_id: eve.person.id, aspect: {name: "new"}
+ post :create, params: {person_id: eve.person.id, aspect: {name: "new"}}, format: :js
expect(alice.aspects.find_by_name("new").contacts.count).to eq(1)
end
it "adds an existing contact to the new aspect" do
- post :create, format: "js", person_id: bob.person.id, aspect: {name: "new"}
+ post :create, params: {person_id: bob.person.id, aspect: {name: "new"}}, format: :js
expect(alice.aspects.find_by_name("new").contacts.count).to eq(1)
end
end
@@ -63,12 +63,12 @@ describe AspectsController, :type => :controller do
context "with invalid params" do
it "does not create an aspect" do
expect(alice.aspects.count).to eq(2)
- post :create, aspect: {name: ""}
+ post :create, params: {aspect: {name: ""}}
expect(alice.reload.aspects.count).to eq(2)
end
it "responds with 422" do
- post :create, aspect: {name: ""}
+ post :create, params: {aspect: {name: ""}}
expect(response.status).to eq(422)
end
end
@@ -83,13 +83,13 @@ describe AspectsController, :type => :controller do
new_user = FactoryGirl.create :user
params = {"name" => "Bruisers"}
params[:user_id] = new_user.id
- put('update', :id => @alices_aspect_1.id, "aspect" => params)
+ put :update, params: {id: @alices_aspect_1.id, aspect: params}
expect(Aspect.find(@alices_aspect_1.id).user_id).to eq(alice.id)
end
it "should return the name and id of the updated item" do
params = {"name" => "Bruisers"}
- put('update', :id => @alices_aspect_1.id, "aspect" => params)
+ put :update, params: {id: @alices_aspect_1.id, aspect: params}
expect(response.body).to eq({ :id => @alices_aspect_1.id, :name => "Bruisers" }.to_json)
end
end
@@ -100,7 +100,7 @@ describe AspectsController, :type => :controller do
@alices_aspect_2.update_attributes(order_id: 20)
ordered_aspect_ids = [@alices_aspect_2.id, @alices_aspect_1.id]
- put(:update_order, ordered_aspect_ids: ordered_aspect_ids)
+ put :update_order, params: {ordered_aspect_ids: ordered_aspect_ids}
expect(Aspect.find(@alices_aspect_1.id).order_id).to eq(1)
expect(Aspect.find(@alices_aspect_2.id).order_id).to eq(0)
@@ -115,12 +115,12 @@ describe AspectsController, :type => :controller do
context "with no auto follow back aspect" do
it "destoys the aspect" do
expect(alice.aspects.to_a).to include @alices_aspect_1
- post :destroy, id: @alices_aspect_1.id
+ post :destroy, params: {id: @alices_aspect_1.id}
expect(alice.reload.aspects.to_a).not_to include @alices_aspect_1
end
it "renders a flash message on success" do
- post :destroy, id: @alices_aspect_1.id
+ post :destroy, params: {id: @alices_aspect_1.id}
expect(flash[:notice]).to eq(I18n.t("aspects.destroy.success", name: @alices_aspect_1.name))
expect(flash[:error]).to be_blank
end
@@ -135,20 +135,20 @@ describe AspectsController, :type => :controller do
it "destoys the aspect" do
expect(alice.aspects.to_a).to include @alices_aspect_1
- post :destroy, id: @alices_aspect_1.id
+ post :destroy, params: {id: @alices_aspect_1.id}
expect(alice.reload.aspects.to_a).not_to include @alices_aspect_1
end
it "disables auto follow back" do
expect(alice.auto_follow_back).to be(true)
expect(alice.auto_follow_back_aspect).to eq(@alices_aspect_1)
- post :destroy, id: @alices_aspect_1.id
+ post :destroy, params: {id: @alices_aspect_1.id}
expect(alice.auto_follow_back).to be(false)
expect(alice.auto_follow_back_aspect).to eq(nil)
end
it "renders a flash message telling you to set a new auto follow back aspect" do
- post :destroy, id: @alices_aspect_1.id
+ post :destroy, params: {id: @alices_aspect_1.id}
expect(flash[:notice]).to eq(I18n.t("aspects.destroy.success_auto_follow_back", name: @alices_aspect_1.name))
expect(flash[:error]).to be_blank
end
@@ -160,7 +160,7 @@ describe AspectsController, :type => :controller do
@alices_aspect_1.contacts_visible = false
@alices_aspect_1.save
- xhr :get, :toggle_contact_visibility, :aspect_id => @alices_aspect_1.id
+ get :toggle_contact_visibility, xhr: true, params: {aspect_id: @alices_aspect_1.id}
expect(@alices_aspect_1.reload.contacts_visible).to be true
end
@@ -168,7 +168,7 @@ describe AspectsController, :type => :controller do
@alices_aspect_1.contacts_visible = true
@alices_aspect_1.save
- xhr :get, :toggle_contact_visibility, :aspect_id => @alices_aspect_1.id
+ get :toggle_contact_visibility, xhr: true, params: {aspect_id: @alices_aspect_1.id}
expect(@alices_aspect_1.reload.contacts_visible).to be false
end
end
diff --git a/spec/controllers/blocks_controller_spec.rb b/spec/controllers/blocks_controller_spec.rb
index de16662ea..0a774da3a 100644
--- a/spec/controllers/blocks_controller_spec.rb
+++ b/spec/controllers/blocks_controller_spec.rb
@@ -6,25 +6,18 @@ describe BlocksController, :type => :controller do
describe "#create" do
it "creates a block" do
expect {
- post :create, :block => {:person_id => eve.person.id}
+ post :create, params: {block: {person_id: eve.person.id}}, format: :json
}.to change { alice.blocks.count }.by(1)
end
- it "redirects back" do
- post :create, :block => { :person_id => 2 }
-
- expect(response).to be_redirect
- end
-
- it "notifies the user" do
- post :create, :block => { :person_id => 2 }
-
- expect(flash).not_to be_empty
+ it "responds with 204" do
+ post :create, params: {block: {person_id: eve.person.id}}, format: :json
+ expect(response.status).to eq(204)
end
it "calls #disconnect_if_contact" do
expect(@controller).to receive(:disconnect_if_contact).with(bob.person)
- post :create, :block => {:person_id => bob.person.id}
+ post :create, params: {block: {person_id: bob.person.id}}, format: :json
end
end
@@ -34,15 +27,35 @@ describe BlocksController, :type => :controller do
end
it "redirects back" do
- delete :destroy, :id => @block.id
+ delete :destroy, params: {id: @block.id}
+ expect(response).to be_redirect
+ end
+
+ it "notifies the user" do
+ delete :destroy, params: {id: @block.id}
+ expect(flash[:notice]).to eq(I18n.t("blocks.destroy.success"))
+ end
+
+ it "responds with 204 with json" do
+ delete :destroy, params: {id: @block.id}, format: :json
+ expect(response.status).to eq(204)
+ end
+
+ it "redirects back on mobile" do
+ delete :destroy, params: {id: @block.id}, format: :mobile
expect(response).to be_redirect
end
it "removes a block" do
expect {
- delete :destroy, :id => @block.id
+ delete :destroy, params: {id: @block.id}, format: :json
}.to change { alice.blocks.count }.by(-1)
end
+
+ it "handles when the block to delete doesn't exist" do
+ delete :destroy, params: {id: -1}
+ expect(flash[:error]).to eq(I18n.t("blocks.destroy.failure"))
+ end
end
describe "#disconnect_if_contact" do
diff --git a/spec/controllers/comments_controller_spec.rb b/spec/controllers/comments_controller_spec.rb
index a155cf531..4b9e22ce5 100644
--- a/spec/controllers/comments_controller_spec.rb
+++ b/spec/controllers/comments_controller_spec.rb
@@ -21,13 +21,13 @@ describe CommentsController, :type => :controller do
end
it 'responds to format json' do
- post :create, comment_hash.merge(:format => 'json')
+ post :create, params: comment_hash, format: :json
expect(response.code).to eq('201')
expect(response.body).to match comment_hash[:text]
end
it 'responds to format mobile' do
- post :create, comment_hash.merge(:format => 'mobile')
+ post :create, params: comment_hash, format: :mobile
expect(response).to be_success
end
end
@@ -39,21 +39,21 @@ describe CommentsController, :type => :controller do
end
it 'comments' do
- post :create, comment_hash
+ post :create, params: comment_hash
expect(response.code).to eq('201')
end
it "doesn't overwrite author_id" do
new_user = FactoryGirl.create(:user)
comment_hash[:author_id] = new_user.person.id.to_s
- post :create, comment_hash
+ post :create, params: comment_hash
expect(Comment.find_by_text(comment_hash[:text]).author_id).to eq(alice.person.id)
end
it "doesn't overwrite id" do
old_comment = alice.comment!(@post, "hello")
comment_hash[:id] = old_comment.id
- post :create, comment_hash
+ post :create, params: comment_hash
expect(old_comment.reload.text).to eq('hello')
end
end
@@ -63,7 +63,7 @@ describe CommentsController, :type => :controller do
@post = eve.post :status_message, :text => 'GIANTS', :to => aspect_to_post
expect(alice).not_to receive(:comment)
- post :create, comment_hash
+ post :create, params: comment_hash
expect(response.code).to eq("404")
expect(response.body).to eq(I18n.t("comments.create.error"))
end
@@ -85,7 +85,7 @@ describe CommentsController, :type => :controller do
comment = bob.comment!(@message, "hey")
expect(bob).to receive(:retract).with(comment)
- delete :destroy, :format => "js", :post_id => 1, :id => comment.id
+ delete :destroy, params: {post_id: 1, id: comment.id}, format: :js
expect(response.status).to eq(204)
end
@@ -93,7 +93,7 @@ describe CommentsController, :type => :controller do
comment = alice.comment!(@message, "hey")
expect(bob).to receive(:retract).with(comment)
- delete :destroy, :format => "js", :post_id => 1, :id => comment.id
+ delete :destroy, params: {post_id: 1, id: comment.id}, format: :js
expect(response.status).to eq(204)
end
end
@@ -103,7 +103,7 @@ describe CommentsController, :type => :controller do
comment = alice.comment!(@message, "hey")
expect(alice).to receive(:retract).with(comment)
- delete :destroy, :format => "js", :post_id => 1, :id => comment.id
+ delete :destroy, params: {post_id: 1, id: comment.id}, format: :js
expect(response.status).to eq(204)
end
@@ -112,13 +112,13 @@ describe CommentsController, :type => :controller do
comment2 = eve.comment!(@message, "hey")
expect(alice).not_to receive(:retract).with(comment1)
- delete :destroy, :format => "js", :post_id => 1, :id => comment2.id
+ delete :destroy, params: {post_id: 1, id: comment2.id}, format: :js
expect(response.status).to eq(403)
end
end
it 'renders nothing and 404 on a nonexistent comment' do
- delete :destroy, :post_id => 1, :id => 343415
+ delete :destroy, params: {post_id: 1, id: 343_415}
expect(response.status).to eq(404)
expect(response.body.strip).to be_empty
end
@@ -131,19 +131,19 @@ describe CommentsController, :type => :controller do
end
it 'works for mobile' do
- get :index, :post_id => @message.id, :format => 'mobile'
+ get :index, params: {post_id: @message.id}, format: :mobile
expect(response).to be_success
end
it 'returns all the comments for a post' do
comments = [alice, bob, eve].map{ |u| u.comment!(@message, "hey") }
- get :index, :post_id => @message.id, :format => :json
+ get :index, params: {post_id: @message.id}, format: :json
expect(JSON.parse(response.body).map {|comment| comment["id"] }).to match_array(comments.map(&:id))
end
it 'returns a 404 on a nonexistent post' do
- get :index, :post_id => 235236, :format => :json
+ get :index, params: {post_id: 235_236}, format: :json
expect(response.status).to eq(404)
end
@@ -151,7 +151,7 @@ describe CommentsController, :type => :controller do
aspect_to_post = eve.aspects.where(:name => "generic").first
message = eve.post(:status_message, :text => "hey", :to => aspect_to_post.id)
bob.comment!(@message, "hey")
- get :index, :post_id => message.id, :format => :json
+ get :index, params: {post_id: message.id}, format: :json
expect(response.status).to eq(404)
end
end
diff --git a/spec/controllers/contacts_controller_spec.rb b/spec/controllers/contacts_controller_spec.rb
index e12a97c3f..c50243264 100644
--- a/spec/controllers/contacts_controller_spec.rb
+++ b/spec/controllers/contacts_controller_spec.rb
@@ -11,7 +11,7 @@ describe ContactsController, :type => :controller do
describe '#index' do
context 'format mobile' do
it "succeeds" do
- get :index, :format => 'mobile'
+ get :index, format: :mobile
expect(response).to be_success
end
end
@@ -40,26 +40,26 @@ describe ContactsController, :type => :controller do
end
it "succeeds" do
- get :index, q: @person1.first_name, format: "json"
+ get :index, params: {q: @person1.first_name}, format: :json
expect(response).to be_success
end
it "responds with json" do
- get :index, q: @person1.first_name, format: "json"
+ get :index, params: {q: @person1.first_name}, format: :json
expect(response.body).to eq([@person1].to_json)
end
it "only returns contacts" do
- get :index, q: @person2.first_name, format: "json"
+ get :index, params: {q: @person2.first_name}, format: :json
expect(response.body).to eq([].to_json)
end
it "only returns mutual contacts when mutual parameter is true" do
- get :index, q: @person1.first_name, mutual: true, format: "json"
+ get :index, params: {q: @person1.first_name, mutual: true}, format: :json
expect(response.body).to eq([].to_json)
- get :index, q: @person2.first_name, mutual: true, format: "json"
+ get :index, params: {q: @person2.first_name, mutual: true}, format: :json
expect(response.body).to eq([].to_json)
- get :index, q: @person3.first_name, mutual: true, format: "json"
+ get :index, params: {q: @person3.first_name, mutual: true}, format: :json
expect(response.body).to eq([@person3].to_json)
end
end
@@ -67,7 +67,7 @@ describe ContactsController, :type => :controller do
context "for pagination on the contacts page" do
context "without parameters" do
it "returns contacts" do
- get :index, format: "json", page: "1"
+ get :index, params: {page: "1"}, format: :json
contact_ids = JSON.parse(response.body).map {|c| c["id"] }
expect(contact_ids.to_set).to eq(bob.contacts.map(&:id).to_set)
end
@@ -76,7 +76,7 @@ describe ContactsController, :type => :controller do
contact = bob.contacts.first
contact.update_attributes(receiving: false)
- get :index, format: "json", page: "1"
+ get :index, params: {params: {page: "1"}}, format: :json
contact_ids = JSON.parse(response.body).map {|c| c["id"] }
expect(contact_ids.to_set).to eq(bob.contacts.receiving.map(&:id).to_set)
expect(contact_ids).not_to include(contact.id)
@@ -90,13 +90,13 @@ describe ContactsController, :type => :controller do
end
it "returns all contacts (sharing and receiving)" do
- get :index, format: "json", page: "1", set: "all"
+ get :index, params: {page: "1", set: "all"}, format: :json
contact_ids = JSON.parse(response.body).map {|c| c["id"] }
expect(contact_ids.to_set).to eq(bob.contacts.map(&:id).to_set)
end
it "sorts contacts by receiving status" do
- get :index, format: "json", page: "1", set: "all"
+ get :index, params: {page: "1", set: "all"}, format: :json
contact_ids = JSON.parse(response.body).map {|c| c["id"] }
expect(contact_ids).to eq(bob.contacts.order("receiving DESC").map(&:id))
expect(contact_ids.last).to eq(bob.contacts.first.id)
@@ -111,16 +111,16 @@ describe ContactsController, :type => :controller do
end
it "returns all contacts" do
- get :index, format: "json", a_id: @aspect.id, page: "1"
+ get :index, params: {a_id: @aspect.id, page: "1"}, format: :json
contact_ids = JSON.parse(response.body).map {|c| c["id"] }
expect(contact_ids.to_set).to eq(bob.contacts.map(&:id).to_set)
end
it "sorts contacts by aspect memberships" do
- get :index, format: "json", a_id: @aspect.id, page: "1"
+ get :index, params: {a_id: @aspect.id, page: "1"}, format: :json
expect(JSON.parse(response.body).first["person"]["id"]).to eq(@person.id)
- get :index, format: "json", a_id: bob.aspects.first.id, page: "1"
+ get :index, params: {a_id: bob.aspects.first.id, page: "1"}, format: :json
expect(JSON.parse(response.body).first["person"]["id"]).not_to eq(@person.id)
end
end
diff --git a/spec/controllers/conversation_visibilities_controller_spec.rb b/spec/controllers/conversation_visibilities_controller_spec.rb
index 5b8893c1e..973873e48 100644
--- a/spec/controllers/conversation_visibilities_controller_spec.rb
+++ b/spec/controllers/conversation_visibilities_controller_spec.rb
@@ -19,7 +19,7 @@ describe ConversationVisibilitiesController, :type => :controller do
describe '#destroy' do
it 'deletes the visibility' do
expect {
- delete :destroy, :conversation_id => @conversation.id
+ delete :destroy, params: {conversation_id: @conversation.id}
}.to change(ConversationVisibility, :count).by(-1)
end
@@ -28,20 +28,20 @@ describe ConversationVisibilitiesController, :type => :controller do
sign_in user2, scope: :user
expect {
- delete :destroy, :conversation_id => @conversation.id
+ delete :destroy, params: {conversation_id: @conversation.id}
}.not_to change(ConversationVisibility, :count)
end
it 'returns "hidden"' do
- get :destroy, :conversation_id => @conversation.id
+ get :destroy, params: {conversation_id: @conversation.id}
expect(flash.notice).to include("hidden")
end
it 'returns "deleted" when last participant' do
- get :destroy, :conversation_id => @conversation.id
+ get :destroy, params: {conversation_id: @conversation.id}
sign_out :user
sign_in bob, scope: :user
- get :destroy, :conversation_id => @conversation.id
+ get :destroy, params: {conversation_id: @conversation.id}
expect(flash.notice).to include("deleted")
end
end
diff --git a/spec/controllers/conversations_controller_spec.rb b/spec/controllers/conversations_controller_spec.rb
index 9bf0c6cc1..dd6b64677 100644
--- a/spec/controllers/conversations_controller_spec.rb
+++ b/spec/controllers/conversations_controller_spec.rb
@@ -17,17 +17,17 @@ describe ConversationsController, :type => :controller do
describe "#new modal" do
context "desktop" do
it "succeeds" do
- get :new, modal: true
+ get :new, params: {modal: true}
expect(response).to be_success
end
it "assigns a contact if passed a contact id" do
- get :new, contact_id: alice.contacts.first.id, modal: true
+ get :new, params: {contact_id: alice.contacts.first.id, modal: true}
expect(controller.gon.conversation_prefill).to eq([alice.contacts.first.person.as_json])
end
it "assigns a set of contacts if passed an aspect id" do
- get :new, aspect_id: alice.aspects.first.id, modal: true
+ get :new, params: {aspect_id: alice.aspects.first.id, modal: true}
expect(controller.gon.conversation_prefill).to eq(alice.aspects.first.contacts.map {|c| c.person.as_json })
end
end
@@ -40,7 +40,7 @@ describe ConversationsController, :type => :controller do
it "assigns a json list of contacts that are sharing with the person" do
sharing_user = FactoryGirl.create(:user_with_aspect)
sharing_user.share_with(alice.person, sharing_user.aspects.first)
- get :new, modal: true
+ get :new, params: {modal: true}
expect(assigns(:contacts_json))
.to include(alice.contacts.where(sharing: true, receiving: true).first.person.name)
alice.contacts << Contact.new(person_id: eve.person.id, user_id: alice.id, sharing: false, receiving: true)
@@ -51,7 +51,7 @@ describe ConversationsController, :type => :controller do
it "does not allow XSS via the name parameter" do
["</script><script>alert(1);</script>",
'"}]});alert(1);(function f() {var foo = [{b:"'].each do |xss|
- get :new, modal: true, name: xss
+ get :new, params: {modal: true, name: xss}
expect(response.body).not_to include xss
end
end
@@ -60,7 +60,7 @@ describe ConversationsController, :type => :controller do
xss = "<script>alert(0);</script>"
contact = alice.contacts.first
contact.person.profile.update_attribute(:first_name, xss)
- get :new, modal: true
+ get :new, params: {modal: true}
json = JSON.parse(assigns(:contacts_json)).first
expect(json["value"].to_s).to eq(contact.id.to_s)
expect(json["name"]).to_not include(xss)
@@ -101,7 +101,7 @@ describe ConversationsController, :type => :controller do
end
it "retrieves a conversation" do
- get :index, conversation_id: @conversations.first.id
+ get :index, params: {conversation_id: @conversations.first.id}
expect(response).to be_success
expect(assigns[:visibilities]).to match_array(@visibilities)
expect(assigns[:conversation]).to eq(@conversations.first)
@@ -109,7 +109,7 @@ describe ConversationsController, :type => :controller do
it "does not let you access conversations where you are not a recipient" do
sign_in eve, scope: :user
- get :index, conversation_id: @conversations.first.id
+ get :index, params: {conversation_id: @conversations.first.id}
expect(assigns[:conversation]).to be_nil
end
@@ -125,31 +125,30 @@ describe ConversationsController, :type => :controller do
describe "#create" do
context "desktop" do
context "with a valid conversation" do
- before do
- @hash = {
- format: :js,
+ let(:params) {
+ {
conversation: {subject: "secret stuff", text: "text debug"},
person_ids: alice.contacts.first.person.id.to_s
}
- end
+ }
it "creates a conversation" do
- expect { post :create, @hash }.to change(Conversation, :count).by(1)
+ expect { post :create, params: params, format: :js }.to change(Conversation, :count).by(1)
end
it "creates a message" do
- expect { post :create, @hash }.to change(Message, :count).by(1)
+ expect { post :create, params: params, format: :js }.to change(Message, :count).by(1)
end
it "responds with the conversation id as JSON" do
- post :create, @hash
+ post :create, params: params, format: :js
expect(response).to be_success
expect(JSON.parse(response.body)["id"]).to eq(Conversation.first.id)
end
it "sets the author to the current_user" do
- @hash[:author] = FactoryGirl.create(:user)
- post :create, @hash
+ params[:author] = FactoryGirl.create(:user)
+ post :create, params: params, format: :js
expect(Message.first.author).to eq(alice.person)
expect(Conversation.first.author).to eq(alice.person)
end
@@ -159,130 +158,128 @@ describe ConversationsController, :type => :controller do
subject: "not spam", messages_attributes: [{author: alice.person, text: "cool stuff"}])
expect(Diaspora::Federation::Dispatcher).to receive(:defer_dispatch)
- post :create, @hash
+ post :create, params: params, format: :js
end
end
context "with empty subject" do
- before do
- @hash = {
- format: :js,
+ let(:params) {
+ {
conversation: {subject: " ", text: "text debug"},
person_ids: alice.contacts.first.person.id.to_s
}
- end
+ }
it "creates a conversation" do
- expect { post :create, @hash }.to change(Conversation, :count).by(1)
+ expect { post :create, params: params, format: :js }.to change(Conversation, :count).by(1)
end
it "creates a message" do
- expect { post :create, @hash }.to change(Message, :count).by(1)
+ expect { post :create, params: params, format: :js }.to change(Message, :count).by(1)
end
it "responds with the conversation id as JSON" do
- post :create, @hash
+ post :create, params: params, format: :js
expect(response).to be_success
expect(JSON.parse(response.body)["id"]).to eq(Conversation.first.id)
end
end
context "with empty text" do
- before do
- @hash = {
- format: :js,
+ let(:params) {
+ {
conversation: {subject: "secret stuff", text: " "},
person_ids: alice.contacts.first.person.id.to_s
}
- end
+ }
it "does not create a conversation" do
- expect { post :create, @hash }.not_to change(Conversation, :count)
+ expect { post :create, params: params, format: :js }.not_to change(Conversation, :count)
end
it "does not create a message" do
- expect { post :create, @hash }.not_to change(Message, :count)
+ expect { post :create, params: params, format: :js }.not_to change(Message, :count)
end
it "responds with an error message" do
- post :create, @hash
+ post :create, params: params, format: :js
expect(response).not_to be_success
expect(response.body).to eq(I18n.t("conversations.create.fail"))
end
end
context "with empty contact" do
- before do
- @hash = {
- format: :js,
+ let(:params) {
+ {
conversation: {subject: "secret stuff", text: "text debug"},
person_ids: " "
}
- end
+ }
it "does not create a conversation" do
- expect { post :create, @hash }.not_to change(Conversation, :count)
+ expect { post :create, params: params, format: :js }.not_to change(Conversation, :count)
end
it "does not create a message" do
- expect { post :create, @hash }.not_to change(Message, :count)
+ expect { post :create, params: params, format: :js }.not_to change(Message, :count)
end
it "responds with an error message" do
- post :create, @hash
+ post :create, params: params, format: :js
expect(response).not_to be_success
expect(response.body).to eq(I18n.t("javascripts.conversation.create.no_recipient"))
end
end
context "with nil contact" do
- before do
- @hash = {
- format: :js,
+ let(:params) {
+ {
conversation: {subject: "secret stuff", text: "text debug"},
person_ids: nil
}
- end
+ }
it "does not create a conversation" do
- expect { post :create, @hash }.not_to change(Conversation, :count)
+ expect { post :create, params: params, format: :js }.not_to change(Conversation, :count)
end
it "does not create a message" do
- expect { post :create, @hash }.not_to change(Message, :count)
+ expect { post :create, params: params, format: :js }.not_to change(Message, :count)
end
it "responds with an error message" do
- post :create, @hash
+ post :create, params: params, format: :js
expect(response).not_to be_success
expect(response.body).to eq(I18n.t("javascripts.conversation.create.no_recipient"))
end
end
context "with non-mutual contact" do
- before do
- @person1 = FactoryGirl.create(:person)
- @person2 = FactoryGirl.create(:person)
- alice.contacts.create!(receiving: false, sharing: true, person: @person2)
- @person3 = FactoryGirl.create(:person)
- alice.contacts.create!(receiving: true, sharing: false, person: @person3)
- @hash = {
- format: :js,
+ let(:person1) { FactoryGirl.create(:person) }
+ let(:person2) { FactoryGirl.create(:person) }
+ let(:person3) { FactoryGirl.create(:person) }
+ let(:params) {
+ {
conversation: {subject: "secret stuff", text: "text debug"},
- person_ids: [@person1.id, @person2.id, @person3.id].join(",")
+ person_ids: [person1.id, person2.id, person3.id].join(",")
}
+ }
+
+ before do
+ alice.contacts.create!(receiving: false, sharing: true, person: person2)
+ alice.contacts.create!(receiving: true, sharing: false, person: person3)
end
it "does not create a conversation" do
- expect { post :create, @hash }.not_to change(Conversation, :count)
+ expect { post :create, params: params, format: :js }.not_to change(Conversation, :count)
end
it "does not create a message" do
- expect { post :create, @hash }.not_to change(Message, :count)
+ expect { post :create, params: params, format: :js }.not_to change(Message, :count)
end
it "responds with an error message" do
- post :create, @hash
+ post :create, params: params, format: :js
expect(response).not_to be_success
expect(response.body).to eq(I18n.t("javascripts.conversation.create.no_recipient"))
end
@@ -295,31 +292,30 @@ describe ConversationsController, :type => :controller do
end
context "with a valid conversation" do
- before do
- @hash = {
- format: :js,
+ let(:params) {
+ {
conversation: {subject: "secret stuff", text: "text debug"},
contact_ids: alice.contacts.first.id.to_s
}
- end
+ }
it "creates a conversation" do
- expect { post :create, @hash }.to change(Conversation, :count).by(1)
+ expect { post :create, params: params, format: :js }.to change(Conversation, :count).by(1)
end
it "creates a message" do
- expect { post :create, @hash }.to change(Message, :count).by(1)
+ expect { post :create, params: params, format: :js }.to change(Message, :count).by(1)
end
it "responds with the conversation id as JSON" do
- post :create, @hash
+ post :create, params: params, format: :js
expect(response).to be_success
expect(JSON.parse(response.body)["id"]).to eq(Conversation.first.id)
end
it "sets the author to the current_user" do
- @hash[:author] = FactoryGirl.create(:user)
- post :create, @hash
+ params[:author] = FactoryGirl.create(:user)
+ post :create, params: params, format: :js
expect(Message.first.author).to eq(alice.person)
expect(Conversation.first.author).to eq(alice.person)
end
@@ -329,127 +325,122 @@ describe ConversationsController, :type => :controller do
subject: "not spam", messages_attributes: [{author: alice.person, text: "cool stuff"}])
expect(Diaspora::Federation::Dispatcher).to receive(:defer_dispatch)
- post :create, @hash
+ post :create, params: params, format: :js
end
end
context "with empty subject" do
- before do
- @hash = {
- format: :js,
+ let(:params) {
+ {
conversation: {subject: " ", text: "text debug"},
contact_ids: alice.contacts.first.id.to_s
}
- end
+ }
it "creates a conversation" do
- expect { post :create, @hash }.to change(Conversation, :count).by(1)
+ expect { post :create, params: params, format: :js }.to change(Conversation, :count).by(1)
end
it "creates a message" do
- expect { post :create, @hash }.to change(Message, :count).by(1)
+ expect { post :create, params: params, format: :js }.to change(Message, :count).by(1)
end
it "responds with the conversation id as JSON" do
- post :create, @hash
+ post :create, params: params, format: :js
expect(response).to be_success
expect(JSON.parse(response.body)["id"]).to eq(Conversation.first.id)
end
end
context "with empty text" do
- before do
- @hash = {
- format: :js,
+ let(:params) {
+ {
conversation: {subject: "secret stuff", text: " "},
contact_ids: alice.contacts.first.id.to_s
}
- end
+ }
it "does not create a conversation" do
- expect { post :create, @hash }.not_to change(Conversation, :count)
+ expect { post :create, params: params, format: :js }.not_to change(Conversation, :count)
end
it "does not create a message" do
- expect { post :create, @hash }.not_to change(Message, :count)
+ expect { post :create, params: params, format: :js }.not_to change(Message, :count)
end
it "responds with an error message" do
- post :create, @hash
+ post :create, params: params, format: :js
expect(response).not_to be_success
expect(response.body).to eq(I18n.t("conversations.create.fail"))
end
end
context "with empty contact" do
- before do
- @hash = {
- format: :js,
+ let(:params) {
+ {
conversation: {subject: "secret stuff", text: "text debug"},
contact_ids: " "
}
- end
+ }
it "does not create a conversation" do
- expect { post :create, @hash }.not_to change(Conversation, :count)
+ expect { post :create, params: params, format: :js }.not_to change(Conversation, :count)
end
it "does not create a message" do
- expect { post :create, @hash }.not_to change(Message, :count)
+ expect { post :create, params: params, format: :js }.not_to change(Message, :count)
end
it "responds with an error message" do
- post :create, @hash
+ post :create, params: params, format: :js
expect(response).not_to be_success
expect(response.body).to eq(I18n.t("javascripts.conversation.create.no_recipient"))
end
end
context "with nil contact" do
- before do
- @hash = {
- format: :js,
+ let(:params) {
+ {
conversation: {subject: "secret stuff", text: "text debug"},
contact_ids: nil
}
- end
+ }
it "does not create a conversation" do
- expect { post :create, @hash }.not_to change(Conversation, :count)
+ expect { post :create, params: params, format: :js }.not_to change(Conversation, :count)
end
it "does not create a message" do
- expect { post :create, @hash }.not_to change(Message, :count)
+ expect { post :create, params: params, format: :js }.not_to change(Message, :count)
end
it "responds with an error message" do
- post :create, @hash
+ post :create, params: params, format: :js
expect(response).not_to be_success
expect(response.body).to eq(I18n.t("javascripts.conversation.create.no_recipient"))
end
end
context "with non-mutual contact" do
- before do
- @contact1 = alice.contacts.create(receiving: false, sharing: true, person: FactoryGirl.create(:person))
- @contact2 = alice.contacts.create(receiving: true, sharing: false, person: FactoryGirl.create(:person))
- @hash = {
- format: :js,
+ let(:contact1) { alice.contacts.create(receiving: false, sharing: true, person: FactoryGirl.create(:person)) }
+ let(:contact2) { alice.contacts.create(receiving: true, sharing: false, person: FactoryGirl.create(:person)) }
+ let(:params) {
+ {
conversation: {subject: "secret stuff", text: "text debug"},
- person_ids: [@contact1.id, @contact2.id].join(",")
+ contact_ids: [contact1.id, contact2.id].join(",")
}
- end
+ }
it "does not create a conversation" do
- expect { post :create, @hash }.not_to change(Conversation, :count)
+ expect { post :create, params: params, format: :js }.not_to change(Conversation, :count)
end
it "does not create a message" do
- expect { post :create, @hash }.not_to change(Message, :count)
+ expect { post :create, params: params, format: :js }.not_to change(Message, :count)
end
it "responds with an error message" do
- post :create, @hash
+ post :create, params: params, format: :js
expect(response).not_to be_success
expect(response.body).to eq(I18n.t("javascripts.conversation.create.no_recipient"))
end
@@ -458,47 +449,45 @@ describe ConversationsController, :type => :controller do
end
describe "#show" do
- before do
- hash = {
+ let(:conversation) {
+ Conversation.create(
author: alice.person,
participant_ids: [alice.contacts.first.person.id, alice.person.id],
subject: "not spam",
messages_attributes: [{author: alice.person, text: "cool stuff"}]
- }
- @conversation = Conversation.create(hash)
- end
+ )
+ }
it "succeeds with json" do
- get :show, :id => @conversation.id, :format => :json
+ get :show, params: {id: conversation.id}, format: :json
expect(response).to be_success
- expect(assigns[:conversation]).to eq(@conversation)
- expect(response.body).to include @conversation.guid
+ expect(assigns[:conversation]).to eq(conversation)
+ expect(response.body).to include conversation.guid
end
it "redirects to index" do
- get :show, :id => @conversation.id
- expect(response).to redirect_to(conversations_path(:conversation_id => @conversation.id))
+ get :show, params: {id: conversation.id}
+ expect(response).to redirect_to(conversations_path(conversation_id: conversation.id))
end
end
describe "#raw" do
- before do
- hash = {
+ let(:conversation) {
+ Conversation.create(
author: alice.person,
participant_ids: [alice.contacts.first.person.id, alice.person.id],
subject: "not spam",
messages_attributes: [{author: alice.person, text: "cool stuff"}]
- }
- @conversation = Conversation.create(hash)
- end
+ )
+ }
it "returns html of conversation" do
- get :raw, conversation_id: @conversation.id
- expect(response).to render_template(partial: "show", locals: {conversation: @conversation})
+ get :raw, params: {conversation_id: conversation.id}
+ expect(response).to render_template(partial: "show", locals: {conversation: conversation})
end
it "returns 404 when requesting non-existant conversation" do
- get :raw, conversation_id: -1
+ get :raw, params: {conversation_id: -1}
expect(response).to have_http_status(404)
end
end
diff --git a/spec/controllers/help_controller_spec.rb b/spec/controllers/help_controller_spec.rb
index b40bcbbaa..a9c3b0a1a 100644
--- a/spec/controllers/help_controller_spec.rb
+++ b/spec/controllers/help_controller_spec.rb
@@ -8,7 +8,7 @@ describe HelpController, type: :controller do
it "fails on mobile" do
expect {
get :faq, format: :mobile
- }.to raise_error ActionView::MissingTemplate
+ }.to raise_error ActionController::UnknownFormat
end
end
end
diff --git a/spec/controllers/home_controller_spec.rb b/spec/controllers/home_controller_spec.rb
index 80b9bc023..2e5a9b3a8 100644
--- a/spec/controllers/home_controller_spec.rb
+++ b/spec/controllers/home_controller_spec.rb
@@ -40,7 +40,7 @@ describe HomeController, type: :controller do
it "redirects to the stream if the user is signed in" do
sign_in alice
- get :show, home: true
+ get :show
expect(response).to redirect_to(stream_path)
end
end
diff --git a/spec/controllers/invitation_codes_controller_spec.rb b/spec/controllers/invitation_codes_controller_spec.rb
index 90864fefc..afc317f99 100644
--- a/spec/controllers/invitation_codes_controller_spec.rb
+++ b/spec/controllers/invitation_codes_controller_spec.rb
@@ -1,7 +1,7 @@
describe InvitationCodesController, type: :controller do
describe "#show" do
it "redirects to the root page if the invitation code is invalid" do
- get :show, id: "InvalidInvitationCode"
+ get :show, params: {id: "InvalidInvitationCode"}
expect(response).to redirect_to root_path
expect(flash[:notice]).to eq(I18n.t("invitation_codes.not_valid"))
end
@@ -10,13 +10,13 @@ describe InvitationCodesController, type: :controller do
let(:invitation_token) { alice.invitation_code.token }
it "redirects logged out users to the sign in page" do
- post :show, id: invitation_token
+ post :show, params: {id: invitation_token}
expect(response).to redirect_to new_user_registration_path(invite: {token: invitation_token})
end
it "redirects logged in users the the inviters page" do
sign_in bob
- post :show, id: invitation_token
+ post :show, params: {id: invitation_token}
expect(response).to redirect_to person_path(alice.person)
expect(flash[:notice]).to eq(I18n.t("invitation_codes.already_logged_in", inviter: alice.name))
end
diff --git a/spec/controllers/invitations_controller_spec.rb b/spec/controllers/invitations_controller_spec.rb
index 7fb2b03fb..9ca17c125 100644
--- a/spec/controllers/invitations_controller_spec.rb
+++ b/spec/controllers/invitations_controller_spec.rb
@@ -17,16 +17,16 @@ describe InvitationsController, type: :controller do
it "does not create an EmailInviter" do
expect(Workers::Mail::InviteEmail).not_to receive(:perform_async)
- post :create, invite_params
+ post :create, params: invite_params
end
it "returns to the previous page" do
- post :create, invite_params
+ post :create, params: invite_params
expect(response).to redirect_to referer
end
it "flashes an error" do
- post :create, invite_params
+ post :create, params: invite_params
expect(flash[:error]).to eq(I18n.t("invitations.create.empty"))
end
end
@@ -39,16 +39,16 @@ describe InvitationsController, type: :controller do
expect(Workers::Mail::InviteEmail).to receive(:perform_async).with(
emails, alice.id, invite_params[:email_inviter]
)
- post :create, invite_params
+ post :create, params: invite_params
end
it "returns to the previous page on success" do
- post :create, invite_params
+ post :create, params: invite_params
expect(response).to redirect_to referer
end
it "flashes a notice" do
- post :create, invite_params
+ post :create, params: invite_params
expected = I18n.t("invitations.create.sent", emails: emails)
expect(flash[:notice]).to eq(expected)
end
@@ -60,16 +60,16 @@ describe InvitationsController, type: :controller do
it "does not create an InviteEmail worker" do
expect(Workers::Mail::InviteEmail).not_to receive(:perform_async)
- post :create, invite_params
+ post :create, params: invite_params
end
it "returns to the previous page" do
- post :create, invite_params
+ post :create, params: invite_params
expect(response).to redirect_to referer
end
it "flashes an error" do
- post :create, invite_params
+ post :create, params: invite_params
expected = I18n.t("invitations.create.rejected", emails: emails)
expect(flash[:error]).to eq(expected)
@@ -85,16 +85,16 @@ describe InvitationsController, type: :controller do
expect(Workers::Mail::InviteEmail).to receive(:perform_async).with(
valid_emails, alice.id, invite_params[:email_inviter]
)
- post :create, invite_params
+ post :create, params: invite_params
end
it "returns to the previous page" do
- post :create, invite_params
+ post :create, params: invite_params
expect(response).to redirect_to referer
end
it "flashes a notice" do
- post :create, invite_params
+ post :create, params: invite_params
expected = I18n.t("invitations.create.sent", emails: valid_emails.split(",").join(", ")) + ". " +
I18n.t("invitations.create.rejected", emails: invalid_emails)
expect(flash[:error]).to eq(expected)
@@ -109,7 +109,7 @@ describe InvitationsController, type: :controller do
it "displays an error if invitations are closed" do
AppConfig.settings.invitations.open = false
- post :create, invite_params
+ post :create, params: invite_params
expect(flash[:error]).to eq(I18n.t("invitations.create.closed"))
end
@@ -117,7 +117,7 @@ describe InvitationsController, type: :controller do
it "displays an error when no invitations are left" do
alice.invitation_code.update_attributes(count: 0)
- post :create, invite_params
+ post :create, params: invite_params
expect(flash[:error]).to eq(I18n.t("invitations.create.no_more"))
end
@@ -127,7 +127,7 @@ describe InvitationsController, type: :controller do
AppConfig.settings.invitations.open = false
alice.invitation_code.update_attributes(count: 0)
- post :create, invite_params
+ post :create, params: invite_params
expect(flash[:error]).to be_nil
end
diff --git a/spec/controllers/jasmine_fixtures/aspects_spec.rb b/spec/controllers/jasmine_fixtures/aspects_spec.rb
index e2adf493d..b82fbc2de 100644
--- a/spec/controllers/jasmine_fixtures/aspects_spec.rb
+++ b/spec/controllers/jasmine_fixtures/aspects_spec.rb
@@ -22,14 +22,14 @@ describe StreamsController, :type => :controller do
end
it "generates a jasmine fixture with a prefill", :fixture => true do
- get :aspects, :prefill => "reshare things"
+ get :aspects, params: {prefill: "reshare things"}
save_fixture(html_for("body"), "aspects_index_prefill")
end
it 'generates a jasmine fixture with services', :fixture => true do
alice.services << Services::Facebook.create(:user_id => alice.id)
alice.services << Services::Twitter.create(:user_id => alice.id)
- get :aspects, :prefill => "reshare things"
+ get :aspects, params: {prefill: "reshare things"}
save_fixture(html_for("body"), "aspects_index_services")
end
@@ -44,7 +44,7 @@ describe StreamsController, :type => :controller do
it 'generates a jasmine fixture with only posts', :fixture => true do
2.times { bob.post(:status_message, :text => "Is anyone out there?", :to => @bob.aspects.where(:name => "generic").first.id) }
- get :aspects, :only_posts => true
+ get :aspects, params: {only_posts: true}
save_fixture(response.body, "aspects_index_only_posts")
end
diff --git a/spec/controllers/jasmine_fixtures/contacts_spec.rb b/spec/controllers/jasmine_fixtures/contacts_spec.rb
index 127f9be2a..06262aed2 100644
--- a/spec/controllers/jasmine_fixtures/contacts_spec.rb
+++ b/spec/controllers/jasmine_fixtures/contacts_spec.rb
@@ -13,12 +13,12 @@ describe ContactsController, :type => :controller do
end
it "generates the aspects_manage fixture", :fixture => true do
- get :index, :a_id => @aspect.id
+ get :index, params: {a_id: @aspect.id}
save_fixture(html_for("body"), "aspects_manage")
end
it "generates the aspects_manage_contacts_json fixture", fixture: true do
- get :index, format: :json, a_id: @aspect.id, page: "1"
+ get :index, params: {a_id: @aspect.id, page: "1"}, format: :json
save_fixture(response.body, "aspects_manage_contacts_json")
end
diff --git a/spec/controllers/jasmine_fixtures/conversations_spec.rb b/spec/controllers/jasmine_fixtures/conversations_spec.rb
index cfba3708b..a35993c0b 100644
--- a/spec/controllers/jasmine_fixtures/conversations_spec.rb
+++ b/spec/controllers/jasmine_fixtures/conversations_spec.rb
@@ -22,10 +22,10 @@ describe ConversationsController, :type => :controller do
end
it "generates a jasmine fixture", :fixture => true do
- get :index, :conversation_id => @conv1.id
+ get :index, params: {conversation_id: @conv1.id}
save_fixture(html_for("body"), "conversations_unread")
- get :index, :conversation_id => @conv1.id
+ get :index, params: {conversation_id: @conv1.id}
save_fixture(html_for("body"), "conversations_read")
end
end
diff --git a/spec/controllers/jasmine_fixtures/people_spec.rb b/spec/controllers/jasmine_fixtures/people_spec.rb
index 432ff5d5c..77ec78424 100644
--- a/spec/controllers/jasmine_fixtures/people_spec.rb
+++ b/spec/controllers/jasmine_fixtures/people_spec.rb
@@ -14,7 +14,7 @@ describe PeopleController, :type => :controller do
end
it "generates a jasmine fixture trying an external search", :fixture => true do
- get :index, :q => "sample@diaspor.us"
+ get :index, params: {q: "sample@diaspor.us"}
save_fixture(html_for("body"), "pending_external_people_search")
end
end
diff --git a/spec/controllers/jasmine_fixtures/photos_spec.rb b/spec/controllers/jasmine_fixtures/photos_spec.rb
index fd62b21a6..3dabe5e53 100644
--- a/spec/controllers/jasmine_fixtures/photos_spec.rb
+++ b/spec/controllers/jasmine_fixtures/photos_spec.rb
@@ -11,7 +11,7 @@ describe PhotosController, :type => :controller do
describe '#index' do
it "generates a jasmine fixture", :fixture => true do
request.env['HTTP_ACCEPT'] = 'application/json'
- get :index, :person_id => alice.person.guid.to_s
+ get :index, params: {person_id: alice.person.guid.to_s}
save_fixture(response.body, "photos_json")
end
end
diff --git a/spec/controllers/jasmine_fixtures/posts_spec.rb b/spec/controllers/jasmine_fixtures/posts_spec.rb
new file mode 100644
index 000000000..aed5d118a
--- /dev/null
+++ b/spec/controllers/jasmine_fixtures/posts_spec.rb
@@ -0,0 +1,11 @@
+require "spec_helper"
+
+describe PostsController, type: :controller do
+ describe "#show" do
+ it "generates the post_json fixture", fixture: true do
+ post = alice.post(:status_message, text: "hello world", public: true)
+ get :show, params: {id: post.id}, format: :json
+ save_fixture(response.body, "post_json")
+ end
+ end
+end
diff --git a/spec/controllers/jasmine_fixtures/status_messages_spec.rb b/spec/controllers/jasmine_fixtures/status_messages_spec.rb
index 905a5137c..6964f1d5b 100644
--- a/spec/controllers/jasmine_fixtures/status_messages_spec.rb
+++ b/spec/controllers/jasmine_fixtures/status_messages_spec.rb
@@ -25,7 +25,7 @@ describe StatusMessagesController, :type => :controller do
aspect = alice.aspects.create(:name => 'people')
contact.aspects << aspect
contact.save
- get :new, :person_id => bob.person.id
+ get :new, params: {person_id: bob.person.id}
save_fixture(html_for("body"), "status_message_new")
end
end
diff --git a/spec/controllers/jasmine_fixtures/streams_spec.rb b/spec/controllers/jasmine_fixtures/streams_spec.rb
index 5447a5420..0e815439a 100644
--- a/spec/controllers/jasmine_fixtures/streams_spec.rb
+++ b/spec/controllers/jasmine_fixtures/streams_spec.rb
@@ -5,6 +5,7 @@
describe StreamsController, :type => :controller do
describe '#multi' do
before do
+ allow(Workers::SendPublic).to receive(:perform_async)
sign_in alice, scope: :user
end
diff --git a/spec/controllers/likes_controller_spec.rb b/spec/controllers/likes_controller_spec.rb
index b9935a70f..b29fdeae9 100644
--- a/spec/controllers/likes_controller_spec.rb
+++ b/spec/controllers/likes_controller_spec.rb
@@ -18,7 +18,7 @@ describe LikesController, type: :controller do
context "on my own post" do
it "succeeds" do
@target = alice.post :status_message, text: "AWESOME", to: @alices_aspect.id
- post :create, like_hash.merge(format: :json)
+ post :create, params: like_hash, format: :json
expect(response.code).to eq("201")
end
end
@@ -29,13 +29,13 @@ describe LikesController, type: :controller do
end
it "likes" do
- post :create, like_hash
+ post :create, params: like_hash
expect(response.code).to eq("201")
end
it "doesn't post multiple times" do
alice.like!(@target)
- post :create, like_hash
+ post :create, params: like_hash
expect(response.code).to eq("422")
end
end
@@ -47,7 +47,7 @@ describe LikesController, type: :controller do
it "doesn't post" do
expect(alice).not_to receive(:like!)
- post :create, like_hash
+ post :create, params: like_hash
expect(response.code).to eq("422")
end
end
@@ -58,8 +58,7 @@ describe LikesController, type: :controller do
end
it "should be catched when it means that the target is not found" do
- params = like_hash.merge(format: :json, post_id: -1)
- post :create, params
+ post :create, params: {post_id: -1}, format: :json
expect(response.code).to eq("422")
end
@@ -67,7 +66,7 @@ describe LikesController, type: :controller do
@target = alice.post :status_message, text: "AWESOME", to: @alices_aspect.id
allow(alice).to receive(:like!).and_raise("something")
allow(@controller).to receive(:current_user).and_return(alice)
- expect { post :create, like_hash.merge(format: :json) }.to raise_error("something")
+ expect { post :create, params: like_hash, format: :json }.to raise_error("something")
end
end
end
@@ -80,18 +79,18 @@ describe LikesController, type: :controller do
it "returns a 404 for a post not visible to the user" do
sign_in eve
expect {
- get :index, post_id: @message.id
+ get :index, params: {post_id: @message.id}
}.to raise_error(ActiveRecord::RecordNotFound)
end
it "returns an array of likes for a post" do
bob.like!(@message)
- get :index, post_id: @message.id
+ get :index, params: {post_id: @message.id}
expect(JSON.parse(response.body).map {|h| h["id"] }).to match_array(@message.likes.map(&:id))
end
it "returns an empty array for a post with no likes" do
- get :index, post_id: @message.id
+ get :index, params: {post_id: @message.id}
expect(JSON.parse(response.body).map(&:id)).to eq([])
end
end
@@ -106,7 +105,7 @@ describe LikesController, type: :controller do
current_user = controller.send(:current_user)
expect(current_user).to receive(:retract).with(@like)
- delete :destroy, format: :json, post_id: @message.id, id: @like.id
+ delete :destroy, params: {post_id: @message.id, id: @like.id}, format: :json
expect(response.status).to eq(204)
end
@@ -114,7 +113,7 @@ describe LikesController, type: :controller do
like2 = eve.like!(@message)
like_count = Like.count
- delete :destroy, format: :json, post_id: @message.id, id: like2.id
+ delete :destroy, params: {post_id: @message.id, id: like2.id}, format: :json
expect(response.status).to eq(404)
expect(response.body).to eq(I18n.t("likes.destroy.error"))
expect(Like.count).to eq(like_count)
diff --git a/spec/controllers/messages_controller_spec.rb b/spec/controllers/messages_controller_spec.rb
index 7e753c4f0..596ca084e 100644
--- a/spec/controllers/messages_controller_spec.rb
+++ b/spec/controllers/messages_controller_spec.rb
@@ -32,7 +32,7 @@ describe MessagesController, :type => :controller do
it 'redirects to conversation' do
expect {
- post :create, @message_params
+ post :create, params: @message_params
}.to change(Message, :count).by(1)
expect(response.status).to eq(302)
expect(response).to redirect_to(conversations_path(:conversation_id => @conversation))
@@ -40,7 +40,7 @@ describe MessagesController, :type => :controller do
it "dispatches the message" do
expect(Diaspora::Federation::Dispatcher).to receive(:defer_dispatch).with(alice, instance_of(Message))
- post :create, @message_params
+ post :create, params: @message_params
end
end
@@ -54,7 +54,7 @@ describe MessagesController, :type => :controller do
it 'does not create the message' do
expect {
- post :create, @message_params
+ post :create, params: @message_params
}.not_to change(Message, :count)
expect(flash[:error]).to be_present
end
@@ -72,7 +72,7 @@ describe MessagesController, :type => :controller do
end
it 'comments' do
- post :create, @message_params
+ post :create, params: @message_params
expect(response.status).to eq(302)
expect(response).to redirect_to(conversations_path(:conversation_id => @conversation))
end
@@ -81,7 +81,7 @@ describe MessagesController, :type => :controller do
new_user = FactoryGirl.create(:user)
@message_params[:author_id] = new_user.person.id.to_s
- post :create, @message_params
+ post :create, params: @message_params
created_message = Message.find_by_text(@message_params[:message][:text])
expect(created_message.author).to eq(alice.person)
end
@@ -94,26 +94,13 @@ describe MessagesController, :type => :controller do
)
@message_params[:id] = old_message.id
- post :create, @message_params
+ post :create, params: @message_params
expect(old_message.reload.text).to eq('hello')
end
it "dispatches the message" do
expect(Diaspora::Federation::Dispatcher).to receive(:defer_dispatch).with(alice, instance_of(Message))
- post :create, @message_params
- end
-
- it "dispatches the message twice if the conversation author is local and it has remote users" do
- @conversation_params[:participant_ids] = [bob.person.id, alice.person.id, remote_raphael.id]
- conversation = Conversation.create!(@conversation_params)
- @message_params[:conversation_id] = conversation.id
-
- expect(Diaspora::Federation::Dispatcher).to receive(:defer_dispatch).with(alice, instance_of(Message))
- expect(Diaspora::Federation::Dispatcher).to receive(:defer_dispatch).with(
- bob, instance_of(Message), subscriber_ids: [remote_raphael.id]
- )
-
- post :create, @message_params
+ post :create, params: @message_params
end
end
@@ -131,7 +118,7 @@ describe MessagesController, :type => :controller do
it 'does not create the message' do
expect {
- post :create, @message_params
+ post :create, params: @message_params
}.not_to change(Message, :count)
expect(flash[:error]).to be_present
end
diff --git a/spec/controllers/node_info_controller_spec.rb b/spec/controllers/node_info_controller_spec.rb
index 6a3a94250..3108ca4cf 100644
--- a/spec/controllers/node_info_controller_spec.rb
+++ b/spec/controllers/node_info_controller_spec.rb
@@ -25,7 +25,7 @@ describe NodeInfoController do
describe "#document" do
context "invalid version" do
it "responds with not found" do
- get :document, version: "0.0", format: :json
+ get :document, params: {version: "0.0"}, format: :json
expect(response.code).to eq "404"
end
@@ -34,7 +34,7 @@ describe NodeInfoController do
%w(1.0 2.0).each do |version|
context "version #{version}" do
it "responds to JSON" do
- get :document, version: version, format: :json
+ get :document, params: {version: version}, format: :json
expect(response).to be_success
end
@@ -43,11 +43,11 @@ describe NodeInfoController do
expect(NodeInfoPresenter).to receive(:new).with(version)
.and_return(double(as_json: {}, content_type: "application/json"))
- get :document, version: version, format: :json
+ get :document, params: {version: version}, format: :json
end
it "notes the schema in the content type" do
- get :document, version: version, format: :json
+ get :document, params: {version: version}, format: :json
expect(response.content_type)
.to eq("application/json; profile=http://nodeinfo.diaspora.software/ns/schema/#{version}#")
@@ -57,15 +57,9 @@ describe NodeInfoController do
end
describe "#statistics" do
- it "responds to format json" do
+ it "returns a 406 for json format" do
get :statistics, format: "json"
- expect(response.code).to eq("200")
- end
-
- it "contains json" do
- get :statistics, format: "json"
- json = JSON.parse(response.body)
- expect(json["name"]).to be_present
+ expect(response.code).to eq("406")
end
it "responds to html" do
diff --git a/spec/controllers/notifications_controller_spec.rb b/spec/controllers/notifications_controller_spec.rb
index e64b45bb4..58a078bcb 100644
--- a/spec/controllers/notifications_controller_spec.rb
+++ b/spec/controllers/notifications_controller_spec.rb
@@ -10,23 +10,23 @@ describe NotificationsController, :type => :controller do
describe '#update' do
it 'marks a notification as read if it gets no other information' do
note = FactoryGirl.create(:notification)
- expect(Notification).to receive( :where ).and_return( [note] )
- expect(note).to receive( :set_read_state ).with( true )
- get :update, "id" => note.id, :format => :json
+ expect(Notification).to receive(:where).and_return([note])
+ expect(note).to receive(:set_read_state).with(true)
+ get :update, params: {id: note.id}, format: :json
end
it 'marks a notification as read if it is told to' do
note = FactoryGirl.create(:notification)
- expect(Notification).to receive( :where ).and_return( [note] )
- expect(note).to receive( :set_read_state ).with( true )
- get :update, "id" => note.id, :set_unread => "false", :format => :json
+ expect(Notification).to receive(:where).and_return([note])
+ expect(note).to receive(:set_read_state).with(true)
+ get :update, params: {id: note.id, set_unread: "false"}, format: :json
end
it 'marks a notification as unread if it is told to' do
note = FactoryGirl.create(:notification)
- expect(Notification).to receive( :where ).and_return( [note] )
- expect(note).to receive( :set_read_state ).with( false )
- get :update, "id" => note.id, :set_unread => "true", :format => :json
+ expect(Notification).to receive(:where).and_return([note])
+ expect(note).to receive(:set_read_state).with(false)
+ get :update, params: {id: note.id, set_unread: "true"}, format: :json
end
it "marks a notification as unread without timestamping" do
@@ -34,7 +34,7 @@ describe NotificationsController, :type => :controller do
FactoryGirl.create(:notification, recipient: alice, unread: false)
end
- get :update, "id" => note.id, :set_unread => "true", :format => :json
+ get :update, params: {id: note.id, set_unread: "true"}, format: :json
expect(response).to be_success
updated_note = Notification.find(note.id)
@@ -48,7 +48,7 @@ describe NotificationsController, :type => :controller do
FactoryGirl.create(:notification, :recipient => alice)
note = FactoryGirl.create(:notification, :recipient => user2)
- get :update, "id" => note.id, :set_unread => "false", :format => :json
+ get :update, params: {id: note.id, set_unread: "false"}, format: :json
expect(Notification.find(note.id).unread).to eq(true)
end
@@ -77,19 +77,20 @@ describe NotificationsController, :type => :controller do
timeago_content = note_html.css("time")[0]["data-time-ago"]
expect(response_json["unread_count"]).to be(1)
expect(response_json["unread_count_by_type"]).to eq(
- "also_commented" => 1,
- "comment_on_post" => 0,
- "liked" => 0,
- "mentioned" => 0,
- "reshared" => 0,
- "started_sharing" => 0
+ "also_commented" => 1,
+ "comment_on_post" => 0,
+ "liked" => 0,
+ "mentioned" => 0,
+ "mentioned_in_comment" => 0,
+ "reshared" => 0,
+ "started_sharing" => 0
)
expect(timeago_content).to include(@notification.updated_at.iso8601)
expect(response.body).to match(/note_html/)
end
it 'succeeds on mobile' do
- get :index, :format => :mobile
+ get :index, format: :mobile
expect(response).to be_success
end
@@ -97,33 +98,33 @@ describe NotificationsController, :type => :controller do
25.times { FactoryGirl.create(:notification, :recipient => alice, :target => @post) }
get :index
expect(assigns[:notifications].count).to eq(25)
- get :index, "page" => 2
+ get :index, params: {page: 2}
expect(assigns[:notifications].count).to eq(1)
end
it "supports a limit per_page parameter" do
2.times { FactoryGirl.create(:notification, :recipient => alice, :target => @post) }
- get :index, "per_page" => 2
+ get :index, params: {per_page: 2}
expect(assigns[:notifications].count).to eq(2)
end
describe "special case for start sharing notifications" do
it "should not provide a contacts menu for standard notifications" do
FactoryGirl.create(:notification, :recipient => alice, :target => @post)
- get :index, "per_page" => 5
+ get :index, params: {per_page: 5}
expect(Nokogiri(response.body).css('.aspect_membership')).to be_empty
end
it "should provide a contacts menu for start sharing notifications" do
eve.share_with(alice.person, eve.aspects.first)
- get :index, "per_page" => 5
+ get :index, params: {per_page: 5}
expect(Nokogiri(response.body).css(".aspect_membership_dropdown")).not_to be_empty
end
it 'succeeds on mobile' do
eve.share_with(alice.person, eve.aspects.first)
- get :index, :format => :mobile
+ get :index, format: :mobile
expect(response).to be_success
end
end
@@ -131,7 +132,7 @@ describe NotificationsController, :type => :controller do
describe "filter notifications" do
it "supports filtering by notification type" do
FactoryGirl.create(:notification, :recipient => alice, :type => "Notifications::StartedSharing")
- get :index, "type" => "started_sharing"
+ get :index, params: {type: "started_sharing"}
expect(assigns[:notifications].count).to eq(1)
end
@@ -139,7 +140,7 @@ describe NotificationsController, :type => :controller do
FactoryGirl.create(:notification, :recipient => alice, :target => @post)
get :read_all
FactoryGirl.create(:notification, :recipient => alice, :target => @post)
- get :index, "show" => "unread"
+ get :index, params: {show: "unread"}
expect(assigns[:notifications].count).to eq(1)
end
end
@@ -164,46 +165,54 @@ describe NotificationsController, :type => :controller do
end
describe "#read_all" do
- it 'marks all notifications as read' do
+ let(:post) { FactoryGirl.create(:status_message) }
+
+ it "marks all notifications as read" do
request.env["HTTP_REFERER"] = "I wish I were spelled right"
- FactoryGirl.create(:notification, :recipient => alice, :target => @post)
- FactoryGirl.create(:notification, :recipient => alice, :target => @post)
+ FactoryGirl.create(:notification, recipient: alice, target: post)
+ FactoryGirl.create(:notification, recipient: alice, target: post)
- expect(Notification.where(:unread => true).count).to eq(2)
+ expect(Notification.where(unread: true).count).to eq(2)
get :read_all
- expect(Notification.where(:unread => true).count).to eq(0)
+ expect(Notification.where(unread: true).count).to eq(0)
end
- it 'marks all notifications in the current filter as read' do
+
+ it "marks all notifications in the current filter as read" do
request.env["HTTP_REFERER"] = "I wish I were spelled right"
- FactoryGirl.create(:notification, :recipient => alice, :target => @post)
- FactoryGirl.create(:notification, :recipient => alice, :type => "Notifications::StartedSharing")
- expect(Notification.where(:unread => true).count).to eq(2)
- get :read_all, "type" => "started_sharing"
- expect(Notification.where(:unread => true).count).to eq(1)
+ FactoryGirl.create(:notification, recipient: alice, target: post)
+ FactoryGirl.create(:notification, recipient: alice, type: "Notifications::StartedSharing")
+ expect(Notification.where(unread: true).count).to eq(2)
+ get :read_all, params: {type: "started_sharing"}
+ expect(Notification.where(unread: true).count).to eq(1)
end
+
it "should redirect back in the html version if it has > 0 notifications" do
- FactoryGirl.create(:notification, :recipient => alice, :type => "Notifications::StartedSharing")
- get :read_all, :format => :html, "type" => "liked"
+ FactoryGirl.create(:notification, recipient: alice, type: "Notifications::StartedSharing")
+ get :read_all, params: {type: "liked"}, format: :html
expect(response).to redirect_to(notifications_path)
end
+
it "should redirect back in the mobile version if it has > 0 notifications" do
- FactoryGirl.create(:notification, :recipient => alice, :type => "Notifications::StartedSharing")
- get :read_all, :format => :mobile, "type" => "liked"
+ FactoryGirl.create(:notification, recipient: alice, type: "Notifications::StartedSharing")
+ get :read_all, params: {type: "liked"}, format: :mobile
expect(response).to redirect_to(notifications_path)
end
+
it "should redirect to stream in the html version if it has 0 notifications" do
- FactoryGirl.create(:notification, :recipient => alice, :type => "Notifications::StartedSharing")
- get :read_all, :format => :html, "type" => "started_sharing"
+ FactoryGirl.create(:notification, recipient: alice, type: "Notifications::StartedSharing")
+ get :read_all, params: {type: "started_sharing"}, format: :html
expect(response).to redirect_to(stream_path)
end
+
it "should redirect back in the mobile version if it has 0 notifications" do
- FactoryGirl.create(:notification, :recipient => alice, :type => "Notifications::StartedSharing")
- get :read_all, :format => :mobile, "type" => "started_sharing"
+ FactoryGirl.create(:notification, recipient: alice, type: "Notifications::StartedSharing")
+ get :read_all, params: {type: "started_sharing"}, format: :mobile
expect(response).to redirect_to(stream_path)
end
+
it "should return a dummy value in the json version" do
- FactoryGirl.create(:notification, :recipient => alice, :target => @post)
- get :read_all, :format => :json
+ FactoryGirl.create(:notification, recipient: alice, target: post)
+ get :read_all, format: :json
expect(response).not_to be_redirect
end
end
diff --git a/spec/controllers/participations_controller_spec.rb b/spec/controllers/participations_controller_spec.rb
index f557188f1..9c2fc1e2c 100644
--- a/spec/controllers/participations_controller_spec.rb
+++ b/spec/controllers/participations_controller_spec.rb
@@ -9,7 +9,7 @@ describe ParticipationsController, :type => :controller do
shared_examples 'on a visible post' do
it 'creates the participation' do
- post :create, post_id: @post.id
+ post :create, params: {post_id: @post.id}
expect(alice.participations.where(:target_id => @post.id)).to exist
expect(response.code).to eq('201')
end
@@ -47,7 +47,7 @@ describe ParticipationsController, :type => :controller do
end
it 'should not create the participation' do
- post :create, post_id: @post.id
+ post :create, params: {post_id: @post.id}
expect(alice.participations.where(:target_id => @post.id)).not_to exist
expect(response.code).to eq('403')
end
@@ -61,7 +61,7 @@ describe ParticipationsController, :type => :controller do
before { alice.participate! post }
it 'should remove participation' do
- delete :destroy, post_id: post.id
+ delete :destroy, params: {post_id: post.id}
expect(alice.participations.where(:target_id => post.id)).not_to exist
expect(response.code).to eq('200')
end
@@ -69,7 +69,7 @@ describe ParticipationsController, :type => :controller do
context 'on a post you do not partecipate to' do
it 'says it is an unprocessable request' do
- delete :destroy, post_id: post.id
+ delete :destroy, params: {post_id: post.id}
expect(response.code).to eq('422')
end
end
diff --git a/spec/controllers/passwords_controller_spec.rb b/spec/controllers/passwords_controller_spec.rb
index 31c3d3e73..378e3a111 100644
--- a/spec/controllers/passwords_controller_spec.rb
+++ b/spec/controllers/passwords_controller_spec.rb
@@ -10,23 +10,23 @@ describe Devise::PasswordsController, type: :controller do
describe "#create" do
context "when there is no such user" do
it "succeeds" do
- post :create, "user" => {"email" => "foo@example.com"}
+ post :create, params: {user: {email: "foo@example.com"}}
expect(response).to be_success
end
it "doesn't send email" do
expect(Workers::ResetPassword).not_to receive(:perform_async)
- post :create, "user" => {"email" => "foo@example.com"}
+ post :create, params: {user: {email: "foo@example.com"}}
end
end
context "when there is a user with that email" do
it "redirects to the login page" do
- post :create, "user" => {"email" => alice.email}
+ post :create, params: {user: {email: alice.email}}
expect(response).to redirect_to(new_user_session_path)
end
it "sends email (enqueued to Sidekiq)" do
expect(Workers::ResetPassword).to receive(:perform_async).with(alice.id)
- post :create, "user" => {"email" => alice.email}
+ post :create, params: {user: {email: alice.email}}
end
end
end
diff --git a/spec/controllers/people_controller_spec.rb b/spec/controllers/people_controller_spec.rb
index 846244927..bb450b88c 100644
--- a/spec/controllers/people_controller_spec.rb
+++ b/spec/controllers/people_controller_spec.rb
@@ -30,24 +30,24 @@ describe PeopleController, :type => :controller do
describe 'via json' do
it 'succeeds' do
- get :index, :q => "Korth", :format => 'json'
+ get :index, params: {q: "Korth"}, format: :json
expect(response).to be_success
end
it 'responds with json' do
- get :index, :q => "Korth", :format => 'json'
+ get :index, params: {q: "Korth"}, format: :json
expect(response.body).to eq([@korth].to_json)
end
it 'does not assign hashes' do
- get :index, :q => "Korth", :format => 'json'
+ get :index, params: {q: "Korth"}, format: :json
expect(assigns[:hashes]).to be_nil
end
it "doesn't include closed accounts" do
- get :index, q: "Closed", format: "json"
+ get :index, params: {q: "Closed"}, format: :json
expect(JSON.parse(response.body).size).to eq(0)
- get :index, q: @closed.diaspora_handle, format: "json"
+ get :index, params: {q: @closed.diaspora_handle}, format: :json
expect(JSON.parse(response.body).size).to eq(0)
end
end
@@ -60,39 +60,39 @@ describe PeopleController, :type => :controller do
:last_name => "w", :searchable => false))
end
it 'finds people even if they have searchable off' do
- get :index, :q => "eugene@example.org"
+ get :index, params: {q: "eugene@example.org"}
expect(assigns[:people][0].id).to eq(@unsearchable_eugene.id)
end
it 'downcases the query term' do
- get :index, :q => "Eugene@Example.ORG"
+ get :index, params: {q: "Eugene@Example.ORG"}
expect(assigns[:people][0].id).to eq(@unsearchable_eugene.id)
end
it 'does not the background query task if the user is found' do
- get :index, :q => "Eugene@Example.ORG"
+ get :index, params: {q: "Eugene@Example.ORG"}
expect(assigns[:background_query]).to eq(nil)
end
it 'sets background query task if the user is not found' do
- get :index, :q => "Eugene@Example1.ORG"
+ get :index, params: {q: "Eugene@Example1.ORG"}
expect(assigns[:background_query]).to eq("eugene@example1.org")
end
it "doesn't include closed accounts" do
- get :index, q: @closed.diaspora_handle
+ get :index, params: {q: @closed.diaspora_handle}
expect(assigns[:people].size).to eq(0)
end
end
context 'query is not a tag or a diaspora ID' do
it 'assigns hashes' do
- get :index, :q => "Korth"
+ get :index, params: {q: "Korth"}
expect(assigns[:hashes]).not_to be_nil
end
it 'does not set the background query task' do
- get :index, :q => "Korth"
+ get :index, params: {q: "Korth"}
expect(assigns[:background_query]).not_to be_present
end
@@ -100,29 +100,29 @@ describe PeopleController, :type => :controller do
eugene2 = FactoryGirl.create(:person,
:profile => FactoryGirl.build(:profile, :first_name => "Eugene",
:last_name => "w"))
- get :index, :q => "Eug"
+ get :index, params: {q: "Eug"}
expect(assigns[:people].map { |x| x.id }).to match_array([@eugene.id, eugene2.id])
end
it "succeeds if there is exactly one match" do
- get :index, :q => "Korth"
+ get :index, params: {q: "Korth"}
expect(assigns[:people].length).to eq(1)
expect(response).to be_success
end
it "succeeds if there are no matches" do
- get :index, :q => "Korthsauce"
+ get :index, params: {q: "Korthsauce"}
expect(assigns[:people].length).to eq(0)
expect(response).to be_success
end
it 'succeeds if you search for the empty term' do
- get :index, :q => ''
+ get :index, params: {q: ""}
expect(response).to be_success
end
it 'succeeds if you search for punctuation' do
- get :index, :q => '+'
+ get :index, params: {q: "+"}
expect(response).to be_success
end
@@ -130,12 +130,12 @@ describe PeopleController, :type => :controller do
eugene2 = FactoryGirl.create(:person,
:profile => FactoryGirl.build(:profile, :first_name => "Eugene",
:last_name => "w", :searchable => false))
- get :index, :q => "Eug"
+ get :index, params: {q: "Eug"}
expect(assigns[:people]).not_to match_array([eugene2])
end
it "doesn't include closed accounts" do
- get :index, q: "Closed"
+ get :index, params: {q: "Closed"}
expect(assigns[:people].size).to eq(0)
end
end
@@ -164,7 +164,7 @@ describe PeopleController, :type => :controller do
it 'takes time' do
expect(Benchmark.realtime {
- get :show, :id => @user.person.to_param
+ get :show, params: {id: @user.person.to_param}
}).to be < 1.0
end
end
@@ -176,44 +176,44 @@ describe PeopleController, :type => :controller do
end
it "404s if the id is invalid" do
- get :show, :id => 'delicious'
+ get :show, params: {id: "delicious"}
expect(response.code).to eq("404")
end
it "404s if no person is found via id" do
- get :show, :id => "3d920397846"
+ get :show, params: {id: "3d920397846"}
expect(response.code).to eq("404")
end
it "404s if no person is found via username" do
- get :show, :username => 'delicious'
+ get :show, params: {username: "delicious"}
expect(response.code).to eq("404")
end
it "returns a person presenter" do
expect(PersonPresenter).to receive(:new).with(@person, @user).and_return(@presenter)
- get :show, username: @person.username
+ get :show, params: {username: @person.username}
expect(assigns(:presenter).to_json).to eq(@presenter.to_json)
end
it 'finds a person via username' do
- get :show, username: @person.username
+ get :show, params: {username: @person.username}
expect(assigns(:presenter).to_json).to eq(@presenter.to_json)
end
it "404s if no person is found via diaspora handle" do
- get :show, :username => 'delicious@pod.net'
+ get :show, params: {username: "delicious@pod.net"}
expect(response.code).to eq("404")
end
it 'finds a person via diaspora handle' do
- get :show, username: @person.diaspora_handle
+ get :show, params: {username: @person.diaspora_handle}
expect(assigns(:presenter).to_json).to eq(@presenter.to_json)
end
it 'redirects home for closed account' do
@person = FactoryGirl.create(:person, :closed_account => true)
- get :show, :id => @person.to_param
+ get :show, params: {id: @person.to_param}
expect(response).to be_redirect
expect(flash[:notice]).not_to be_blank
end
@@ -222,7 +222,7 @@ describe PeopleController, :type => :controller do
user2 = bob
profile = user2.profile
profile.update_attribute(:first_name, "</script><script> alert('xss attack');</script>")
- get :show, :id => user2.person.to_param
+ get :show, params: {id: user2.person.to_param}
expect(response).to be_success
expect(response.body).not_to include(profile.first_name)
end
@@ -231,27 +231,27 @@ describe PeopleController, :type => :controller do
16.times do |i|
eve.post(:photo, :user_file => uploaded_photo, :to => eve.aspects.first.id, :public => true)
end
- get :show, :id => eve.person.to_param
+ get :show, params: {id: eve.person.to_param}
expect(response.body).to include ',"photos_count":16'
eve.post(:photo, :user_file => uploaded_photo, :to => eve.aspects.first.id, :public => false)
- get :show, :id => eve.person.to_param
+ get :show, params: {id: eve.person.to_param}
expect(response.body).to include ',"photos_count":16' # eve is not sharing with alice
end
context "when the person is the current user" do
it "succeeds" do
- get :show, :id => @user.person.to_param
+ get :show, params: {id: @user.person.to_param}
expect(response).to be_success
end
it 'succeeds on the mobile site' do
- get :show, :id => @user.person.to_param, :format => :mobile
+ get :show, params: {id: @user.person.to_param}, format: :mobile
expect(response).to be_success
end
it "assigns the right person" do
- get :show, id: @person.to_param
+ get :show, params: {id: @person.to_param}
expect(assigns(:presenter).id).to eq(@presenter.id)
end
end
@@ -263,25 +263,25 @@ describe PeopleController, :type => :controller do
end
it "succeeds" do
- get :show, :id => @person.to_param
+ get :show, params: {id: @person.to_param}
expect(response.status).to eq(200)
end
it 'succeeds on the mobile site' do
- get :show, :id => @person.to_param, :format => :mobile
+ get :show, params: {id: @person.to_param}, format: :mobile
expect(response).to be_success
end
it 'forces to sign in if the person is remote' do
p = FactoryGirl.create(:person)
- get :show, :id => p.to_param
+ get :show, params: {id: p.to_param}
expect(response).to be_redirect
expect(response).to redirect_to new_user_session_path
end
it "leaks no private profile info" do
- get :show, id: @person.to_param
+ get :show, params: {id: @person.to_param}
expect(response.body).not_to include(@person.profile.bio)
end
@@ -296,7 +296,7 @@ describe PeopleController, :type => :controller do
last_name: {html_attribute: "property", name: "og:profile:last_name"}
}
- get :show, id: @person.to_param
+ get :show, params: {id: @person.to_param}
methods_properties.each do |method, property|
value = presenter.send(method)
@@ -313,12 +313,12 @@ describe PeopleController, :type => :controller do
end
it "succeeds" do
- get :show, :id => @person.to_param
+ get :show, params: {id: @person.to_param}
expect(response).to be_success
end
it 'succeeds on the mobile site' do
- get :show, :id => @person.to_param, :format => :mobile
+ get :show, params: {id: @person.to_param}, format: :mobile
expect(response).to be_success
end
@@ -326,18 +326,18 @@ describe PeopleController, :type => :controller do
note = FactoryGirl.create(:notification, :recipient => @user, :target => @person, :unread => true)
expect {
- get :show, :id => @person.to_param
+ get :show, params: {id: @person.to_param}
note.reload
}.to change(Notification.where(:unread => true), :count).by(-1)
end
it "includes private profile info" do
- get :show, id: @person.to_param
+ get :show, params: {id: @person.to_param}
expect(response.body).to include(@person.profile.bio)
end
it "preloads data using gon for the aspect memberships dropdown" do
- get :show, id: @person.to_param
+ get :show, params: {id: @person.to_param}
expect_gon_preloads_for_aspect_membership_dropdown(:person, true)
end
end
@@ -348,22 +348,22 @@ describe PeopleController, :type => :controller do
end
it "succeeds" do
- get :show, :id => @person.to_param
+ get :show, params: {id: @person.to_param}
expect(response).to be_success
end
it 'succeeds on the mobile site' do
- get :show, :id => @person.to_param, :format => :mobile
+ get :show, params: {id: @person.to_param}, format: :mobile
expect(response).to be_success
end
it "leaks no private profile info" do
- get :show, id: @person.to_param
+ get :show, params: {id: @person.to_param}
expect(response.body).not_to include(@person.profile.bio)
end
it "preloads data using gon for the aspect memberships dropdown" do
- get :show, id: @person.to_param
+ get :show, params: {id: @person.to_param}
expect_gon_preloads_for_aspect_membership_dropdown(:person, false)
end
end
@@ -376,7 +376,7 @@ describe PeopleController, :type => :controller do
end
it "leaks no private profile info" do
- get :show, id: @person.to_param
+ get :show, params: {id: @person.to_param}
expect(response.body).not_to include(@person.profile.bio)
end
end
@@ -384,7 +384,7 @@ describe PeopleController, :type => :controller do
describe '#stream' do
it "redirects non-json requests" do
- get :stream, person_id: @user.person.to_param
+ get :stream, params: {person_id: @user.person.to_param}
expect(response).to be_redirect
end
@@ -395,7 +395,7 @@ describe PeopleController, :type => :controller do
@user.post(:status_message, :text => "to all aspects", :to => 'all')
@user.post(:status_message, :text => "public", :to => 'all', :public => true)
expect(@user.reload.posts.length).to eq(3)
- get :stream, person_id: @user.person.to_param, format: :json
+ get :stream, params: {person_id: @user.person.to_param}, format: :json
expect(assigns(:stream).posts.map(&:id)).to match_array(@user.posts.map(&:id))
end
@@ -403,7 +403,7 @@ describe PeopleController, :type => :controller do
cmmt = 'I mean it'
message = @user.post :status_message, :text => 'test more', :to => @aspect.id
@user.comment!(message, cmmt)
- get :stream, person_id: @user.person.to_param, format: :json
+ get :stream, params: {person_id: @user.person.to_param}, format: :json
expect(response).to be_success
expect(response.body).to include(cmmt)
end
@@ -416,7 +416,7 @@ describe PeopleController, :type => :controller do
it "includes reshares" do
reshare = @user.post(:reshare, :public => true, :root_guid => FactoryGirl.create(:status_message, :public => true).guid, :to => alice.aspect_ids)
- get :stream, person_id: @user.person.to_param, format: :json
+ get :stream, params: {person_id: @user.person.to_param}, format: :json
expect(assigns[:stream].posts.map { |x| x.id }).to include(reshare.id)
end
@@ -431,7 +431,7 @@ describe PeopleController, :type => :controller do
posts_user_can_see << bob.post(:status_message, :text => "public", :to => 'all', :public => true)
expect(bob.reload.posts.length).to eq(4)
- get :stream, person_id: @person.to_param, format: :json
+ get :stream, params: {person_id: @person.to_param}, format: :json
expect(assigns(:stream).posts.map(&:id)).to match_array(posts_user_can_see.map(&:id))
end
end
@@ -448,13 +448,13 @@ describe PeopleController, :type => :controller do
public_post = eve.post(:status_message, :text => "public", :to => 'all', :public => true)
expect(eve.reload.posts.length).to eq(3)
- get :stream, person_id: @person.to_param, format: :json
+ get :stream, params: {person_id: @person.to_param}, format: :json
expect(assigns[:stream].posts.map(&:id)).to match_array([public_post].map(&:id))
end
it "posts include reshares" do
reshare = @user.post(:reshare, :public => true, :root_guid => FactoryGirl.create(:status_message, :public => true).guid, :to => alice.aspect_ids)
- get :stream, person_id: @user.person.to_param, format: :json
+ get :stream, params: {person_id: @user.person.to_param}, format: :json
expect(assigns[:stream].posts.map { |x| x.id }).to include(reshare.id)
end
end
@@ -478,17 +478,17 @@ describe PeopleController, :type => :controller do
it "posts include reshares" do
reshare = @user.post(:reshare, :public => true, :root_guid => FactoryGirl.create(:status_message, :public => true).guid, :to => alice.aspect_ids)
- get :stream, person_id: @user.person.to_param, format: :json
+ get :stream, params: {person_id: @user.person.to_param}, format: :json
expect(assigns[:stream].posts.map { |x| x.id }).to include(reshare.id)
end
it "assigns only public posts" do
- get :stream, person_id: @person.to_param, format: :json
+ get :stream, params: {person_id: @person.to_param}, format: :json
expect(assigns[:stream].posts.map(&:id)).to match_array(@public_posts.map(&:id))
end
it 'is sorted by created_at desc' do
- get :stream, person_id: @person.to_param, format: :json
+ get :stream, params: {person_id: @person.to_param}, format: :json
expect(assigns[:stream].stream_posts).to eq(@public_posts.sort_by { |p| p.created_at }.reverse)
end
end
@@ -503,19 +503,19 @@ describe PeopleController, :type => :controller do
end
it 'redirects html requests' do
- get :hovercard, :person_id => @hover_test.guid
+ get :hovercard, params: {person_id: @hover_test.guid}
expect(response).to redirect_to person_path(:id => @hover_test.guid)
end
it 'returns json with profile stuff' do
- get :hovercard, :person_id => @hover_test.guid, :format => 'json'
+ get :hovercard, params: {person_id: @hover_test.guid}, format: :json
expect(JSON.parse(response.body)["diaspora_id"]).to eq(@hover_test.diaspora_handle)
end
it "returns contact when sharing" do
alice.share_with(@hover_test, alice.aspects.first)
expect(@controller).to receive(:current_user).at_least(:once).and_return(alice)
- get :hovercard, person_id: @hover_test.guid, format: "json"
+ get :hovercard, params: {person_id: @hover_test.guid}, format: :json
expect(JSON.parse(response.body)["contact"]).not_to be_falsy
end
@@ -525,13 +525,13 @@ describe PeopleController, :type => :controller do
end
it "succeeds with local person" do
- get :hovercard, person_id: bob.person.guid, format: :json
+ get :hovercard, params: {person_id: bob.person.guid}, format: :json
expect(response.status).to eq(200)
expect(JSON.parse(response.body)["diaspora_id"]).to eq(bob.diaspora_handle)
end
it "succeeds with remote person" do
- get :hovercard, person_id: remote_raphael.guid, format: :json
+ get :hovercard, params: {person_id: remote_raphael.guid}, format: :json
expect(response.status).to eq(200)
expect(JSON.parse(response.body)["diaspora_id"]).to eq(remote_raphael.diaspora_handle)
end
@@ -557,22 +557,22 @@ describe PeopleController, :type => :controller do
describe "via json" do
it "returns no data when a search fails" do
- get :refresh_search, q: "weweweKorth", format: "json"
+ get :refresh_search, params: {q: "weweweKorth"}, format: :json
expect(response.body).to eq({search_html: "", contacts: nil}.to_json)
end
it "returns no data unless a fully composed name is sent" do
- get :refresh_search, q: "Korth"
+ get :refresh_search, params: {q: "Korth"}
expect(response.body).to eq({search_html: "", contacts: nil}.to_json)
end
it "returns with a found name" do
- get :refresh_search, q: @korth.diaspora_handle
+ get :refresh_search, params: {q: @korth.diaspora_handle}
expect(JSON.parse(response.body)["contacts"].size).to eq(1)
end
it "doesn't include closed accounts" do
- get :refresh_search, q: @closed.diaspora_handle
+ get :refresh_search, params: {q: @closed.diaspora_handle}
expect(JSON.parse(response.body)["contacts"]).to be_nil
end
end
@@ -583,13 +583,13 @@ describe PeopleController, :type => :controller do
it 'assigns the contacts of a person' do
contact = alice.contact_for(bob.person)
contacts = contact.contacts
- get :contacts, :person_id => bob.person.to_param
+ get :contacts, params: {person_id: bob.person.to_param}
expect(assigns(:contacts_of_contact).to_a).to eq(contacts.to_a)
expect(response).to be_success
end
it 'shows an error when invalid person id' do
- get :contacts, :person_id => 'foo'
+ get :contacts, params: {person_id: "foo"}
expect(flash[:error]).to be_present
expect(response).to redirect_to people_path
end
@@ -598,16 +598,16 @@ describe PeopleController, :type => :controller do
16.times do |i|
eve.post(:photo, :user_file => uploaded_photo, :to => eve.aspects.first.id, :public => true)
end
- get :contacts, :person_id => eve.person.to_param
+ get :contacts, params: {person_id: eve.person.to_param}
expect(response.body).to include ',"photos_count":16'
eve.post(:photo, :user_file => uploaded_photo, :to => eve.aspects.first.id, :public => false)
- get :contacts, :person_id => eve.person.to_param
+ get :contacts, params: {person_id: eve.person.to_param}
expect(response.body).to include ',"photos_count":16' # eve is not sharing with alice
end
it "returns a 406 for json format" do
- get :contacts, person_id: "foo", format: :json
+ get :contacts, params: {person_id: "foo"}, format: :json
expect(response.code).to eq("406")
end
end
diff --git a/spec/controllers/photos_controller_spec.rb b/spec/controllers/photos_controller_spec.rb
index 9b76fffe5..d323ba87b 100644
--- a/spec/controllers/photos_controller_spec.rb
+++ b/spec/controllers/photos_controller_spec.rb
@@ -24,18 +24,18 @@ describe PhotosController, :type => :controller do
it 'accepts a photo from a regular form submission' do
expect {
- post :create, @params
+ post :create, params: @params
}.to change(Photo, :count).by(1)
end
it 'returns application/json when possible' do
request.env['HTTP_ACCEPT'] = 'application/json'
- expect(post(:create, @params).headers['Content-Type']).to match 'application/json.*'
+ expect(post(:create, params: @params).headers["Content-Type"]).to match "application/json.*"
end
it 'returns text/html by default' do
request.env['HTTP_ACCEPT'] = 'text/html,*/*'
- expect(post(:create, @params).headers['Content-Type']).to match 'text/html.*'
+ expect(post(:create, params: @params).headers["Content-Type"]).to match "text/html.*"
end
end
@@ -47,57 +47,57 @@ describe PhotosController, :type => :controller do
it "creates a photo" do
expect {
- post :create, @params
+ post :create, params: @params
}.to change(Photo, :count).by(1)
end
it "doesn't allow mass assignment of person" do
new_user = FactoryGirl.create(:user)
@params[:photo][:author] = new_user
- post :create, @params
+ post :create, params: @params
expect(Photo.last.author).to eq(alice.person)
end
it "doesn't allow mass assignment of person_id" do
new_user = FactoryGirl.create(:user)
@params[:photo][:author_id] = new_user.id
- post :create, @params
+ post :create, params: @params
expect(Photo.last.author).to eq(alice.person)
end
it 'can set the photo as the profile photo' do
old_url = alice.person.profile.image_url
@params[:photo][:set_profile_photo] = true
- post :create, @params
+ post :create, params: @params
expect(alice.reload.person.profile.image_url).not_to eq(old_url)
end
end
describe '#index' do
it "succeeds without any available pictures" do
- get :index, :person_id => FactoryGirl.create(:person).guid.to_s
+ get :index, params: {person_id: FactoryGirl.create(:person).guid}
expect(response).to be_success
end
it "succeeds on mobile devices without any available pictures" do
- get :index, format: :mobile, person_id: FactoryGirl.create(:person).guid.to_s
+ get :index, params: {person_id: FactoryGirl.create(:person).guid}, format: :mobile
expect(response).to be_success
end
it "succeeds on mobile devices with available pictures" do
- get :index, format: :mobile, person_id: bob.person.guid.to_s
+ get :index, params: {person_id: bob.person.guid}, format: :mobile
expect(response).to be_success
end
it "displays the logged in user's pictures" do
- get :index, :person_id => alice.person.guid.to_s
+ get :index, params: {person_id: alice.person.guid}
expect(assigns[:person]).to eq(alice.person)
expect(assigns[:posts]).to eq([@alices_photo])
end
it "displays another person's pictures" do
- get :index, :person_id => bob.person.guid.to_s
+ get :index, params: {person_id: bob.person.guid}
expect(assigns[:person]).to eq(bob.person)
expect(assigns[:posts]).to eq([@bobs_photo])
end
@@ -106,25 +106,24 @@ describe PhotosController, :type => :controller do
16.times do |i|
eve.post(:photo, :user_file => uploaded_photo, :to => eve.aspects.first.id, :public => true)
end
- get :index, :person_id => eve.person.to_param
+ get :index, params: {person_id: eve.person.to_param}
expect(response.body).to include ',"photos_count":16'
eve.post(:photo, :user_file => uploaded_photo, :to => eve.aspects.first.id, :public => false)
- get :index, :person_id => eve.person.to_param
+ get :index, params: {person_id: eve.person.to_param}
expect(response.body).to include ',"photos_count":16' # eve is not sharing with alice
end
it "returns json when requested" do
request.env['HTTP_ACCEPT'] = 'application/json'
- get :index, :person_id => alice.person.guid.to_s
+ get :index, params: {person_id: alice.person.guid}
expect(response.headers['Content-Type']).to match 'application/json.*'
end
it 'displays by date of creation' do
max_time = bob.photos.first.created_at - 1.day
- get :index, person_id: bob.person.guid.to_s,
- max_time: max_time.to_i
+ get :index, params: {person_id: bob.person.guid, max_time: max_time.to_i}
expect(assigns[:posts]).to be_empty
end
@@ -136,19 +135,19 @@ describe PhotosController, :type => :controller do
end
it "succeeds" do
- get :index, person_id: @person.to_param
+ get :index, params: {person_id: @person.to_param}
expect(response.status).to eq(200)
end
it "succeeds on the mobile site" do
- get :index, person_id: @person.to_param, format: :mobile
+ get :index, params: {person_id: @person.to_param}, format: :mobile
expect(response).to be_success
end
it "forces to sign in if the person is remote" do
p = FactoryGirl.create(:person)
- get :index, person_id: p.to_param
+ get :index, params: {person_id: p.to_param}
expect(response).to be_redirect
expect(response).to redirect_to new_user_session_path
end
@@ -157,16 +156,16 @@ describe PhotosController, :type => :controller do
16.times do
eve.post(:photo, user_file: uploaded_photo, to: eve.aspects.first.id, public: true)
end
- get :index, person_id: eve.person.to_param
+ get :index, params: {person_id: eve.person.to_param}
expect(response.body).to include ',"photos_count":16'
eve.post(:photo, user_file: uploaded_photo, to: eve.aspects.first.id, public: false)
- get :index, person_id: eve.person.to_param
+ get :index, params: {person_id: eve.person.to_param}
expect(response.body).to include ',"photos_count":16'
end
it "displays a person's pictures" do
- get :index, person_id: bob.person.guid.to_s
+ get :index, params: {person_id: bob.person.guid}
expect(assigns[:person]).to eq(bob.person)
expect(assigns[:posts]).to eq([@bobs_photo])
end
@@ -175,42 +174,42 @@ describe PhotosController, :type => :controller do
describe '#destroy' do
it 'let a user delete his message' do
- delete :destroy, :id => @alices_photo.id
+ delete :destroy, params: {id: @alices_photo.id}
expect(Photo.find_by_id(@alices_photo.id)).to be_nil
end
it 'will let you delete your profile picture' do
- xhr :get, :make_profile_photo, :photo_id => @alices_photo.id, :format => :js
- delete :destroy, :id => @alices_photo.id
+ get :make_profile_photo, params: {photo_id: @alices_photo.id}, xhr: true, format: :js
+ delete :destroy, params: {id: @alices_photo.id}, format: :json
expect(Photo.find_by_id(@alices_photo.id)).to be_nil
end
it 'sends a retraction on delete' do
allow(@controller).to receive(:current_user).and_return(alice)
expect(alice).to receive(:retract).with(@alices_photo)
- delete :destroy, :id => @alices_photo.id
+ delete :destroy, params: {id: @alices_photo.id}
end
it 'will not let you destroy posts visible to you' do
- delete :destroy, :id => @bobs_photo.id
+ delete :destroy, params: {id: @bobs_photo.id}
expect(Photo.find_by_id(@bobs_photo.id)).to be_truthy
end
it 'will not let you destroy posts you do not own' do
eves_photo = eve.post(:photo, :user_file => uploaded_photo, :to => eve.aspects.first.id, :public => true)
- delete :destroy, :id => eves_photo.id
+ delete :destroy, params: {id: eves_photo.id}
expect(Photo.find_by_id(eves_photo.id)).to be_truthy
end
end
describe "#make_profile_photo" do
it 'should return a 201 on a js success' do
- xhr :get, :make_profile_photo, :photo_id => @alices_photo.id, :format => 'js'
+ get :make_profile_photo, params: {photo_id: @alices_photo.id}, xhr: true, format: :js
expect(response.code).to eq("201")
end
it 'should return a 422 on failure' do
- get :make_profile_photo, :photo_id => @bobs_photo.id
+ get :make_profile_photo, params: {photo_id: @bobs_photo.id}
expect(response.code).to eq("422")
end
end
@@ -218,19 +217,19 @@ describe PhotosController, :type => :controller do
describe "#show" do
it 'should return 404 for nonexistent stuff on mobile devices' do
expect {
- get :show, :person_id => bob.person.guid, :id => 772831, :format => 'mobile'
+ get :show, params: {person_id: bob.person.guid, id: 772_831}, format: :mobile
}.to raise_error ActiveRecord::RecordNotFound
end
it 'should return 200 for existing stuff on mobile devices' do
- get :show, :person_id => alice.person.guid, :id => @alices_photo.id, :format => 'mobile'
+ get :show, params: {person_id: alice.person.guid, id: @alices_photo.id}, format: :mobile
expect(response).to be_success
end
it "doesn't leak private photos to the public" do
sign_out :user
expect {
- get :show, :person_id => alice.person.guid, :id => @alices_photo.id, :format => 'mobile'
+ get :show, params: {person_id: alice.person.guid, id: @alices_photo.id}, format: :mobile
}.to raise_error ActiveRecord::RecordNotFound
end
end
diff --git a/spec/controllers/posts_controller_spec.rb b/spec/controllers/posts_controller_spec.rb
index 7f2d9c9fb..2c5f72f92 100644
--- a/spec/controllers/posts_controller_spec.rb
+++ b/spec/controllers/posts_controller_spec.rb
@@ -4,6 +4,7 @@
describe PostsController, type: :controller do
let(:post) { alice.post(:status_message, text: "ohai", to: alice.aspects.first) }
+ let(:post_service) { controller.send(:post_service) }
describe "#show" do
context "user signed in" do
@@ -15,7 +16,7 @@ describe PostsController, type: :controller do
it "succeeds" do
expect_any_instance_of(PostService).to receive(:mark_user_notifications).with(post.id)
- get :show, id: post.id
+ get :show, params: {id: post.id}
expect(response).to be_success
end
@@ -28,12 +29,12 @@ describe PostsController, type: :controller do
expect(msg.mentioned_people.count).to eq(1)
user.destroy
- get :show, id: msg.id
+ get :show, params: {id: msg.id}
expect(response).to be_success
end
it "renders the application layout on mobile" do
- get :show, id: post.id, format: :mobile
+ get :show, params: {id: post.id}, format: :mobile
expect(response).to render_template("layouts/application")
end
@@ -41,7 +42,7 @@ describe PostsController, type: :controller do
reshare_id = FactoryGirl.create(:reshare, author: alice.person).id
expect_any_instance_of(PostService).to receive(:mark_user_notifications).with(reshare_id)
- get :show, id: reshare_id, format: :mobile
+ get :show, params: {id: reshare_id}, format: :mobile
expect(response).to be_success
end
end
@@ -53,7 +54,7 @@ describe PostsController, type: :controller do
it "returns a 404" do
expect {
- get :show, id: post.id
+ get :show, params: {id: post.id}
}.to raise_error ActiveRecord::RecordNotFound
end
end
@@ -65,22 +66,16 @@ describe PostsController, type: :controller do
let(:public_with_tags) { alice.post(:status_message, text: "#hi #howareyou", public: true) }
it "shows a public post" do
- get :show, id: public.id
+ get :show, params: {id: public.id}
expect(response.body).to match "hello"
end
it "succeeds for statusnet" do
@request.env["HTTP_ACCEPT"] = "application/html+xml,text/html"
- get :show, id: public.id
+ get :show, params: {id: public.id}
expect(response.body).to match "hello"
end
- it "responds with diaspora xml if format is xml" do
- get :show, id: public.guid, format: :xml
- expected_xml = DiasporaFederation::Salmon::XmlPayload.pack(Diaspora::Federation::Entities.post(public)).to_xml
- expect(response.body).to eq(expected_xml)
- end
-
it "includes the correct uniques meta tags" do
presenter = PostPresenter.new(public)
methods_properties = {
@@ -93,7 +88,7 @@ describe PostsController, type: :controller do
author_name: {html_attribute: "property", name: "og:article:author"}
}
- get :show, id: public.id, format: :html
+ get :show, params: {id: public.id}, format: :html
methods_properties.each do |method, property|
value = presenter.send(method)
@@ -104,7 +99,7 @@ describe PostsController, type: :controller do
end
it "includes the correct multiple meta tags" do
- get :show, id: public_with_tags.id, format: :html
+ get :show, params: {id: public_with_tags.id}, format: :html
expect(response.body).to include('<meta property="og:article:tag" content="hi" />')
expect(response.body).to include('<meta property="og:article:tag" content="howareyou" />')
@@ -113,7 +108,7 @@ describe PostsController, type: :controller do
context "given a limited post" do
it "forces the user to sign" do
- get :show, id: post.id
+ get :show, params: {id: post.id}
expect(response).to be_redirect
expect(response).to redirect_to new_user_session_path
end
@@ -124,44 +119,54 @@ describe PostsController, type: :controller do
describe "oembed" do
it "works when you can see it" do
sign_in alice
- get :oembed, url: "/posts/#{post.id}"
+ get :oembed, params: {url: "/posts/#{post.id}"}
expect(response.body).to match /iframe/
end
it "returns a 404 response when the post is not found" do
- get :oembed, url: "/posts/#{post.id}"
+ get :oembed, params: {url: "/posts/#{post.id}"}
expect(response.status).to eq(404)
end
end
- describe "#interactions" do
- context "user not signed in" do
- it "returns a 401 for private posts and format json" do
- get :interactions, id: post.id, format: :json
- expect(response.status).to eq(401)
- expect(JSON.parse(response.body)["error"]).to eq(I18n.t("devise.failure.unauthenticated"))
+ describe "#mentionable" do
+ context "with a user signed in" do
+ before do
+ sign_in alice
+ end
+
+ it "returns status 204 without a :q parameter" do
+ get :mentionable, params: {id: post.id}, format: :json
+ expect(response.status).to eq(204)
end
- it "returns a 406 for private posts and format html" do
- get :interactions, id: post.id
+ it "responses status 406 (not acceptable) on html request" do
+ get :mentionable, params: {id: post.id, q: "whatever"}, format: :html
expect(response.status).to eq(406)
end
- end
- context "user signed in" do
- before do
- sign_in alice
+ it "responses status 404 when the post can't be found" do
+ expect(post_service).to receive(:find!) do
+ raise ActiveRecord::RecordNotFound
+ end
+ get :mentionable, params: {id: post.id, q: "whatever"}, format: :json
+ expect(response.status).to eq(404)
end
- it "shows interactions of a post as json" do
- get :interactions, id: post.id, format: :json
- expect(response.body).to eq(PostInteractionPresenter.new(post, alice).to_json)
+ it "calls PostService#mentionable_in_comment and passes the result as a response" do
+ expect(post_service).to receive(:mentionable_in_comment).with(post.id.to_s, "whatever").and_return([bob.person])
+ get :mentionable, params: {id: post.id, q: "whatever"}, format: :json
+ expect(response.status).to eq(200)
+ expect(response.body).to eq([bob.person].to_json)
end
+ end
- it "returns a 406 for format html" do
- sign_in alice
- get :interactions, id: post.id
- expect(response.status).to eq(406)
+ context "without a user signed in" do
+ it "returns 401" do
+ allow(post_service).to receive(:mentionable_in_comment).and_return([])
+ get :mentionable, params: {id: post.id, q: "whatever"}, format: :json
+ expect(response.status).to eq(401)
+ expect(JSON.parse(response.body)["error"]).to eq(I18n.t("devise.failure.unauthenticated"))
end
end
end
@@ -175,12 +180,12 @@ describe PostsController, type: :controller do
it "works when it is your post" do
expect_any_instance_of(PostService).to receive(:destroy).with(post.id.to_s)
- delete :destroy, format: :json, id: post.id
+ delete :destroy, params: {id: post.id}, format: :json
expect(response.status).to eq(204)
end
it "redirects to stream on mobile" do
- delete :destroy, format: :mobile, id: post.id
+ delete :destroy, params: {id: post.id}, format: :mobile
expect(response).to be_redirect
expect(response).to redirect_to stream_path
end
@@ -190,7 +195,7 @@ describe PostsController, type: :controller do
it "will respond with a 403" do
sign_in bob, scope: :user
- delete :destroy, format: :json, id: post.id
+ delete :destroy, params: {id: post.id}, format: :json
expect(response.body).to eq("You are not allowed to do that")
expect(response.status).to eq(403)
end
@@ -199,7 +204,7 @@ describe PostsController, type: :controller do
sign_in eve, scope: :user
expect {
- delete :destroy, format: :json, id: post.id
+ delete :destroy, params: {id: post.id}, format: :json
}.to raise_error ActiveRecord::RecordNotFound
end
end
diff --git a/spec/controllers/profiles_controller_spec.rb b/spec/controllers/profiles_controller_spec.rb
index 9a6a47e8e..405b2902b 100644
--- a/spec/controllers/profiles_controller_spec.rb
+++ b/spec/controllers/profiles_controller_spec.rb
@@ -15,7 +15,7 @@ describe ProfilesController, :type => :controller do
expect(Person).to receive(:find_by_guid!).with("12345").and_return(mock_person)
expect(PersonPresenter).to receive(:new).with(mock_person, eve).and_return(mock_presenter)
- get :show, :id => 12345, :format => :json
+ get :show, params: {id: 12_345}, format: :json
expect(response.body).to eq({:rock_star => "Jamie Cai"}.to_json)
end
end
@@ -44,27 +44,29 @@ describe ProfilesController, :type => :controller do
describe '#update' do
it "sets the flash" do
- put :update, :profile => {
- :image_url => "",
- :first_name => "Will",
- :last_name => "Smith"
+ put :update, params: {
+ profile: {
+ image_url: "",
+ first_name: "Will",
+ last_name: "Smith"
}
+ }
expect(flash[:notice]).not_to be_blank
end
it "sets nsfw" do
- expect(eve.person(true).profile.nsfw).to eq(false)
- put :update, :profile => { :id => eve.person.id, :nsfw => "1" }
- expect(eve.person(true).profile.nsfw).to eq(true)
+ expect(eve.person.reload.profile.nsfw).to eq(false)
+ put :update, params: {profile: {id: eve.person.id, nsfw: "1"}}
+ expect(eve.person.reload.profile.nsfw).to eq(true)
end
it "unsets nsfw" do
eve.person.profile.nsfw = true
eve.person.profile.save
- expect(eve.person(true).profile.nsfw).to eq(true)
- put :update, :profile => { :id => eve.person.id }
- expect(eve.person(true).profile.nsfw).to eq(false)
+ expect(eve.person.reload.profile.nsfw).to eq(true)
+ put :update, params: {profile: {id: eve.person.id}}
+ expect(eve.person.reload.profile.nsfw).to eq(false)
end
it 'sets tags' do
@@ -72,8 +74,8 @@ describe ProfilesController, :type => :controller do
:tags => '#apples #oranges',
:profile => {:tag_string => ''} }
- put :update, params
- expect(eve.person(true).profile.tag_list.to_set).to eq(['apples', 'oranges'].to_set)
+ put :update, params: params
+ expect(eve.person.reload.profile.tag_list.to_set).to eq(%w[apples oranges].to_set)
end
it 'sets plaintext tags' do
@@ -81,8 +83,8 @@ describe ProfilesController, :type => :controller do
:tags => ',#apples,#oranges,',
:profile => {:tag_string => '#pears'} }
- put :update, params
- expect(eve.person(true).profile.tag_list.to_set).to eq(['apples', 'oranges', 'pears'].to_set)
+ put :update, params: params
+ expect(eve.person.reload.profile.tag_list.to_set).to eq(%w[apples oranges pears].to_set)
end
it 'sets plaintext tags without #' do
@@ -90,8 +92,8 @@ describe ProfilesController, :type => :controller do
:tags => ',#apples,#oranges,',
:profile => {:tag_string => 'bananas'} }
- put :update, params
- expect(eve.person(true).profile.tag_list.to_set).to eq(['apples', 'oranges', 'bananas'].to_set)
+ put :update, params: params
+ expect(eve.person.reload.profile.tag_list.to_set).to eq(%w[apples oranges bananas].to_set)
end
it 'sets valid birthday' do
@@ -102,10 +104,11 @@ describe ProfilesController, :type => :controller do
:month => '02',
:day => '28' } } }
- put :update, params
- expect(eve.person(true).profile.birthday.year).to eq(2001)
- expect(eve.person(true).profile.birthday.month).to eq(2)
- expect(eve.person(true).profile.birthday.day).to eq(28)
+ put :update, params: params
+ birthday = eve.person.reload.profile.birthday
+ expect(birthday.year).to eq(2001)
+ expect(birthday.month).to eq(2)
+ expect(birthday.day).to eq(28)
end
it 'displays error for invalid birthday' do
@@ -116,7 +119,7 @@ describe ProfilesController, :type => :controller do
:month => '02',
:day => '31' } } }
- put :update, params
+ put :update, params: params
expect(flash[:error]).not_to be_blank
end
@@ -134,7 +137,7 @@ describe ProfilesController, :type => :controller do
it "doesn't overwrite the profile photo when an empty string is passed in" do
image_url = eve.person.profile.image_url
- put :update, @params
+ put :update, params: @params
expect(Person.find(eve.person.id).profile.image_url).to eq(image_url)
end
@@ -150,12 +153,12 @@ describe ProfilesController, :type => :controller do
it 'person_id' do
person = eve.person
profile = person.profile
- put :update, @profile_params
+ put :update, params: @profile_params
expect(profile.reload.person_id).to eq(person.id)
end
it 'diaspora handle' do
- put :update, @profile_params
+ put :update, params: @profile_params
expect(Person.find(eve.person.id).profile[:diaspora_handle]).not_to eq('abc@a.com')
end
end
diff --git a/spec/controllers/registrations_controller_spec.rb b/spec/controllers/registrations_controller_spec.rb
index d39edb683..91cf4603d 100644
--- a/spec/controllers/registrations_controller_spec.rb
+++ b/spec/controllers/registrations_controller_spec.rb
@@ -30,19 +30,19 @@ describe RegistrationsController, type: :controller do
end
it "redirects #create to the login page" do
- post :create, valid_params
+ post :create, params: valid_params
expect(flash[:error]).to eq(I18n.t("registrations.closed"))
expect(response).to redirect_to new_user_session_path
end
it "does not redirect if there is a valid invite token" do
code = InvitationCode.create(user: bob)
- get :new, invite: {token: code.token}
+ get :new, params: {invite: {token: code.token}}
expect(response).not_to be_redirect
end
it "does redirect if there is an invalid invite token" do
- get :new, invite: {token: "fssdfsd"}
+ get :new, params: {invite: {token: "fssdfsd"}}
expect(response).to redirect_to new_user_session_path
end
@@ -50,7 +50,7 @@ describe RegistrationsController, type: :controller do
code = InvitationCode.create(user: bob)
code.update_attributes(count: 0)
- get :new, invite: {token: code.token}
+ get :new, params: {invite: {token: code.token}}
expect(response).to redirect_to new_user_session_path
end
@@ -58,7 +58,7 @@ describe RegistrationsController, type: :controller do
code = InvitationCode.create(user: bob)
AppConfig.settings.invitations.open = false
- get :new, invite: {token: code.token}
+ get :new, params: {invite: {token: code.token}}
expect(response).to redirect_to new_user_session_path
end
@@ -68,7 +68,7 @@ describe RegistrationsController, type: :controller do
code = InvitationCode.create(user: bob)
code.update_attributes(count: 0)
- get :new, invite: {token: code.token}
+ get :new, params: {invite: {token: code.token}}
expect(response).not_to be_redirect
end
end
@@ -79,22 +79,22 @@ describe RegistrationsController, type: :controller do
context "with valid parameters" do
it "creates a user" do
expect {
- get :create, valid_params
+ get :create, params: valid_params
}.to change(User, :count).by(1)
end
it "assigns @user" do
- get :create, valid_params
+ get :create, params: valid_params
expect(assigns(:user)).to be_truthy
end
it "sets the flash" do
- get :create, valid_params
+ get :create, params: valid_params
expect(flash[:notice]).not_to be_blank
end
it "redirects to the home path" do
- get :create, valid_params
+ get :create, params: valid_params
expect(response).to be_redirect
expect(response.location).to match(/^#{getting_started_url}$/)
end
@@ -106,7 +106,7 @@ describe RegistrationsController, type: :controller do
code = InvitationCode.create(user: bob)
expect {
- get :create, valid_params.merge(invite: {token: code.token})
+ get :create, params: valid_params.merge(invite: {token: code.token})
}.to change { code.reload.count }.by(-1)
end
@@ -114,14 +114,14 @@ describe RegistrationsController, type: :controller do
code = InvitationCode.create(user: bob)
expect {
- get :create, valid_params.merge(invite: {token: code.token})
+ get :create, params: valid_params.merge(invite: {token: code.token})
}.not_to change { code.reload.count }
end
it "links inviter with the user" do
code = InvitationCode.create(user: bob)
- post :create, valid_params.merge(invite: {token: code.token})
+ post :create, params: valid_params.merge(invite: {token: code.token})
expect(User.find_by(username: "jdoe").invited_by).to eq(bob)
end
@@ -132,20 +132,20 @@ describe RegistrationsController, type: :controller do
let(:invalid_params) { valid_params.deep_merge(user: {password_confirmation: "baddword"}) }
it "does not create a user" do
- expect { get :create, invalid_params }.not_to change(User, :count)
+ expect { get :create, params: invalid_params }.not_to change(User, :count)
end
it "does not create a person" do
- expect { get :create, invalid_params }.not_to change(Person, :count)
+ expect { get :create, params: invalid_params }.not_to change(Person, :count)
end
it "assigns @user" do
- get :create, invalid_params
+ get :create, params: invalid_params
expect(assigns(:user)).not_to be_nil
end
it "sets the flash error" do
- get :create, invalid_params
+ get :create, params: invalid_params
expect(flash[:error]).not_to be_blank
end
@@ -155,17 +155,17 @@ describe RegistrationsController, type: :controller do
code = InvitationCode.create(user: bob)
expect {
- get :create, invalid_params.merge(invite: {token: code.token})
+ get :create, params: invalid_params.merge(invite: {token: code.token})
}.not_to change { code.reload.count }
end
it "renders new" do
- get :create, invalid_params
+ get :create, params: invalid_params
expect(response).to render_template("registrations/new")
end
it "keeps invalid params in form" do
- get :create, invalid_params
+ get :create, params: invalid_params
expect(response.body).to match /jdoe@example.com/m
end
end
diff --git a/spec/controllers/report_controller_spec.rb b/spec/controllers/report_controller_spec.rb
index bb049243c..176a1d4f8 100644
--- a/spec/controllers/report_controller_spec.rb
+++ b/spec/controllers/report_controller_spec.rb
@@ -46,14 +46,14 @@ describe ReportController, type: :controller do
context "report offensive post" do
it "succeeds" do
- put :create, report: {item_id: @message.id, item_type: "Post", text: "offensive content"}
+ put :create, params: {report: {item_id: @message.id, item_type: "Post", text: "offensive content"}}
expect(response.status).to eq(200)
expect(Report.exists?(item_id: @message.id, item_type: "Post")).to be true
end
end
context "report offensive comment" do
it "succeeds" do
- put :create, report: {item_id: @comment.id, item_type: "Comment", text: "offensive content"}
+ put :create, params: {report: {item_id: @comment.id, item_type: "Comment", text: "offensive content"}}
expect(response.status).to eq(200)
expect(Report.exists?(item_id: @comment.id, item_type: "Comment")).to be true
end
@@ -63,14 +63,14 @@ describe ReportController, type: :controller do
describe "#update" do
context "mark post report as user" do
it "is behind redirect_unless_admin_or_moderator" do
- put :update, id: @message.id, type: "post"
+ put :update, params: {id: @message.id, type: "post"}
expect(response).to redirect_to stream_path
expect(Report.where(reviewed: false, item_id: @message.id, item_type: "Post")).to be_truthy
end
end
context "mark comment report as user" do
it "is behind redirect_unless_admin_or_moderator" do
- put :update, id: @comment.id, type: "comment"
+ put :update, params: {id: @comment.id, type: "comment"}
expect(response).to redirect_to stream_path
expect(Report.where(reviewed: false, item_id: @comment.id, item_type: "Comment")).to be_truthy
end
@@ -81,7 +81,7 @@ describe ReportController, type: :controller do
Role.add_admin(alice.person)
end
it "succeeds" do
- put :update, id: @message.id, type: "post"
+ put :update, params: {id: @message.id, type: "post"}
expect(response.status).to eq(302)
expect(Report.where(reviewed: true, item_id: @message.id, item_type: "Post")).to be_truthy
end
@@ -91,7 +91,7 @@ describe ReportController, type: :controller do
Role.add_admin(alice.person)
end
it "succeeds" do
- put :update, id: @comment.id, type: "comment"
+ put :update, params: {id: @comment.id, type: "comment"}
expect(response.status).to eq(302)
expect(Report.where(reviewed: true, item_id: @comment.id, item_type: "Comment")).to be_truthy
end
@@ -103,7 +103,7 @@ describe ReportController, type: :controller do
end
it "succeeds" do
- put :update, id: @message.id, type: "post"
+ put :update, params: {id: @message.id, type: "post"}
expect(response.status).to eq(302)
expect(Report.where(reviewed: true, item_id: @message.id, item_type: "Post")).to be_truthy
end
@@ -114,7 +114,7 @@ describe ReportController, type: :controller do
Role.add_moderator(alice.person)
end
it "succeeds" do
- put :update, id: @comment.id, type: "comment"
+ put :update, params: {id: @comment.id, type: "comment"}
expect(response.status).to eq(302)
expect(Report.where(reviewed: true, item_id: @comment.id, item_type: "Comment")).to be_truthy
end
@@ -124,14 +124,14 @@ describe ReportController, type: :controller do
describe "#destroy" do
context "destroy post as user" do
it "is behind redirect_unless_admin_or_moderator" do
- delete :destroy, id: @message.id, type: "post"
+ delete :destroy, params: {id: @message.id, type: "post"}
expect(response).to redirect_to stream_path
expect(Report.where(reviewed: false, item_id: @message.id, item_type: "Post")).to be_truthy
end
end
context "destroy comment as user" do
it "is behind redirect_unless_admin_or_moderator" do
- delete :destroy, id: @comment.id, type: "comment"
+ delete :destroy, params: {id: @comment.id, type: "comment"}
expect(response).to redirect_to stream_path
expect(Report.where(reviewed: false, item_id: @comment.id, item_type: "Comment")).to be_truthy
end
@@ -142,7 +142,7 @@ describe ReportController, type: :controller do
Role.add_admin(alice.person)
end
it "succeeds" do
- delete :destroy, id: @message.id, type: "post"
+ delete :destroy, params: {id: @message.id, type: "post"}
expect(response.status).to eq(302)
expect(Report.where(reviewed: true, item_id: @message.id, item_type: "Post")).to be_truthy
end
@@ -152,7 +152,7 @@ describe ReportController, type: :controller do
Role.add_admin(alice.person)
end
it "succeeds" do
- delete :destroy, id: @comment.id, type: "comment"
+ delete :destroy, params: {id: @comment.id, type: "comment"}
expect(response.status).to eq(302)
expect(Report.where(reviewed: true, item_id: @comment.id, item_type: "Comment")).to be_truthy
end
@@ -163,7 +163,7 @@ describe ReportController, type: :controller do
Role.add_moderator(alice.person)
end
it "succeeds" do
- delete :destroy, id: @message.id, type: "post"
+ delete :destroy, params: {id: @message.id, type: "post"}
expect(response.status).to eq(302)
expect(Report.where(reviewed: true, item_id: @message.id, item_type: "Post")).to be_truthy
end
@@ -173,7 +173,7 @@ describe ReportController, type: :controller do
Role.add_moderator(alice.person)
end
it "succeeds" do
- delete :destroy, id: @comment.id, type: "comment"
+ delete :destroy, params: {id: @comment.id, type: "comment"}
expect(response.status).to eq(302)
expect(Report.where(reviewed: true, item_id: @comment.id, item_type: "Comment")).to be_truthy
end
diff --git a/spec/controllers/reshares_controller_spec.rb b/spec/controllers/reshares_controller_spec.rb
index 38a65b94e..4682baa23 100644
--- a/spec/controllers/reshares_controller_spec.rb
+++ b/spec/controllers/reshares_controller_spec.rb
@@ -1,7 +1,7 @@
describe ResharesController, :type => :controller do
describe '#create' do
let(:post_request!) {
- post :create, :format => :json, :root_guid => @post_guid
+ post :create, params: {root_guid: @post_guid}, format: :json
}
before do
@@ -74,13 +74,13 @@ describe ResharesController, :type => :controller do
it "returns a 404 for a post not visible to the user" do
sign_in(eve, scope: :user)
expect {
- get :index, post_id: @post.id, format: :json
+ get :index, params: {post_id: @post.id}, format: :json
}.to raise_error(ActiveRecord::RecordNotFound)
end
it "returns an empty array for a post visible to the user" do
sign_in(bob, scope: :user)
- get :index, post_id: @post.id, format: :json
+ get :index, params: {post_id: @post.id}, format: :json
expect(JSON.parse(response.body)).to eq([])
end
end
@@ -93,12 +93,12 @@ describe ResharesController, :type => :controller do
it "returns an array of reshares for a post" do
bob.reshare!(@post)
- get :index, post_id: @post.id, format: :json
+ get :index, params: {post_id: @post.id}, format: :json
expect(JSON.parse(response.body).map {|h| h["id"] }).to eq(@post.reshares.map(&:id))
end
it "returns an empty array for a post with no reshares" do
- get :index, post_id: @post.id, format: :json
+ get :index, params: {post_id: @post.id}, format: :json
expect(JSON.parse(response.body)).to eq([])
end
end
diff --git a/spec/controllers/search_controller_spec.rb b/spec/controllers/search_controller_spec.rb
index ab90b253b..655cb86d4 100644
--- a/spec/controllers/search_controller_spec.rb
+++ b/spec/controllers/search_controller_spec.rb
@@ -7,7 +7,7 @@ describe SearchController, :type => :controller do
describe 'query is a person' do
it 'goes to people index page' do
- get :search, :q => 'eugene'
+ get :search, params: {q: "eugene"}
expect(response).to be_redirect
end
end
@@ -15,17 +15,17 @@ describe SearchController, :type => :controller do
describe 'query is a tag' do
it 'goes to a tag page' do
- get :search, :q => '#cats'
+ get :search, params: {q: "#cats"}
expect(response).to redirect_to(tag_path('cats'))
end
it 'removes dots from the query' do
- get :search, :q => '#cat.s'
+ get :search, params: {q: "#cat.s"}
expect(response).to redirect_to(tag_path('cats'))
end
it 'stay on the page if you search for the empty hash' do
- get :search, :q => '#'
+ get :search, params: {q: "#"}
expect(flash[:error]).to be_present
end
end
diff --git a/spec/controllers/services_controller_spec.rb b/spec/controllers/services_controller_spec.rb
index 75cff3391..9ad8e36aa 100644
--- a/spec/controllers/services_controller_spec.rb
+++ b/spec/controllers/services_controller_spec.rb
@@ -35,12 +35,12 @@ describe ServicesController, :type => :controller do
it 'creates a new service and associates it with the current user' do
expect {
- post :create, :provider => 'facebook'
+ post :create, params: {provider: "facebook"}
}.to change(user.services, :count).by(1)
end
it 'saves the provider' do
- post :create, :provider => 'facebook'
+ post :create, params: {provider: "facebook"}
expect(user.reload.services.first.class.name).to eq("Services::Facebook")
end
@@ -49,7 +49,7 @@ describe ServicesController, :type => :controller do
it "imports the profile photo from the service" do
expect(Workers::FetchProfilePhoto).to receive(:perform_async)
- post :create, :provider => 'facebook'
+ post :create, params: {provider: "facebook"}
end
end
@@ -58,12 +58,12 @@ describe ServicesController, :type => :controller do
it 'doesnt create a new service' do
service_count = Service.count
- post :create, :provider => 'twitter'
+ post :create, params: {provider: "twitter"}
expect(Service.count).to eq(service_count)
end
it 'flashes an already_authorized error with the diaspora handle for the user' do
- post :create, :provider => 'twitter'
+ post :create, params: {provider: "twitter"}
expect(flash[:error].include?(user.profile.diaspora_handle)).to be true
expect(flash[:error].include?( 'already authorized' )).to be true
end
@@ -84,12 +84,12 @@ describe ServicesController, :type => :controller do
it 'doesnt create a new service' do
service_count = Service.count
- post :create, :provider => 'twitter'
+ post :create, params: {provider: "twitter"}
expect(Service.count).to eq(service_count)
end
it 'flashes an read-only access error' do
- post :create, :provider => 'twitter'
+ post :create, params: {provider: "twitter"}
expect(flash[:error].include?( 'Access level is read-only' )).to be true
end
end
@@ -103,7 +103,7 @@ describe ServicesController, :type => :controller do
it "doesn't break when twitter-specific extras aren't available in omniauth hash" do
expect {
- post :create, :provider => 'facebook'
+ post :create, params: {provider: "facebook"}
}.to change(user.services, :count).by(1)
end
end
@@ -121,7 +121,7 @@ describe ServicesController, :type => :controller do
expect(Workers::FetchProfilePhoto).not_to receive(:perform_async)
- post :create, :provider => 'twitter'
+ post :create, params: {provider: "twitter"}
end
it 'queues a job to save user photo if the photo does not exist' do
@@ -129,7 +129,7 @@ describe ServicesController, :type => :controller do
expect(Workers::FetchProfilePhoto).to receive(:perform_async).with(user.id, anything(), "https://service.com/fallback_lowres.jpg")
- post :create, :provider => 'twitter'
+ post :create, params: {provider: "twitter"}
end
end
end
@@ -141,7 +141,7 @@ describe ServicesController, :type => :controller do
it 'destroys a service selected by id' do
expect{
- delete :destroy, :id => @service1.id
+ delete :destroy, params: {id: @service1.id}
}.to change(user.services, :count).by(-1)
end
end
diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb
index 55ae17bae..69bbf510c 100644
--- a/spec/controllers/sessions_controller_spec.rb
+++ b/spec/controllers/sessions_controller_spec.rb
@@ -15,14 +15,14 @@ describe SessionsController, type: :controller do
describe "#create" do
it "redirects to /stream for a non-mobile user" do
- post :create, {"user" => {"remember_me" => "0", "username" => @user.username, "password" => "evankorth"}}
+ post :create, params: {user: {remember_me: "0", username: @user.username, password: "evankorth"}}
expect(response).to be_redirect
expect(response.location).to match /^#{stream_url}\??$/
end
it "redirects to /stream for a mobile user" do
request.headers["X_MOBILE_DEVICE"] = true
- post :create, {"user" => {"remember_me" => "0", "username" => @user.username, "password" => "evankorth"}}
+ post :create, params: {user: {remember_me: "0", username: @user.username, password: "evankorth"}}
expect(response).to be_redirect
expect(response.location).to match /^#{stream_url}\??$/
end
diff --git a/spec/controllers/share_visibilities_controller_spec.rb b/spec/controllers/share_visibilities_controller_spec.rb
index 30c0151e9..f70a50ea3 100644
--- a/spec/controllers/share_visibilities_controller_spec.rb
+++ b/spec/controllers/share_visibilities_controller_spec.rb
@@ -14,13 +14,13 @@ describe ShareVisibilitiesController, :type => :controller do
end
it 'succeeds' do
- put :update, :format => :js, :id => 42, :post_id => @status.id
+ put :update, params: {id: 42, post_id: @status.id}, format: :js
expect(response).to be_success
end
it 'it calls toggle_hidden_shareable' do
expect(@controller.current_user).to receive(:toggle_hidden_shareable).with(an_instance_of(StatusMessage))
- put :update, :format => :js, :id => 42, :post_id => @status.id
+ put :update, params: {id: 42, post_id: @status.id}, format: :js
end
end
@@ -31,14 +31,14 @@ describe ShareVisibilitiesController, :type => :controller do
it "raises an error" do
expect {
- put :update, format: :js, id: 42, post_id: @status.id
+ put :update, params: {id: 42, post_id: @status.id}, format: :js
}.to raise_error ActiveRecord::RecordNotFound
end
it "it doesn't call toggle_hidden_shareable" do
expect(@controller.current_user).not_to receive(:toggle_hidden_shareable).with(an_instance_of(StatusMessage))
begin
- put :update, format: :js, id: 42, post_id: @status.id
+ put :update, params: {id: 42, post_id: @status.id}, format: :js
rescue ActiveRecord::RecordNotFound
end
end
diff --git a/spec/controllers/status_messages_controller_spec.rb b/spec/controllers/status_messages_controller_spec.rb
index 62fba474c..8b99c04c2 100644
--- a/spec/controllers/status_messages_controller_spec.rb
+++ b/spec/controllers/status_messages_controller_spec.rb
@@ -27,16 +27,18 @@ describe StatusMessagesController, :type => :controller do
end
it 'accepts get params' do
- get :bookmarklet, { url: 'https://www.youtube.com/watch?v=0Bmhjf0rKe8',
- title: 'Surprised Kitty',
- notes: 'cute kitty' }
+ get :bookmarklet, params: {
+ url: "https://www.youtube.com/watch?v=0Bmhjf0rKe8",
+ title: "Surprised Kitty",
+ notes: "cute kitty"
+ }
expect(response).to be_success
end
end
describe '#new' do
it 'succeeds' do
- get :new, :person_id => bob.person.id
+ get :new, params: {person_id: bob.person.id}
expect(response).to be_success
end
@@ -55,43 +57,31 @@ describe StatusMessagesController, :type => :controller do
}
}
- it 'creates with valid html' do
- post :create, status_message_hash
- expect(response.status).to eq(302)
- expect(response).to be_redirect
- end
-
- it 'creates with invalid html' do
- post :create, status_message_hash.merge(:status_message => { :text => "0123456789" * 7000 })
- expect(response.status).to eq(302)
- expect(response).to be_redirect
- end
-
it 'creates with valid json' do
- post :create, status_message_hash.merge(:format => 'json')
+ post :create, params: status_message_hash, format: :json
expect(response.status).to eq(201)
end
it 'creates with invalid json' do
- post :create, status_message_hash.merge(:status_message => { :text => "0123456789" * 7000 }, :format => 'json')
+ post :create, params: status_message_hash.merge(status_message: {text: "0123456789" * 7000}), format: :json
expect(response.status).to eq(403)
end
it 'creates with valid mobile' do
- post :create, status_message_hash.merge(:format => 'mobile')
+ post :create, params: status_message_hash, format: :mobile
expect(response.status).to eq(302)
expect(response).to be_redirect
end
it 'creates with invalid mobile' do
- post :create, status_message_hash.merge(:status_message => { :text => "0123456789" * 7000 }, :format => 'mobile')
+ post :create, params: status_message_hash.merge(status_message: {text: "0123456789" * 7000}), format: :mobile
expect(response.status).to eq(302)
expect(response).to be_redirect
end
it 'removes getting started from new users' do
expect(@controller).to receive(:remove_getting_started)
- post :create, status_message_hash
+ post :create, params: status_message_hash
end
context "with aspect_ids" do
@@ -100,43 +90,43 @@ describe StatusMessagesController, :type => :controller do
end
it "takes one aspect as array in aspect_ids" do
- post :create, status_message_hash
- expect(response.status).to eq(302)
+ post :create, params: status_message_hash, format: :json
+ expect(response.status).to eq(201)
status_message = StatusMessage.find_by_text(text)
- expect(status_message.aspect_visibilities.map(&:aspect)).to eq([@aspect1])
+ expect(status_message.aspect_visibilities.map(&:aspect)).to eq([@aspect1]), format: :json
end
it "takes one aspect as string in aspect_ids" do
- post :create, status_message_hash.merge(aspect_ids: @aspect1.id.to_s)
- expect(response.status).to eq(302)
+ post :create, params: status_message_hash.merge(aspect_ids: @aspect1.id.to_s), format: :json
+ expect(response.status).to eq(201)
status_message = StatusMessage.find_by_text(text)
expect(status_message.aspect_visibilities.map(&:aspect)).to eq([@aspect1])
end
it "takes public as array in aspect_ids" do
- post :create, status_message_hash.merge(aspect_ids: ["public"])
- expect(response.status).to eq(302)
+ post :create, params: status_message_hash.merge(aspect_ids: ["public"]), format: :json
+ expect(response.status).to eq(201)
status_message = StatusMessage.find_by_text(text)
expect(status_message.public).to be_truthy
end
it "takes public as string in aspect_ids" do
- post :create, status_message_hash.merge(aspect_ids: "public")
- expect(response.status).to eq(302)
+ post :create, params: status_message_hash.merge(aspect_ids: "public"), format: :json
+ expect(response.status).to eq(201)
status_message = StatusMessage.find_by_text(text)
expect(status_message.public).to be_truthy
end
it "takes all_aspects as array in aspect_ids" do
- post :create, status_message_hash.merge(aspect_ids: ["all_aspects"])
- expect(response.status).to eq(302)
+ post :create, params: status_message_hash.merge(aspect_ids: ["all_aspects"]), format: :json
+ expect(response.status).to eq(201)
status_message = StatusMessage.find_by_text(text)
expect(status_message.aspect_visibilities.map(&:aspect)).to match_array([@aspect1, @aspect2])
end
it "takes all_aspects as string in aspect_ids" do
- post :create, status_message_hash.merge(aspect_ids: "all_aspects")
- expect(response.status).to eq(302)
+ post :create, params: status_message_hash.merge(aspect_ids: "all_aspects"), format: :json
+ expect(response.status).to eq(201)
status_message = StatusMessage.find_by_text(text)
expect(status_message.aspect_visibilities.map(&:aspect)).to match_array([@aspect1, @aspect2])
end
@@ -149,7 +139,7 @@ describe StatusMessagesController, :type => :controller do
status_message_hash[:services] = ['facebook']
service_types = Service.titles(status_message_hash[:services])
expect(alice).to receive(:dispatch_post).with(anything(), hash_including(:service_types => service_types))
- post :create, status_message_hash
+ post :create, params: status_message_hash
end
it "works if services is a string" do
@@ -157,12 +147,12 @@ describe StatusMessagesController, :type => :controller do
alice.services << s1
status_message_hash[:services] = "facebook"
expect(alice).to receive(:dispatch_post).with(anything(), hash_including(:service_types => ["Services::Facebook"]))
- post :create, status_message_hash
+ post :create, params: status_message_hash
end
it "doesn't overwrite author_id" do
status_message_hash[:status_message][:author_id] = bob.person.id
- post :create, status_message_hash
+ post :create, params: status_message_hash
new_message = StatusMessage.find_by_text(text)
expect(new_message.author_id).to eq(alice.person.id)
end
@@ -170,7 +160,7 @@ describe StatusMessagesController, :type => :controller do
it "doesn't overwrite id" do
old_status_message = alice.post(:status_message, :text => "hello", :to => @aspect1.id)
status_message_hash[:status_message][:id] = old_status_message.id
- post :create, status_message_hash
+ post :create, params: status_message_hash
expect(old_status_message.reload.text).to eq('hello')
end
@@ -178,18 +168,18 @@ describe StatusMessagesController, :type => :controller do
expect(alice).to receive(:dispatch_post) {|post, _opts|
expect(post.subscribers).to eq([bob.person])
}
- post :create, status_message_hash
+ post :create, params: status_message_hash
end
it 'respsects provider_display_name' do
status_message_hash.merge!(:aspect_ids => ['public'])
status_message_hash[:status_message].merge!(:provider_display_name => "mobile")
- post :create, status_message_hash
+ post :create, params: status_message_hash
expect(StatusMessage.first.provider_display_name).to eq('mobile')
end
it "has no participation" do
- post :create, status_message_hash
+ post :create, params: status_message_hash
new_message = StatusMessage.find_by_text(text)
expect(new_message.participations.count).to eq(0)
end
@@ -208,19 +198,19 @@ describe StatusMessagesController, :type => :controller do
it "will post a photo without text" do
@hash.delete :text
- post :create, @hash
- expect(response).to be_redirect
+ post :create, params: @hash, format: :json
+ expect(response.status).to eq(201)
end
it "attaches all referenced photos" do
- post :create, @hash
+ post :create, params: @hash, format: :json
status_message = StatusMessage.find_by_text(text)
expect(status_message.photos.map(&:id)).to match_array([@photo1, @photo2].map(&:id))
end
it "sets the pending bit of referenced photos" do
inlined_jobs do
- post :create, @hash
+ post :create, params: @hash, format: :json
end
expect(@photo1.reload.pending).to be false
diff --git a/spec/controllers/tags_controller_spec.rb b/spec/controllers/tags_controller_spec.rb
index 3b49bccbc..b62adc5b0 100644
--- a/spec/controllers/tags_controller_spec.rb
+++ b/spec/controllers/tags_controller_spec.rb
@@ -12,13 +12,13 @@ describe TagsController, :type => :controller do
end
it 'responds with json' do
- get :index, :q => "ra", :format => 'json'
+ get :index, params: {q: "ra"}, format: :json
#parse json
expect(response.body).to include("#rad")
end
it 'requires at least two characters' do
- get :index, :q => "c", :format => 'json'
+ get :index, params: {q: "c"}, format: :json
expect(response.body).not_to include("#cats")
end
@@ -28,7 +28,7 @@ describe TagsController, :type => :controller do
end
it 'does not allow json requestors to party' do
- get :index, :format => :json
+ get :index, format: :json
expect(response.status).to eq(422)
end
end
@@ -40,7 +40,7 @@ describe TagsController, :type => :controller do
end
it 'redirect to the downcase tag uri' do
- get :show, :name => 'DiasporaRocks!'
+ get :show, params: {name: "DiasporaRocks!"}
expect(response).to redirect_to(:action => :show, :name => 'diasporarocks!')
end
end
@@ -53,7 +53,7 @@ describe TagsController, :type => :controller do
end
it 'includes the tagged user' do
- get :show, :name => 'cats'
+ get :show, params: {name: "cats"}
expect(response.body).to include(bob.diaspora_handle)
end
end
@@ -69,40 +69,40 @@ describe TagsController, :type => :controller do
end
it 'assigns a Stream::Tag object with the current_user' do
- get :show, :name => 'yes'
+ get :show, params: {name: "yes"}
expect(assigns[:stream].user).to eq(alice)
end
it 'succeeds' do
- get :show, :name => 'hellyes'
+ get :show, params: {name: "hellyes"}
expect(response.status).to eq(200)
end
it 'includes the tagged post' do
- get :show, :name => 'foo'
+ get :show, params: {name: "foo"}
expect(assigns[:stream].posts.first.text).to include("tagged post")
end
it 'includes comments of the tagged post' do
alice.comment!(@post, "comment on a tagged post")
- get :show, :name => 'foo', :format => 'json'
+ get :show, params: {name: "foo"}, format: :json
expect(response.body).to include("comment on a tagged post")
end
end
context "not signed in" do
it 'assigns a Stream::Tag object with no user' do
- get :show, :name => 'yes'
+ get :show, params: {name: "yes"}
expect(assigns[:stream].user).to be_nil
end
it 'succeeds' do
- get :show, :name => 'hellyes'
+ get :show, params: {name: "hellyes"}
expect(response.status).to eq(200)
end
it 'succeeds with mobile' do
- get :show, :name => 'foo', :format => :mobile
+ get :show, params: {name: "foo"}, format: :mobile
expect(response).to be_success
end
@@ -113,7 +113,7 @@ describe TagsController, :type => :controller do
public: true,
created_at: @post.created_at - 1.day
)
- get :show, name: "what", max_time: @post.created_at, format: :json
+ get :show, params: {name: "what", max_time: @post.created_at.to_i}, format: :json
expect(JSON.parse(response.body).size).to be(1)
expect(JSON.parse(response.body).first["guid"]).to eq(post2.guid)
end
@@ -122,7 +122,7 @@ describe TagsController, :type => :controller do
it "includes the correct meta tags" do
tag_url = tag_url "yes", host: AppConfig.pod_uri.host, port: AppConfig.pod_uri.port
- get :show, name: "yes"
+ get :show, params: {name: "yes"}
expect(response.body).to include('<meta name="keywords" content="yes" />')
expect(response.body).to include(
diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb
index ad8a2b70e..e3ef6a785 100644
--- a/spec/controllers/users_controller_spec.rb
+++ b/spec/controllers/users_controller_spec.rb
@@ -58,26 +58,26 @@ describe UsersController, :type => :controller do
end
it "contains the text" do
- get :public, username: @user.username, format: :atom
+ get :public, params: {username: @user.username}, format: :atom
doc = Nokogiri::XML(response.body)
expect(doc.css("entry content")[0].content).to eq(@sm.message.markdownified(disable_hovercards: true))
end
it "contains the title" do
- get :public, username: @user.username, format: :atom
+ get :public, params: {username: @user.username}, format: :atom
doc = Nokogiri::XML(response.body)
expect(doc.css("entry title")[0].content).to eq(post_page_title(@sm))
end
it "contains the author" do
- get :public, username: @user.username, format: :atom
+ get :public, params: {username: @user.username}, format: :atom
doc = Nokogiri::XML(response.body)
expect(doc.css("entry author name")[0].content).to eq(@sm.author_name)
end
it "contains the original author for reshares" do
FactoryGirl.create(:reshare, root: @sm, author: bob.person)
- get :public, username: bob.username, format: :atom
+ get :public, params: {username: bob.username}, format: :atom
doc = Nokogiri::XML(response.body)
expect(doc.css("entry author name")[0].content).to eq(@sm.author_name)
end
@@ -85,7 +85,7 @@ describe UsersController, :type => :controller do
it 'includes reshares in the atom feed' do
reshare = FactoryGirl.create(:reshare, :author => @user.person)
- get :public, :username => @user.username, :format => :atom
+ get :public, params: {username: @user.username}, format: :atom
expect(response.body).to include reshare.root.text
end
@@ -93,17 +93,17 @@ describe UsersController, :type => :controller do
post = FactoryGirl.create(:status_message, :public => true);
reshare = FactoryGirl.create(:reshare, :root => post, :author => @user.person)
post.delete
- get :public, :username => @user.username, :format => :atom
+ get :public, params: {username: @user.username}, format: :atom
expect(response.code).to eq('200')
end
it 'redirects to a profile page if html is requested' do
- get :public, :username => @user.username
+ get :public, params: {username: @user.username}
expect(response).to be_redirect
end
it 'redirects to a profile page if mobile is requested' do
- get :public, :username => @user.username, :format => :mobile
+ get :public, params: {username: @user.username}, format: :mobile
expect(response).to be_redirect
end
end
@@ -116,12 +116,12 @@ describe UsersController, :type => :controller do
it "doesn't overwrite random attributes" do
expect {
- put :update, @params
+ put :update, params: @params
}.not_to change(@user, :diaspora_handle)
end
it 'renders the user edit page' do
- put :update, @params
+ put :update, params: @params
expect(response).to render_template('edit')
end
@@ -139,7 +139,7 @@ describe UsersController, :type => :controller do
it "uses devise's update with password" do
expect(@user).to receive(:update_with_password).with(hash_including(password_params))
allow(@controller).to receive(:current_user).and_return(@user)
- put :update, params
+ put :update, params: params
end
end
@@ -148,9 +148,7 @@ describe UsersController, :type => :controller do
old_language = 'en'
@user.language = old_language
@user.save
- put(:update, :id => @user.id, :user =>
- { :language => "fr"}
- )
+ put :update, params: {id: @user.id, user: {language: "fr"}}
@user.reload
expect(@user.language).not_to eq(old_language)
end
@@ -161,7 +159,7 @@ describe UsersController, :type => :controller do
old_color_theme = "original"
@user.color_theme = old_color_theme
@user.save
- put(:update, id: @user.id, user: {color_theme: "dark_green"})
+ put :update, params: {id: @user.id, user: {color_theme: "dark_green"}}
@user.reload
expect(@user.color_theme).not_to eq(old_color_theme)
end
@@ -170,68 +168,72 @@ describe UsersController, :type => :controller do
describe 'email' do
it 'disallow the user to change his new (unconfirmed) mail when it is the same as the old' do
@user.email = "my@newemail.com"
- put(:update, :id => @user.id, :user => { :email => "my@newemail.com"})
+ put :update, params: {id: @user.id, user: {email: "my@newemail.com"}}
@user.reload
expect(@user.unconfirmed_email).to eql(nil)
end
it 'allow the user to change his (unconfirmed) email' do
- put(:update, :id => @user.id, :user => { :email => "my@newemail.com"})
+ put :update, params: {id: @user.id, user: {email: "my@newemail.com"}}
@user.reload
expect(@user.unconfirmed_email).to eql("my@newemail.com")
end
it 'informs the user about success' do
- put(:update, :id => @user.id, :user => { :email => "my@newemail.com"})
+ put :update, params: {id: @user.id, user: {email: "my@newemail.com"}}
expect(request.flash[:notice]).to eql(I18n.t('users.update.unconfirmed_email_changed'))
expect(request.flash[:error]).to be_blank
end
it 'informs the user about failure' do
- put(:update, id: @user.id, user: {email: "mynewemailcom"})
+ put :update, params: {id: @user.id, user: {email: "mynewemailcom"}}
expect(request.flash[:error]).to eql(I18n.t('users.update.unconfirmed_email_not_changed'))
expect(request.flash[:notice]).to be_blank
end
it 'allow the user to change his (unconfirmed) email to blank (= abort confirmation)' do
- put(:update, :id => @user.id, :user => { :email => ""})
+ put :update, params: {id: @user.id, user: {email: ""}}
@user.reload
expect(@user.unconfirmed_email).to eql(nil)
end
it 'sends out activation email on success' do
expect(Workers::Mail::ConfirmEmail).to receive(:perform_async).with(@user.id).once
- put(:update, :id => @user.id, :user => { :email => "my@newemail.com"})
+ put :update, params: {id: @user.id, user: {email: "my@newemail.com"}}
end
it "saves unconfirmed_email when podmail is disabled" do
AppConfig.mail.enable = false
- put(:update, id: @user.id, user: {email: "my@newemail.com"})
+ put :update, params: {id: @user.id, user: {email: "my@newemail.com"}}
@user.reload
expect(@user.email).to eql("my@newemail.com")
end
end
- describe 'email settings' do
- it 'lets the user turn off mail' do
- par = {:id => @user.id, :user => {:email_preferences => {'mentioned' => 'true'}}}
- expect{
- put :update, par
- }.to change(@user.user_preferences, :count).by(1)
- end
+ describe "email settings" do
+ UserPreference::VALID_EMAIL_TYPES.each do |email_type|
+ context "for #{email_type}" do
+ it "lets the user turn off mail" do
+ par = {id: @user.id, user: {email_preferences: {email_type => "true"}}}
+ expect {
+ put :update, params: par
+ }.to change(@user.user_preferences, :count).by(1)
+ end
- it 'lets the user get mail again' do
- @user.user_preferences.create(:email_type => 'mentioned')
- par = {:id => @user.id, :user => {:email_preferences => {'mentioned' => 'false'}}}
- expect{
- put :update, par
- }.to change(@user.user_preferences, :count).by(-1)
+ it "lets the user get mail again" do
+ @user.user_preferences.create(email_type: email_type)
+ par = {id: @user.id, user: {email_preferences: {email_type => "false"}}}
+ expect {
+ put :update, params: par
+ }.to change(@user.user_preferences, :count).by(-1)
+ end
+ end
end
end
describe 'getting started' do
it 'can be reenabled' do
- put :update, user: {getting_started: true}
+ put :update, params: {user: {getting_started: true}}
expect(@user.reload.getting_started?).to be true
end
end
@@ -246,32 +248,32 @@ describe UsersController, :type => :controller do
describe '#edit' do
it "returns a 200" do
- get 'edit', :id => @user.id
+ get :edit, params: {id: @user.id}
expect(response.status).to eq(200)
end
it 'displays community spotlight checkbox' do
AppConfig.settings.community_spotlight.enable = true
- get 'edit', :id => @user.id
+ get :edit, params: {id: @user.id}
expect(response.body).to include('input name="user[show_community_spotlight_in_stream]"')
end
it 'hides community spotlight checkbox' do
AppConfig.settings.community_spotlight = false
- get 'edit', :id => @user.id
+ get :edit, params: {id: @user.id}
expect(response.body).not_to include('input name="user[show_community_spotlight_in_stream]"')
end
it 'set @email_pref to false when there is a user pref' do
@user.user_preferences.create(:email_type => 'mentioned')
- get 'edit', :id => @user.id
+ get :edit, params: {id: @user.id}
expect(assigns[:email_prefs]['mentioned']).to be false
end
it "does not allow token auth" do
sign_out :user
bob.reset_authentication_token!
- get :edit, :auth_token => bob.authentication_token
+ get :edit, params: {auth_token: bob.authentication_token}
expect(response).to redirect_to new_user_session_path
end
end
@@ -279,17 +281,17 @@ describe UsersController, :type => :controller do
describe '#destroy' do
it 'does nothing if the password does not match' do
expect(Workers::DeleteAccount).not_to receive(:perform_async)
- delete :destroy, :user => { :current_password => "stuff" }
+ delete :destroy, params: {user: {current_password: "stuff"}}
end
it 'closes the account' do
expect(alice).to receive(:close_account!)
- delete :destroy, :user => { :current_password => "bluepin7" }
+ delete :destroy, params: {user: {current_password: "bluepin7"}}
end
it 'enqueues a delete job' do
expect(Workers::DeleteAccount).to receive(:perform_async).with(anything)
- delete :destroy, :user => { :current_password => "bluepin7" }
+ delete :destroy, params: {user: {current_password: "bluepin7"}}
end
end
@@ -299,12 +301,12 @@ describe UsersController, :type => :controller do
end
it 'redirects to to the user edit page' do
- get 'confirm_email', :token => @user.confirm_email_token
+ get :confirm_email, params: {token: @user.confirm_email_token}
expect(response).to redirect_to edit_user_path
end
it 'confirms email' do
- get 'confirm_email', :token => @user.confirm_email_token
+ get :confirm_email, params: {token: @user.confirm_email_token}
@user.reload
expect(@user.email).to eql('my@newemail.com')
expect(request.flash[:notice]).to eql(I18n.t('users.confirm_email.email_confirmed', :email => 'my@newemail.com'))
@@ -312,7 +314,7 @@ describe UsersController, :type => :controller do
end
it 'does NOT confirm email with wrong token' do
- get 'confirm_email', :token => @user.confirm_email_token.reverse
+ get :confirm_email, params: {token: @user.confirm_email_token.reverse}
@user.reload
expect(@user.email).not_to eql('my@newemail.com')
expect(request.flash[:error]).to eql(I18n.t('users.confirm_email.email_not_confirmed'))
@@ -327,7 +329,7 @@ describe UsersController, :type => :controller do
end
it 'does not fail miserably on mobile' do
- get :getting_started, :format => :mobile
+ get :getting_started, format: :mobile
expect(response).to be_success
end
diff --git a/spec/factories.rb b/spec/factories.rb
index 2f8b37d30..32a322933 100644
--- a/spec/factories.rb
+++ b/spec/factories.rb
@@ -10,8 +10,7 @@ def r_str
SecureRandom.hex(3)
end
-require "diaspora_federation/test"
-DiasporaFederation::Test::Factories.federation_factories
+require "diaspora_federation/test/factories"
FactoryGirl.define do
factory :profile do
@@ -32,12 +31,17 @@ FactoryGirl.define do
end
factory(:person, aliases: %i(author)) do
+ transient do
+ first_name nil
+ end
+
sequence(:diaspora_handle) {|n| "bob-person-#{n}#{r_str}@example.net" }
pod { Pod.find_or_create_by(url: "http://example.net") }
serialized_public_key OpenSSL::PKey::RSA.generate(1024).public_key.export
- after(:build) do |person|
+ after(:build) do |person, evaluator|
unless person.profile.first_name.present?
person.profile = FactoryGirl.build(:profile, person: person)
+ person.profile.first_name = evaluator.first_name if evaluator.first_name
end
end
after(:create) do |person|
@@ -47,9 +51,11 @@ FactoryGirl.define do
factory :account_deletion do
association :person
- after(:build) do |delete|
- delete.diaspora_handle = delete.person.diaspora_handle
- end
+ end
+
+ factory :account_migration do
+ association :old_person, factory: :person
+ association :new_person, factory: :person
end
factory :like do
@@ -76,8 +82,17 @@ FactoryGirl.define do
end
end
- factory :user_with_aspect, :parent => :user do
- after(:create) { |u| FactoryGirl.create(:aspect, :user => u) }
+ factory :user_with_aspect, parent: :user do
+ transient do
+ friends []
+ end
+
+ after(:create) do |user, evaluator|
+ FactoryGirl.create(:aspect, user: user)
+ evaluator.friends.each do |friend|
+ connect_users_with_aspects(user, friend)
+ end
+ end
end
factory :aspect do
@@ -116,8 +131,8 @@ FactoryGirl.define do
factory(:status_message_in_aspect) do
public false
+ author { FactoryGirl.create(:user_with_aspect).person }
after(:build) do |sm|
- sm.author = FactoryGirl.create(:user_with_aspect).person
sm.aspects << sm.author.owner.aspects.first
end
end
@@ -135,10 +150,15 @@ FactoryGirl.define do
end
end
+ factory(:share_visibility) do
+ user
+ association :shareable, factory: :status_message
+ end
+
factory(:location) do
- address "Fernsehturm Berlin, Berlin, Germany"
- lat 52.520645
- lng 13.409779
+ sequence(:address) {|n| "Fernsehturm Berlin, #{n}, Berlin, Germany" }
+ sequence(:lat) {|n| 52.520645 + 0.0000001 * n }
+ sequence(:lng) {|n| 13.409779 + 0.0000001 * n }
end
factory :participation do
@@ -212,13 +232,8 @@ FactoryGirl.define do
sequence(:uid) { |token| "00000#{token}" }
sequence(:access_token) { |token| "12345#{token}" }
sequence(:access_secret) { |token| "98765#{token}" }
- end
- factory :service_user do
- sequence(:uid) { |id| "a#{id}"}
- sequence(:name) { |num| "Rob Fergus the #{num.ordinalize}" }
- association :service
- photo_url "/assets/user/adams.jpg"
+ user
end
factory :pod do
@@ -228,20 +243,29 @@ FactoryGirl.define do
factory(:comment) do
sequence(:text) {|n| "#{n} cats"}
- association(:author, :factory => :person)
- association(:post, :factory => :status_message)
+ association(:author, factory: :person)
+ association(:post, factory: :status_message)
end
- factory(:notification) do
+ factory(:notification, class: Notifications::AlsoCommented) do
association :recipient, :factory => :user
association :target, :factory => :comment
- type 'Notifications::AlsoCommented'
after(:build) do |note|
note.actors << FactoryGirl.build(:person)
end
end
+ factory(:notification_mentioned_in_comment, class: Notification) do
+ association :recipient, factory: :user
+ type "Notifications::MentionedInComment"
+
+ after(:build) do |note|
+ note.actors << FactoryGirl.build(:person)
+ note.target = FactoryGirl.create :mention_in_comment, person: note.recipient.person
+ end
+ end
+
factory(:tag, :class => ActsAsTaggableOn::Tag) do
name "partytimeexcellent"
end
@@ -271,8 +295,13 @@ FactoryGirl.define do
end
factory(:mention) do
- association(:person, :factory => :person)
- association(:post, :factory => :status_message)
+ association(:person, factory: :person)
+ association(:mentions_container, factory: :status_message)
+ end
+
+ factory(:mention_in_comment, class: Mention) do
+ association(:person, factory: :person)
+ association(:mentions_container, factory: :comment)
end
factory(:conversation) do
@@ -315,6 +344,11 @@ FactoryGirl.define do
additional_data { {"new_property" => "some text"} }
end
+ factory :role do
+ association :person
+ name "moderator"
+ end
+
factory(:poll_participation_signature) do
author_signature "some signature"
association :signature_order, order: "guid parent_guid author poll_answer_guid new_property"
@@ -325,38 +359,29 @@ FactoryGirl.define do
text SecureRandom.hex(1000)
end
- factory(:status, :parent => :status_message)
+ factory(:status, parent: :status_message)
- factory :o_auth_application, class: Api::OpenidConnect::OAuthApplication do
- client_name "Diaspora Test Client"
- redirect_uris %w(http://localhost:3000/)
+ factory :block do
+ user
+ person
end
- factory :o_auth_application_with_image, class: Api::OpenidConnect::OAuthApplication do
- client_name "Diaspora Test Client"
- redirect_uris %w(http://localhost:3000/)
- logo_uri "/assets/user/default.png"
+ factory :report do
+ user
+ association :item, factory: :status_message
+ text "offensive content"
end
- factory :o_auth_application_with_ppid, class: Api::OpenidConnect::OAuthApplication do
- client_name "Diaspora Test Client"
+ factory :o_auth_application, class: Api::OpenidConnect::OAuthApplication do
+ client_name { "Diaspora Test Client #{r_str}" }
redirect_uris %w(http://localhost:3000/)
- ppid true
- sector_identifier_uri "https://example.com/uri"
end
- factory :o_auth_application_with_ppid_with_specific_id, class: Api::OpenidConnect::OAuthApplication do
- client_name "Diaspora Test Client"
- redirect_uris %w(http://localhost:3000/)
+ factory :o_auth_application_with_ppid, parent: :o_auth_application do
ppid true
sector_identifier_uri "https://example.com/uri"
end
- factory :o_auth_application_with_multiple_redirects, class: Api::OpenidConnect::OAuthApplication do
- client_name "Diaspora Test Client"
- redirect_uris %w(http://localhost:3000/ http://localhost/)
- end
-
factory :o_auth_application_with_xss, class: Api::OpenidConnect::OAuthApplication do
client_name "<script>alert(0);</script>"
redirect_uris %w(http://localhost:3000/)
diff --git a/spec/federation_callbacks_spec.rb b/spec/federation_callbacks_spec.rb
index 253484ded..7a5ddb58e 100644
--- a/spec/federation_callbacks_spec.rb
+++ b/spec/federation_callbacks_spec.rb
@@ -6,15 +6,20 @@ describe "diaspora federation callbacks" do
person = alice.person
wf = DiasporaFederation.callbacks.trigger(:fetch_person_for_webfinger, alice.diaspora_handle)
expect(wf.acct_uri).to eq("acct:#{person.diaspora_handle}")
- expect(wf.alias_url).to eq(AppConfig.url_to("/people/#{person.guid}"))
expect(wf.hcard_url).to eq(AppConfig.url_to("/hcard/users/#{person.guid}"))
expect(wf.seed_url).to eq(AppConfig.pod_uri)
expect(wf.profile_url).to eq(person.profile_url)
expect(wf.atom_url).to eq(person.atom_url)
expect(wf.salmon_url).to eq(person.receive_url)
expect(wf.subscribe_url).to eq(AppConfig.url_to("/people?q={uri}"))
- expect(wf.guid).to eq(person.guid)
- expect(wf.public_key).to eq(person.serialized_public_key)
+ end
+
+ it "contains the OpenID issuer" do
+ wf = DiasporaFederation.callbacks.trigger(:fetch_person_for_webfinger, alice.diaspora_handle)
+ links = wf.additional_data[:links]
+ openid_issuer = links.find {|l| l[:rel] == OpenIDConnect::Discovery::Provider::Issuer::REL_VALUE }
+ expect(openid_issuer).not_to be_nil
+ expect(openid_issuer[:href]).to eq(Rails.application.routes.url_helpers.root_url)
end
it "returns nil if the person was not found" do
@@ -203,7 +208,7 @@ describe "diaspora federation callbacks" do
it "returns nil for an unknown id" do
expect(
- DiasporaFederation.callbacks.trigger(:fetch_private_key, FactoryGirl.generate(:diaspora_id))
+ DiasporaFederation.callbacks.trigger(:fetch_private_key, Fabricate.sequence(:diaspora_id))
).to be_nil
end
end
@@ -225,7 +230,7 @@ describe "diaspora federation callbacks" do
end
it "returns nil for an unknown person" do
- diaspora_id = FactoryGirl.generate(:diaspora_id)
+ diaspora_id = Fabricate.sequence(:diaspora_id)
expect(Person).to receive(:find_or_fetch_by_identifier).with(diaspora_id)
.and_raise(DiasporaFederation::Discovery::DiscoveryError)
@@ -295,7 +300,7 @@ describe "diaspora federation callbacks" do
it "returns nil for a non-existing guid" do
expect(
- DiasporaFederation.callbacks.trigger(:fetch_related_entity, "Post", FactoryGirl.generate(:guid))
+ DiasporaFederation.callbacks.trigger(:fetch_related_entity, "Post", Fabricate.sequence(:guid))
).to be_nil
end
end
@@ -337,7 +342,7 @@ describe "diaspora federation callbacks" do
describe ":receive_entity" do
it "receives an AccountDeletion" do
- account_deletion = FactoryGirl.build(:account_deletion_entity, author: remote_person.diaspora_handle)
+ account_deletion = Fabricate(:account_deletion_entity, author: remote_person.diaspora_handle)
expect(Diaspora::Federation::Receive).to receive(:account_deletion).with(account_deletion)
expect(Workers::ReceiveLocal).not_to receive(:perform_async)
@@ -346,7 +351,7 @@ describe "diaspora federation callbacks" do
end
it "receives a Retraction" do
- retraction = FactoryGirl.build(:retraction_entity, author: remote_person.diaspora_handle)
+ retraction = Fabricate(:retraction_entity, author: remote_person.diaspora_handle)
expect(Diaspora::Federation::Receive).to receive(:retraction).with(retraction, 42)
expect(Workers::ReceiveLocal).not_to receive(:perform_async)
@@ -355,7 +360,7 @@ describe "diaspora federation callbacks" do
end
it "receives a entity" do
- received = FactoryGirl.build(:status_message_entity, author: remote_person.diaspora_handle)
+ received = Fabricate(:status_message_entity, author: remote_person.diaspora_handle)
persisted = FactoryGirl.create(:status_message)
expect(Diaspora::Federation::Receive).to receive(:perform).with(received).and_return(persisted)
@@ -365,7 +370,7 @@ describe "diaspora federation callbacks" do
end
it "calls schedule_check_if_needed on the senders pod" do
- received = FactoryGirl.build(:status_message_entity, author: remote_person.diaspora_handle)
+ received = Fabricate(:status_message_entity, author: remote_person.diaspora_handle)
persisted = FactoryGirl.create(:status_message)
expect(Person).to receive(:by_account_identifier).with(received.author).and_return(remote_person)
@@ -377,7 +382,7 @@ describe "diaspora federation callbacks" do
end
it "receives a entity for a recipient" do
- received = FactoryGirl.build(:status_message_entity, author: remote_person.diaspora_handle)
+ received = Fabricate(:status_message_entity, author: remote_person.diaspora_handle)
persisted = FactoryGirl.create(:status_message)
expect(Diaspora::Federation::Receive).to receive(:perform).with(received).and_return(persisted)
@@ -387,7 +392,7 @@ describe "diaspora federation callbacks" do
end
it "does not trigger a ReceiveLocal job if Receive.perform returned nil" do
- received = FactoryGirl.build(:status_message_entity, author: remote_person.diaspora_handle)
+ received = Fabricate(:status_message_entity, author: remote_person.diaspora_handle)
expect(Diaspora::Federation::Receive).to receive(:perform).with(received).and_return(nil)
expect(Workers::ReceiveLocal).not_to receive(:perform_async)
@@ -460,7 +465,7 @@ describe "diaspora federation callbacks" do
end
it "forwards the DiscoveryError" do
- diaspora_id = FactoryGirl.generate(:diaspora_id)
+ diaspora_id = Fabricate.sequence(:diaspora_id)
expect(Person).to receive(:find_or_fetch_by_identifier).with(diaspora_id)
.and_raise(DiasporaFederation::Discovery::DiscoveryError)
diff --git a/spec/helper_methods.rb b/spec/helper_methods.rb
index ad4371a34..720f28058 100644
--- a/spec/helper_methods.rb
+++ b/spec/helper_methods.rb
@@ -3,10 +3,12 @@ require Rails.root.join("spec", "support", "inlined_jobs")
module HelperMethods
def connect_users_with_aspects(u1, u2)
- aspect1 = u1.aspects.length == 1 ? u1.aspects.first : u1.aspects.where(:name => "Besties").first
- aspect2 = u2.aspects.length == 1 ? u2.aspects.first : u2.aspects.where(:name => "Besties").first
+ aspect1, aspect2 = [u1, u2].map do |user|
+ user.aspects.where(name: "Besties").first.presence || user.aspects.first
+ end
connect_users(u1, aspect1, u2, aspect2)
end
+
def connect_users(user1, aspect1, user2, aspect2)
user1.contacts.create!(:person => user2.person,
:aspects => [aspect1],
@@ -25,12 +27,12 @@ module HelperMethods
File.open(fixture_name)
end
- def create_conversation_with_message(sender, recipient_person, subject, text)
+ def create_conversation_with_message(sender_person, recipient_person, subject, text)
create_hash = {
- :author => sender.person,
- :participant_ids => [sender.person.id, recipient_person.id],
- :subject => subject,
- :messages_attributes => [ {:author => sender.person, :text => text} ]
+ author: sender_person,
+ participant_ids: [sender_person.id, recipient_person.id],
+ subject: subject,
+ messages_attributes: [{author: sender_person, text: text}]
}
Conversation.create!(create_hash)
@@ -42,4 +44,18 @@ module HelperMethods
body.close if body.respond_to?(:close) # avoids deadlock after 3 tests
ActionDispatch::TestResponse.new(status, headers, body)
end
+
+ def text_mentioning(*people)
+ people.map {|person|
+ "this is a text mentioning @{#{person.diaspora_handle}} ... have fun testing!"
+ }.join(" ")
+ end
+
+ def build_relayable_federation_entity(type, data={}, additional_data={})
+ attributes = Fabricate.attributes_for("#{type}_entity".to_sym, data)
+ entity_class = "DiasporaFederation::Entities::#{type.to_s.camelize}".constantize
+ signable_fields = attributes.keys - %i[author_signature parent]
+
+ entity_class.new(attributes, [*signable_fields, *additional_data.keys], additional_data)
+ end
end
diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb
index 8a277d41a..c7564c5be 100644
--- a/spec/helpers/application_helper_spec.rb
+++ b/spec/helpers/application_helper_spec.rb
@@ -54,13 +54,13 @@ describe ApplicationHelper, :type => :helper do
end
it 'includes jquery.js from asset pipeline' do
- expect(helper.jquery_include_tag).to match(/jquery2\.js/)
+ expect(helper.jquery_include_tag).to match(/jquery3-[0-9a-f]{64}\.js/)
expect(helper.jquery_include_tag).not_to match(/jquery\.com/)
end
end
it 'inclues jquery_ujs.js' do
- expect(helper.jquery_include_tag).to match(/jquery_ujs\.js/)
+ expect(helper.jquery_include_tag).to match(/jquery_ujs-[0-9a-f]{64}\.js/)
end
it "disables ajax caching" do
diff --git a/spec/helpers/notifications_helper_spec.rb b/spec/helpers/notifications_helper_spec.rb
index 7f5f2e601..1aa84d6a9 100644
--- a/spec/helpers/notifications_helper_spec.rb
+++ b/spec/helpers/notifications_helper_spec.rb
@@ -90,6 +90,37 @@ describe NotificationsHelper, type: :helper do
end
end
end
+
+ let(:status_message) {
+ FactoryGirl.create(:status_message_in_aspect, author: alice.person, text: text_mentioning(bob))
+ }
+
+ describe "when mentioned in status message" do
+ it "should include correct wording and post link" do
+ Notifications::MentionedInPost.notify(status_message, [bob.id])
+ notification = Notifications::MentionedInPost.last
+ expect(notification).not_to be_nil
+
+ link = object_link(notification, notification_people_link(notification))
+ expect(link).to include("mentioned you in the post")
+ expect(link).to include(post_path(status_message))
+ end
+ end
+
+ describe "when mentioned in comment" do
+ it "should include correct wording, post link and comment link" do
+ comment = FactoryGirl.create(:comment, author: bob.person, text: text_mentioning(alice), post: status_message)
+ Notifications::MentionedInComment.notify(comment, [alice.id])
+ notification = Notifications::MentionedInComment.last
+ expect(notification).not_to be_nil
+
+ link = object_link(notification, notification_people_link(notification))
+ expect(link).to include("mentioned you in a")
+ expect(link).to include(">comment</a>")
+ expect(link).to include("href=\"#{post_path(status_message)}\"")
+ expect(link).to include("#{post_path(status_message)}##{comment.guid}")
+ end
+ end
end
describe '#display_year?' do
diff --git a/spec/integration/account_deletion_spec.rb b/spec/integration/account_deletion_spec.rb
index dfe3ee7c0..b6cca15cf 100644
--- a/spec/integration/account_deletion_spec.rb
+++ b/spec/integration/account_deletion_spec.rb
@@ -1,128 +1,39 @@
-describe "deleteing your account", type: :request do
- context "user" do
- before do
- @person = bob.person
- @alices_post = alice.post(:status_message,
- text: "@{bob Grimn; #{bob.person.diaspora_handle}} you are silly",
- to: alice.aspects.find_by_name("generic"))
-
- # bob's own content
- bob.post(:status_message, text: "asldkfjs", to: bob.aspects.first)
- FactoryGirl.create(:photo, author: bob.person)
-
- @aspect_vis = AspectVisibility.where(aspect_id: bob.aspects.map(&:id))
-
- # objects on post
- bob.like!(@alices_post)
- bob.comment!(@alices_post, "here are some thoughts on your post")
-
- # conversations
- create_conversation_with_message(alice, bob.person, "Subject", "Hey bob")
-
- # join tables
- @users_sv = ShareVisibility.where(user_id: bob.id).load
- @persons_sv = ShareVisibility.where(shareable_id: bob.posts.map(&:id), shareable_type: "Post").load
-
- # user associated objects
- @prefs = []
- %w(mentioned liked reshared).each do |pref|
- @prefs << bob.user_preferences.create!(email_type: pref)
- end
-
- # notifications
- @notifications = []
- 3.times do
- @notifications << FactoryGirl.create(:notification, recipient: bob)
- end
-
- # services
- @services = []
- 3.times do
- @services << FactoryGirl.create(:service, user: bob)
- end
-
- # block
- @block = bob.blocks.create!(person: eve.person)
-
- AccountDeleter.new(bob.person.diaspora_handle).perform!
- bob.reload
- end
-
- it "deletes all of the user's preferences" do
- expect(UserPreference.where(id: @prefs.map(&:id))).to be_empty
- end
-
- it "deletes all of the user's notifications" do
- expect(Notification.where(id: @notifications.map(&:id))).to be_empty
- end
-
- it "deletes all of the users's blocked users" do
- expect(Block.where(id: @block.id)).to be_empty
- end
-
- it "deletes all of the user's services" do
- expect(Service.where(id: @services.map(&:id))).to be_empty
- end
-
- it "deletes all of bobs share visiblites" do
- expect(ShareVisibility.where(id: @users_sv.map(&:id))).to be_empty
- expect(ShareVisibility.where(id: @persons_sv.map(&:id))).to be_empty
- end
+describe "deleteing account", type: :request do
+ def account_removal_method
+ AccountDeleter.new(person).perform!
+ subject.reload
+ end
- it "deletes all of bobs aspect visiblites" do
- expect(AspectVisibility.where(id: @aspect_vis.map(&:id))).to be_empty
- end
+ context "of local user" do
+ subject(:user) { FactoryGirl.create(:user_with_aspect) }
+ let(:person) { user.person }
- it "deletes all aspects" do
- expect(bob.aspects).to be_empty
+ before do
+ DataGenerator.create(subject, :generic_user_data)
end
- it "deletes all user contacts" do
- expect(bob.contacts).to be_empty
- end
+ it_behaves_like "deletes all of the user data"
- it "clears the account fields" do
- bob.send(:clearable_fields).each do |field|
- expect(bob.reload[field]).to be_blank
- end
- end
+ it_behaves_like "it removes the person associations"
- it_should_behave_like "it removes the person associations"
+ it_behaves_like "it keeps the person conversations"
end
- context "remote person" do
- before do
- @person = remote_raphael
-
- # contacts
- @contacts = @person.contacts
+ context "of remote person" do
+ subject(:person) { remote_raphael }
- # posts
- @posts = (1..3).map do
- FactoryGirl.create(:status_message, author: @person)
- end
+ before do
+ DataGenerator.create(subject, :generic_person_data)
+ end
- @persons_sv = @posts.each do |post|
- @contacts.each do |contact|
- ShareVisibility.create!(user_id: contact.user.id, shareable: post)
- end
- end
+ it_behaves_like "it removes the person associations"
- # photos
- @photo = FactoryGirl.create(:photo, author: @person)
+ it_behaves_like "it keeps the person conversations"
- # mentions
- @mentions = 3.times do
- FactoryGirl.create(:mention, person: @person)
+ it_behaves_like "it makes account closed and clears profile" do
+ before do
+ account_removal_method
end
-
- # conversations
- create_conversation_with_message(alice, @person, "Subject", "Hey bob")
-
- AccountDeleter.new(@person.diaspora_handle).perform!
- @person.reload
end
-
- it_should_behave_like "it removes the person associations"
end
end
diff --git a/spec/integration/account_migration_spec.rb b/spec/integration/account_migration_spec.rb
new file mode 100644
index 000000000..b7559259e
--- /dev/null
+++ b/spec/integration/account_migration_spec.rb
@@ -0,0 +1,204 @@
+require "integration/federation/federation_helper"
+
+def create_remote_contact(user, pod_host)
+ FactoryGirl.create(
+ :contact,
+ user: user,
+ person: FactoryGirl.create(
+ :person,
+ pod: Pod.find_or_create_by(url: "http://#{pod_host}"),
+ diaspora_handle: "#{r_str}@#{pod_host}"
+ )
+ )
+end
+
+shared_examples_for "old person account is closed and profile is cleared" do
+ subject { old_user.person }
+
+ before do
+ run_migration
+ subject.reload
+ end
+
+ include_examples "it makes account closed and clears profile"
+end
+
+shared_examples_for "old person doesn't have any reference left" do
+ let(:person) { old_user.person }
+
+ before do
+ DataGenerator.create(person, :generic_person_data)
+ end
+
+ def account_removal_method
+ run_migration
+ person.reload
+ end
+
+ include_examples "it removes the person associations"
+
+ include_examples "it removes the person conversations"
+end
+
+shared_examples_for "every migration scenario" do
+ it_behaves_like "it updates person references"
+
+ it_behaves_like "old person account is closed and profile is cleared"
+
+ it_behaves_like "old person doesn't have any reference left"
+end
+
+shared_examples_for "migration scenarios with local old user" do
+ it "locks the old user account" do
+ run_migration
+ expect(old_user.reload).to be_a_locked_account
+ end
+end
+
+shared_examples_for "migration scenarios initiated remotely" do
+ it "resends known contacts to the new user" do
+ contacts = Array.new(2) { FactoryGirl.create(:contact, person: old_user.person, sharing: true) }
+ expect(DiasporaFederation::Federation::Sender).to receive(:private)
+ .twice do |sender_id, obj_str, _urls, _xml|
+ expect(sender_id).to eq(contacts.first.user_id)
+ expect(obj_str).to eq("Contact:#{contacts.first.user.diaspora_handle}:#{new_user.diaspora_handle}")
+ contacts.shift
+ []
+ end
+ inlined_jobs { run_migration }
+ end
+end
+
+shared_examples_for "migration scenarios initiated locally" do
+ it "dispatches account migration message to the federation" do
+ expect(DiasporaFederation::Federation::Sender).to receive(:public) do |sender_id, obj_str, urls, xml|
+ if old_user.person.remote?
+ expect(sender_id).to eq(old_user.diaspora_handle)
+ else
+ expect(sender_id).to eq(old_user.id)
+ end
+ expect(obj_str).to eq("AccountMigration:#{old_user.diaspora_handle}:#{new_user.diaspora_handle}")
+ subscribers = [remote_contact.person]
+ subscribers.push(old_user) if old_user.person.remote?
+ expect(urls).to match_array(subscribers.map(&:url).map {|url| "#{url}receive/public" })
+
+ entity = nil
+ expect {
+ magic_env = Nokogiri::XML(xml).root
+ entity = DiasporaFederation::Salmon::MagicEnvelope
+ .unenvelop(magic_env, old_user.diaspora_handle).payload
+ }.not_to raise_error
+
+ expect(entity).to be_a(DiasporaFederation::Entities::AccountMigration)
+ expect(entity.author).to eq(old_user.diaspora_handle)
+ expect(entity.profile.author).to eq(new_user.diaspora_handle)
+ []
+ end
+
+ inlined_jobs do
+ run_migration
+ end
+ end
+end
+
+describe "account migration" do
+ # this is the case when we receive account migration message from the federation
+ context "remotely initiated" do
+ let(:entity) { create_account_migration_entity(old_user.diaspora_handle, new_user) }
+
+ def run_migration
+ allow_callbacks(%i[queue_public_receive fetch_public_key receive_entity])
+ post_message(generate_payload(entity, old_user))
+ end
+
+ context "both new and old profiles are remote" do
+ include_context "with remote old user"
+ include_context "with remote new user"
+
+ it "creates AccountMigration db object" do
+ run_migration
+ expect(AccountMigration.where(old_person: old_user.person, new_person: new_user.person)).to exist
+ end
+
+ include_examples "every migration scenario"
+
+ include_examples "migration scenarios initiated remotely"
+ end
+
+ # this is the case when we're a pod, which was left by a person in favor of remote one
+ context "old user is local, new user is remote" do
+ include_context "with local old user"
+ include_context "with remote new user"
+
+ include_examples "every migration scenario"
+
+ include_examples "migration scenarios initiated remotely"
+
+ it_behaves_like "migration scenarios with local old user"
+
+ it_behaves_like "deletes all of the user data" do
+ let(:user) { old_user }
+
+ before do
+ DataGenerator.create(user, :generic_user_data)
+ end
+
+ def account_removal_method
+ run_migration
+ user.reload
+ end
+ end
+ end
+ end
+
+ context "locally initiated" do
+ before do
+ allow(DiasporaFederation.callbacks).to receive(:trigger).and_call_original
+ end
+
+ # this is the case when user migrates to our pod from a remote one
+ context "old user is remote and new user is local" do
+ include_context "with remote old user"
+ include_context "with local new user"
+
+ def run_migration
+ AccountMigration.create!(
+ old_person: old_user.person,
+ new_person: new_user.person,
+ old_private_key: old_user.serialized_private_key
+ ).perform!
+ end
+
+ include_examples "every migration scenario"
+
+ it_behaves_like "migration scenarios initiated locally" do
+ let!(:remote_contact) { create_remote_contact(new_user, "remote-friend.org") }
+ end
+ end
+
+ # this is the case when a user changes diaspora id but stays on the same pod
+ context "old user is local and new user is local" do
+ include_context "with local old user"
+ include_context "with local new user"
+
+ def run_migration
+ AccountMigration.create!(old_person: old_user.person, new_person: new_user.person).perform!
+ end
+
+ include_examples "every migration scenario"
+
+ it_behaves_like "migration scenarios initiated locally" do
+ let!(:remote_contact) { create_remote_contact(old_user, "remote-friend.org") }
+ end
+
+ it_behaves_like "migration scenarios with local old user"
+
+ it "clears the old user account" do
+ run_migration
+ expect(old_user.reload).to be_a_clear_account
+ end
+
+ it_behaves_like "it updates user references"
+ end
+ end
+end
diff --git a/spec/integration/api/user_info_controller_spec.rb b/spec/integration/api/user_info_controller_spec.rb
index eaff50459..2c692a100 100644
--- a/spec/integration/api/user_info_controller_spec.rb
+++ b/spec/integration/api/user_info_controller_spec.rb
@@ -5,7 +5,7 @@ describe Api::OpenidConnect::UserInfoController do
describe "#show" do
before do
@user = auth_with_read_and_ppid.user
- get api_openid_connect_user_info_path, access_token: access_token_with_read
+ get api_openid_connect_user_info_path, params: {access_token: access_token_with_read}
end
it "shows the info" do
diff --git a/spec/integration/application_spec.rb b/spec/integration/application_spec.rb
index 39c6c0d67..2c4e78fd5 100644
--- a/spec/integration/application_spec.rb
+++ b/spec/integration/application_spec.rb
@@ -10,14 +10,14 @@ describe ApplicationController, type: :request do
it "redirects to the new session page on validation fails" do
expect_any_instance_of(SessionsController).to receive(:verified_request?).and_return(false)
- post "/users/sign_in", user: {remember_me: 0, username: @user.username, password: "evankorth"}
+ post "/users/sign_in", params: {user: {remember_me: 0, username: @user.username, password: "evankorth"}}
expect(response).to redirect_to new_user_session_path
expect(flash[:error]).to eq(I18n.t("error_messages.csrf_token_fail"))
end
it "doesn't redirect to the new session page if the validation succeeded" do
expect_any_instance_of(SessionsController).to receive(:verified_request?).and_return(true)
- post "/users/sign_in", user: {remember_me: 0, username: @user.username, password: "evankorth"}
+ post "/users/sign_in", params: {user: {remember_me: 0, username: @user.username, password: "evankorth"}}
expect(response).to redirect_to stream_path
expect(flash[:error]).to be_blank
end
@@ -30,7 +30,7 @@ describe ApplicationController, type: :request do
it "signs out users if a wrong token was given" do
expect_any_instance_of(UsersController).to receive(:verified_request?).and_return(false)
- put edit_user_path, user: {language: "en"}
+ put edit_user_path, params: {user: {language: "en"}}
expect(response).to redirect_to new_user_session_path
expect(flash[:error]).to eq(I18n.t("error_messages.csrf_token_fail"))
end
@@ -38,12 +38,12 @@ describe ApplicationController, type: :request do
it "sends an email to the current user if the token validation failed" do
expect_any_instance_of(UsersController).to receive(:verified_request?).and_return(false)
expect(Workers::Mail::CsrfTokenFail).to receive(:perform_async).with(alice.id)
- put edit_user_path, user: {language: "en"}
+ put edit_user_path, params: {user: {language: "en"}}
end
it "doesn't sign out users if the token was correct" do
expect_any_instance_of(UsersController).to receive(:verified_request?).and_return(true)
- put edit_user_path, user: {language: "en"}
+ put edit_user_path, params: {user: {language: "en"}}
expect(response).not_to be_redirect
expect(flash[:error]).to be_blank
end
diff --git a/spec/integration/exporter_spec.rb b/spec/integration/exporter_spec.rb
new file mode 100644
index 000000000..8cea5501a
--- /dev/null
+++ b/spec/integration/exporter_spec.rb
@@ -0,0 +1,444 @@
+# Copyright (c) 2010-2011, Diaspora Inc. This file is
+# licensed under the Affero General Public License version 3 or later. See
+# the COPYRIGHT file.
+
+describe Diaspora::Exporter do
+ let(:user) { FactoryGirl.create(:user_with_aspect) }
+
+ context "output json" do
+ let(:json) { Diaspora::Exporter.new(user).execute }
+
+ it "matches archive schema" do
+ DataGenerator.create(
+ user,
+ %i[generic_user_data activity status_messages_flavours work_aspect]
+ )
+
+ expect(JSON.parse(json)).to match_json_schema(:archive_schema)
+ end
+
+ it "contains basic user data" do
+ user_properties = build_property_hash(
+ user,
+ %i[email username language disable_mail show_community_spotlight_in_stream auto_follow_back
+ auto_follow_back_aspect strip_exif],
+ private_key: :serialized_private_key
+ )
+
+ user_properties[:profile] = {
+ entity_type: "profile",
+ entity_data: build_property_hash(
+ user.profile,
+ %i[first_name last_name gender bio location image_url birthday searchable nsfw tag_string],
+ author: :diaspora_handle
+ )
+ }
+
+ expect(json).to include_json(user: user_properties)
+ end
+
+ it "contains aspects" do
+ DataGenerator.create(user, :work_aspect)
+
+ expect(json).to include_json(
+ user: {
+ "contact_groups": [
+ {
+ "name": "generic",
+ "contacts_visible": true,
+ "chat_enabled": false
+ },
+ {
+ "name": "Work",
+ "contacts_visible": false,
+ "chat_enabled": false
+ }
+ ]
+ }
+ )
+ end
+
+ it "contains contacts" do
+ friends = DataGenerator.create(user, Array.new(2, :mutual_friend))
+ serialized_contacts = friends.map {|friend|
+ contact = Contact.find_by(person_id: friend.person_id)
+ hash = build_property_hash(
+ contact,
+ %i[sharing receiving person_guid person_name],
+ following: :sharing, followed: :receiving, account_id: :person_diaspora_handle
+ )
+ hash[:public_key] = contact.person.serialized_public_key
+ hash[:contact_groups_membership] = contact.aspects.map(&:name)
+ hash
+ }
+
+ expect(json).to include_json(user: {contacts: serialized_contacts})
+ end
+
+ it "contains a public status message" do
+ status_message = FactoryGirl.create(:status_message, author: user.person, public: true)
+ serialized = {
+ "subscribed_pods_uris": [AppConfig.pod_uri.to_s],
+ "entity_type": "status_message",
+ "entity_data": {
+ "author": user.diaspora_handle,
+ "guid": status_message.guid,
+ "created_at": status_message.created_at.iso8601,
+ "text": status_message.text,
+ "public": true
+ }
+ }
+
+ expect(json).to include_json(user: {posts: [serialized]})
+ end
+
+ it "contains a status message with subscribers" do
+ subscriber, status_message = DataGenerator.create(user, :status_message_with_subscriber)
+ serialized = {
+ "subscribed_users_ids": [subscriber.diaspora_handle],
+ "entity_type": "status_message",
+ "entity_data": {
+ "author": user.diaspora_handle,
+ "guid": status_message.guid,
+ "created_at": status_message.created_at.iso8601,
+ "text": status_message.text,
+ "public": false
+ }
+ }
+
+ expect(json).to include_json(user: {posts: [serialized]})
+ end
+
+ it "contains a status message with a poll" do
+ status_message = FactoryGirl.create(:status_message_with_poll, author: user.person)
+ serialized = {
+ "entity_type": "status_message",
+ "entity_data": {
+ "author": user.diaspora_handle,
+ "guid": status_message.guid,
+ "created_at": status_message.created_at.iso8601,
+ "text": status_message.text,
+ "poll": {
+ "entity_type": "poll",
+ "entity_data": {
+ "guid": status_message.poll.guid,
+ "question": status_message.poll.question,
+ "poll_answers": status_message.poll.poll_answers.map {|answer|
+ {
+ "entity_type": "poll_answer",
+ "entity_data": {
+ "guid": answer.guid,
+ "answer": answer.answer
+ }
+ }
+ }
+ }
+ },
+ "public": false
+ }
+ }
+
+ expect(json).to include_json(user: {posts: [serialized]})
+ end
+
+ it "contains a status message with a photo" do
+ status_message = FactoryGirl.create(:status_message_with_photo, author: user.person)
+
+ serialized = {
+ "entity_type": "status_message",
+ "entity_data": {
+ "author": user.diaspora_handle,
+ "guid": status_message.guid,
+ "created_at": status_message.created_at.iso8601,
+ "text": status_message.text,
+ "photos": [
+ {
+ "entity_type": "photo",
+ "entity_data": {
+ "guid": status_message.photos.first.guid,
+ "author": user.diaspora_handle,
+ "public": false,
+ "created_at": status_message.photos.first.created_at.iso8601,
+ "remote_photo_path": "#{AppConfig.pod_uri}uploads\/images\/",
+ "remote_photo_name": status_message.photos.first.remote_photo_name,
+ "status_message_guid": status_message.guid,
+ "height": 42,
+ "width": 23
+ }
+ }
+ ],
+ "public": false
+ }
+ }
+
+ expect(json).to include_json(user: {posts: [serialized]})
+ end
+
+ it "contains a status message with a location" do
+ status_message = FactoryGirl.create(:status_message_with_location, author: user.person)
+
+ serialized = {
+ "entity_type": "status_message",
+ "entity_data": {
+ "author": user.diaspora_handle,
+ "guid": status_message.guid,
+ "created_at": status_message.created_at.iso8601,
+ "text": status_message.text,
+ "location": {
+ "entity_type": "location",
+ "entity_data": {
+ "address": status_message.location.address,
+ "lat": status_message.location.lat,
+ "lng": status_message.location.lng
+ }
+ },
+ "public": false
+ }
+ }
+
+ expect(json).to include_json(user: {posts: [serialized]})
+ end
+
+ it "contains a reshare and its root" do
+ reshare = FactoryGirl.create(:reshare, author: user.person)
+ serialized_reshare = {
+ "subscribed_pods_uris": [reshare.root.author.pod.url_to(""), AppConfig.pod_uri.to_s],
+ "entity_type": "reshare",
+ "entity_data": {
+ "author": user.diaspora_handle,
+ "guid": reshare.guid,
+ "created_at": reshare.created_at.iso8601,
+ "public": true,
+ "root_author": reshare.root_author.diaspora_handle,
+ "root_guid": reshare.root_guid
+ }
+ }
+
+ status_message = reshare.root
+ serialized_parent = {
+ "entity_type": "status_message",
+ "entity_data": {
+ "author": status_message.diaspora_handle,
+ "guid": status_message.guid,
+ "created_at": status_message.created_at.iso8601,
+ "text": status_message.text,
+ "public": true
+ }
+ }
+
+ expect(json).to include_json(
+ user: {posts: [serialized_reshare]},
+ others_data: {posts: [serialized_parent]}
+ )
+ end
+
+ it "contains followed tags" do
+ tag_following = DataGenerator.create(user, :tag_following)
+ expect(json).to include_json(user: {followed_tags: [tag_following.tag.name]})
+ end
+
+ it "contains post subscriptions" do
+ subscription = DataGenerator.create(user, :subscription)
+ expect(json).to include_json(user: {post_subscriptions: [subscription.target.guid]})
+ end
+
+ it "contains a comment and the commented post" do
+ comment = FactoryGirl.create(:comment, author: user.person)
+ serialized_comment = {
+ "entity_type": "comment",
+ "entity_data": {
+ "author": user.diaspora_handle,
+ "guid": comment.guid,
+ "parent_guid": comment.parent.guid,
+ "text": comment.text,
+ "created_at": comment.created_at.iso8601
+ },
+ "property_order": %w[author guid parent_guid text created_at]
+ }
+
+ status_message = comment.parent
+ serialized_post = {
+ "entity_type": "status_message",
+ "entity_data": {
+ "author": status_message.diaspora_handle,
+ "guid": status_message.guid,
+ "created_at": status_message.created_at.iso8601,
+ "text": status_message.text,
+ "public": false
+ }
+ }
+
+ expect(json).to include_json(
+ user: {relayables: [serialized_comment]},
+ others_data: {posts: [serialized_post]}
+ )
+ end
+
+ it "contains a like and the liked post" do
+ like = FactoryGirl.create(:like, author: user.person)
+ serialized_like = {
+ "entity_type": "like",
+ "entity_data": {
+ "author": user.diaspora_handle,
+ "guid": like.guid,
+ "parent_guid": like.parent.guid,
+ "parent_type": like.target_type,
+ "positive": like.positive
+ },
+ "property_order": %w[author guid parent_guid parent_type positive]
+ }
+
+ status_message = like.target
+ serialized_post = {
+ "entity_type": "status_message",
+ "entity_data": {
+ "author": status_message.diaspora_handle,
+ "guid": status_message.guid,
+ "created_at": status_message.created_at.iso8601,
+ "text": status_message.text,
+ "public": false
+ }
+ }
+
+ expect(json).to include_json(
+ user: {relayables: [serialized_like]},
+ others_data: {posts: [serialized_post]}
+ )
+ end
+
+ it "contains a poll participation and post with this poll" do
+ poll_participation = FactoryGirl.create(:poll_participation, author: user.person)
+ serialized_participation = {
+ "entity_type": "poll_participation",
+ "entity_data": {
+ "author": user.diaspora_handle,
+ "guid": poll_participation.guid,
+ "parent_guid": poll_participation.parent.guid,
+ "poll_answer_guid": poll_participation.poll_answer.guid
+ },
+ "property_order": %w[author guid parent_guid poll_answer_guid]
+ }
+
+ poll = poll_participation.poll
+ status_message = poll_participation.status_message
+ serialized_post = {
+ "entity_type": "status_message",
+ "entity_data": {
+ "author": status_message.diaspora_handle,
+ "guid": status_message.guid,
+ "created_at": status_message.created_at.iso8601,
+ "text": status_message.text,
+ "poll": {
+ "entity_type": "poll",
+ "entity_data": {
+ "guid": poll.guid,
+ "question": poll.question,
+ "poll_answers": poll.poll_answers.map {|answer|
+ {
+ "entity_type": "poll_answer",
+ "entity_data": {
+ "guid": answer.guid,
+ "answer": answer.answer
+ }
+ }
+ }
+ }
+ },
+ "public": false
+ }
+ }
+
+ expect(json).to include_json(
+ user: {relayables: [serialized_participation]},
+ others_data: {posts: [serialized_post]}
+ )
+ end
+
+ it "contains a comment for the user's post" do
+ status_message, comment = DataGenerator.create(user, :status_message_with_comment)
+ serialized = {
+ "entity_type": "comment",
+ "entity_data": {
+ "author": comment.diaspora_handle,
+ "guid": comment.guid,
+ "parent_guid": status_message.guid,
+ "text": comment.text,
+ "created_at": comment.created_at.iso8601,
+ "author_signature": Diaspora::Federation::Entities.build(comment).to_h[:author_signature]
+ },
+ "property_order": %w[author guid parent_guid text created_at]
+ }
+
+ expect(json).to include_json(others_data: {relayables: [serialized]})
+ end
+
+ it "contains a like for the user's post" do
+ status_message, like = DataGenerator.create(user, :status_message_with_like)
+ serialized = {
+ "entity_type": "like",
+ "entity_data": {
+ "author": like.diaspora_handle,
+ "guid": like.guid,
+ "parent_guid": status_message.guid,
+ "parent_type": like.target_type,
+ "positive": like.positive,
+ "author_signature": Diaspora::Federation::Entities.build(like).to_h[:author_signature]
+ },
+ "property_order": %w[author guid parent_guid parent_type positive]
+ }
+
+ expect(json).to include_json(others_data: {relayables: [serialized]})
+ end
+
+ it "contains a poll participation for the user's post" do
+ _, poll_participation = DataGenerator.create(user, :status_message_with_poll_participation)
+ serialized = {
+ "entity_type": "poll_participation",
+ "entity_data": {
+ "author": poll_participation.diaspora_handle,
+ "guid": poll_participation.guid,
+ "parent_guid": poll_participation.parent.guid,
+ "poll_answer_guid": poll_participation.poll_answer.guid,
+ "author_signature": Diaspora::Federation::Entities.build(poll_participation).to_h[:author_signature]
+ },
+ "property_order": %w[author guid parent_guid poll_answer_guid]
+ }
+
+ expect(json).to include_json(others_data: {relayables: [serialized]})
+ end
+
+ it "contains metadata of a non-contact author of a post where we commented" do
+ comment = FactoryGirl.create(:comment, author: user.person)
+
+ author = comment.parent.author
+ expect(json).to include_json(
+ others_data: {
+ non_contact_authors: [
+ {
+ "guid": author.guid,
+ "account_id": author.diaspora_handle,
+ "public_key": author.serialized_public_key
+ }
+ ]
+ }
+ )
+ end
+
+ def transform_value(value)
+ return value.iso8601 if value.is_a? Date
+ value
+ end
+
+ def build_property_hash(object, direct_properties, aliased_properties={})
+ props = direct_properties.map {|key|
+ [key, transform_value(object.send(key))]
+ }.to_h
+
+ aliased = aliased_properties.map {|key, key_alias|
+ [key, object.send(key_alias)]
+ }.to_h
+
+ props.merge(aliased)
+ end
+ end
+end
diff --git a/spec/integration/federation/attack_vectors_spec.rb b/spec/integration/federation/attack_vectors_spec.rb
index e345420ef..b88d4883c 100644
--- a/spec/integration/federation/attack_vectors_spec.rb
+++ b/spec/integration/federation/attack_vectors_spec.rb
@@ -23,7 +23,7 @@ describe "attack vectors", type: :request do
alice.share_with(eve.person, alices_aspect)
- post_message(generate_xml(Diaspora::Federation::Entities.post(original_message), bob, alice), alice)
+ post_message(generate_payload(Diaspora::Federation::Entities.post(original_message), bob, alice), alice)
# alice still should not see eves original post, even though bob sent it to her
expect(alice.reload.visible_shareables(Post).where(guid: original_message.guid)).to be_blank
@@ -34,36 +34,39 @@ describe "attack vectors", type: :request do
profile = eve.profile.clone
profile.first_name = "Not BOB"
- post_message(generate_xml(Diaspora::Federation::Entities.profile(profile), alice, bob), bob)
+ post_message(generate_payload(Diaspora::Federation::Entities.profile(profile), alice, bob), bob)
- expect(eve.profile(true).first_name).not_to eq("Not BOB")
+ expect(eve.profile.reload.first_name).not_to eq("Not BOB")
end
it "public post should not be spoofed from another author" do
post = FactoryGirl.build(:status_message, public: true, author: eve.person)
- post_message(generate_xml(Diaspora::Federation::Entities.post(post), alice))
+ post_message(generate_payload(Diaspora::Federation::Entities.post(post), alice))
expect(StatusMessage.exists?(guid: post.guid)).to be_falsey
end
it "should not receive retractions where the retractor and the salmon author do not match" do
original_message = eve.post(:status_message, text: "store this!", to: eves_aspect.id)
+ retraction = Retraction.for(original_message)
expect {
- post_message(generate_xml(Diaspora::Federation::Entities.retraction(original_message), alice, bob), bob)
+ post_message(generate_payload(Diaspora::Federation::Entities.retraction(retraction), alice, bob), bob)
}.to_not change { bob.visible_shareables(Post).count(:all) }
end
it "should not receive contact retractions from another person" do
# we are banking on bob being friends with alice and eve
# here, alice is trying to disconnect bob and eve
- contact = bob.contacts(true).find_by(person_id: eve.person.id)
+ contact = bob.contacts.reload.find_by(person_id: eve.person.id)
expect(contact).to be_sharing
- post_message(generate_xml(Diaspora::Federation::Entities.retraction(contact), alice, bob), bob)
+ post_message(
+ generate_payload(Diaspora::Federation::Entities.retraction(ContactRetraction.for(contact)), alice, bob), bob
+ )
- expect(bob.contacts(true).find_by(person_id: eve.person.id)).to be_sharing
+ expect(bob.contacts.reload.find_by(person_id: eve.person.id)).to be_sharing
end
end
@@ -79,7 +82,7 @@ describe "attack vectors", type: :request do
author: alice.person
)
- post_message(generate_xml(Diaspora::Federation::Entities.post(malicious_message), alice, bob), bob)
+ post_message(generate_payload(Diaspora::Federation::Entities.post(malicious_message), alice, bob), bob)
expect(original_message.reload.author_id).to eq(eve.person.id)
end
@@ -92,7 +95,7 @@ describe "attack vectors", type: :request do
# eve tries to send me another message with the same ID
malicious_message = FactoryGirl.build(:status_message, id: original_message.id, text: "BAD!!!", author: eve.person)
- post_message(generate_xml(Diaspora::Federation::Entities.post(malicious_message), eve, bob), bob)
+ post_message(generate_payload(Diaspora::Federation::Entities.post(malicious_message), eve, bob), bob)
expect(original_message.reload.text).to eq("store this!")
end
@@ -108,7 +111,7 @@ describe "attack vectors", type: :request do
)
expect {
- post_message(generate_xml(retraction, alice, bob), bob)
+ post_message(generate_payload(retraction, alice, bob), bob)
}.to_not change(StatusMessage, :count)
end
@@ -121,7 +124,7 @@ describe "attack vectors", type: :request do
new_message.height = 23
new_message.width = 42
- post_message(generate_xml(Diaspora::Federation::Entities.photo(new_message), alice, bob), bob)
+ post_message(generate_payload(Diaspora::Federation::Entities.photo(new_message), alice, bob), bob)
expect(original_message.reload.text).to eq("store this!")
end
diff --git a/spec/integration/federation/federation_helper.rb b/spec/integration/federation/federation_helper.rb
index afc880792..f2da9812b 100644
--- a/spec/integration/federation/federation_helper.rb
+++ b/spec/integration/federation/federation_helper.rb
@@ -6,21 +6,43 @@ def remote_user_on_pod_c
@remote_on_c ||= create_remote_user("remote-c.net")
end
-def create_remote_user(pod)
+def allow_private_key_fetch(user)
+ allow(DiasporaFederation.callbacks).to receive(:trigger).with(
+ :fetch_private_key, user.diaspora_handle
+ ) { user.encryption_key }
+end
+
+def allow_public_key_fetch(user)
+ allow(DiasporaFederation.callbacks).to receive(:trigger).with(
+ :fetch_public_key, user.diaspora_handle
+ ) { OpenSSL::PKey::RSA.new(user.person.serialized_public_key) }
+end
+
+def create_undiscovered_user(pod)
FactoryGirl.build(:user).tap do |user|
allow(user).to receive(:person).and_return(
- FactoryGirl.create(:person,
- profile: FactoryGirl.build(:profile),
- serialized_public_key: user.encryption_key.public_key.export,
- pod: Pod.find_or_create_by(url: "http://#{pod}"),
- diaspora_handle: "#{user.username}@#{pod}")
+ FactoryGirl.build(:person,
+ profile: FactoryGirl.build(:profile),
+ serialized_public_key: user.encryption_key.public_key.export,
+ pod: Pod.find_or_create_by(url: "http://#{pod}"),
+ diaspora_handle: "#{user.username}@#{pod}")
)
- allow(DiasporaFederation.callbacks).to receive(:trigger).with(
- :fetch_private_key, user.diaspora_handle
- ) { user.encryption_key }
- allow(DiasporaFederation.callbacks).to receive(:trigger).with(
- :fetch_public_key, user.diaspora_handle
- ) { OpenSSL::PKey::RSA.new(user.person.serialized_public_key) }
+ end
+end
+
+def expect_person_discovery(undiscovered_user)
+ allow(Person).to receive(:find_or_fetch_by_identifier).with(any_args).and_call_original
+ expect(Person).to receive(:find_or_fetch_by_identifier).with(undiscovered_user.diaspora_handle) {
+ undiscovered_user.person.save!
+ undiscovered_user.person
+ }
+end
+
+def create_remote_user(pod)
+ create_undiscovered_user(pod).tap do |user|
+ user.person.save!
+ allow_private_key_fetch(user)
+ allow_public_key_fetch(user)
end
end
@@ -35,41 +57,46 @@ def create_relayable_entity(entity_name, parent, diaspora_id)
:fetch_private_key, alice.diaspora_handle
).at_least(1).times.and_return(nil) if parent == local_parent
- parent_guid = parent.guid
- FactoryGirl.build(
+ Fabricate(
entity_name,
- conversation_guid: parent_guid,
- parent_guid: parent_guid,
- author: diaspora_id,
- poll_answer_guid: parent.respond_to?(:poll_answers) ? parent.poll_answers.first.guid : nil,
- parent: Diaspora::Federation::Entities.related_entity(parent)
+ parent_guid: parent.guid,
+ author: diaspora_id,
+ poll_answer_guid: parent.respond_to?(:poll_answers) ? parent.poll_answers.first.guid : nil,
+ parent: Diaspora::Federation::Entities.related_entity(parent)
+ )
+end
+
+def create_account_migration_entity(diaspora_id, new_user)
+ Fabricate(
+ :account_migration_entity,
+ author: diaspora_id,
+ profile: Diaspora::Federation::Entities.build(new_user.profile)
)
end
-def generate_xml(entity, remote_user, recipient=nil)
+def generate_payload(entity, remote_user, recipient=nil)
+ magic_env = DiasporaFederation::Salmon::MagicEnvelope.new(
+ entity,
+ remote_user.diaspora_handle
+ ).envelop(remote_user.encryption_key)
+
if recipient
- DiasporaFederation::Salmon::EncryptedSlap.prepare(
- remote_user.diaspora_handle,
- remote_user.encryption_key,
- entity
- ).generate_xml(recipient.encryption_key)
+ DiasporaFederation::Salmon::EncryptedMagicEnvelope.encrypt(magic_env, recipient.encryption_key)
else
- DiasporaFederation::Salmon::Slap.generate_xml(
- remote_user.diaspora_handle,
- remote_user.encryption_key,
- entity
- )
+ magic_env.to_xml
end
end
-def post_message(xml, recipient=nil)
+def post_message(payload, recipient=nil)
if recipient
inlined_jobs do
- post "/receive/users/#{recipient.guid}", guid: recipient.guid, xml: xml
+ headers = {"CONTENT_TYPE" => "application/json"}
+ post "/receive/users/#{recipient.guid}", params: payload, headers: headers
end
else
inlined_jobs do
- post "/receive/public", xml: xml
+ headers = {"CONTENT_TYPE" => "application/magic-envelope+xml"}
+ post "/receive/public", params: payload, headers: headers
end
end
end
diff --git a/spec/integration/federation/receive_federation_messages_spec.rb b/spec/integration/federation/receive_federation_messages_spec.rb
index 85a2b142d..8ddb917cc 100644
--- a/spec/integration/federation/receive_federation_messages_spec.rb
+++ b/spec/integration/federation/receive_federation_messages_spec.rb
@@ -9,36 +9,111 @@ describe "Receive federation messages feature" do
end
let(:sender) { remote_user_on_pod_b }
- let(:sender_id) { remote_user_on_pod_b.diaspora_handle }
+ let(:sender_id) { sender.diaspora_handle }
context "with public receive" do
let(:recipient) { nil }
- it "receives account deletion correctly" do
- post_message(generate_xml(DiasporaFederation::Entities::AccountDeletion.new(diaspora_id: sender_id), sender))
+ context "account deletion" do
+ it "receives account deletion correctly" do
+ post_message(generate_payload(DiasporaFederation::Entities::AccountDeletion.new(author: sender_id), sender))
- expect(AccountDeletion.exists?(diaspora_handle: sender_id)).to be_truthy
+ expect(AccountDeletion.exists?(person: sender.person)).to be_truthy
+ end
+
+ it "rejects account deletion with wrong author" do
+ delete_id = Fabricate.sequence(:diaspora_id)
+ expect {
+ post_message(generate_payload(DiasporaFederation::Entities::AccountDeletion.new(author: delete_id), sender))
+ }.not_to change(AccountDeletion, :count)
+ end
end
- it "rejects account deletion with wrong diaspora_id" do
- delete_id = FactoryGirl.generate(:diaspora_id)
- post_message(generate_xml(DiasporaFederation::Entities::AccountDeletion.new(diaspora_id: delete_id), sender))
+ context "account migration" do
+ # In case when sender is unknown we should just ignore the migration
+ # but this depends on https://github.com/diaspora/diaspora_federation/issues/72
+ # which is low-priority, so we just discover the sender profile in this case.
+ # But there won't be a spec for that.
+
+ let(:entity) { create_account_migration_entity(sender_id, new_user) }
+
+ def run_migration
+ post_message(generate_payload(entity, sender))
+ end
+
+ context "with undiscovered new user profile" do
+ before do
+ allow_callbacks(%i[fetch_public_key])
+ allow_private_key_fetch(new_user)
+ expect_person_discovery(new_user)
+ end
+
+ let(:new_user) { create_undiscovered_user("example.org") }
+
+ it "receives account migration correctly" do
+ run_migration
+ expect(AccountMigration.where(old_person: sender.person, new_person: new_user.person)).to exist
+ expect(AccountMigration.find_by(old_person: sender.person, new_person: new_user.person)).to be_performed
+ end
+
+ it "doesn't accept the same migration for the second time" do
+ run_migration
+ expect {
+ run_migration
+ }.to raise_error(ActiveRecord::RecordInvalid)
+ end
+
+ it "doesn't accept second migration for the same sender" do
+ run_migration
+ expect {
+ entity = create_account_migration_entity(sender_id, create_remote_user("example.org"))
+ post_message(generate_payload(entity, sender))
+ }.to raise_error(ActiveRecord::RecordInvalid)
+ end
+
+ it "doesn't accept second migration for the same new user profile" do
+ run_migration
+ expect {
+ sender = create_remote_user("example.org")
+ entity = create_account_migration_entity(sender.diaspora_handle, new_user)
+ post_message(generate_payload(entity, sender))
+ }.to raise_error(ActiveRecord::RecordInvalid)
+ end
- expect(AccountDeletion.exists?(diaspora_handle: delete_id)).to be_falsey
- expect(AccountDeletion.exists?(diaspora_handle: sender_id)).to be_falsey
+ context "when our pod was left" do
+ let(:sender) { FactoryGirl.create(:user) }
+
+ it "locks the old user account access" do
+ run_migration
+ expect(sender.reload.access_locked?).to be_truthy
+ end
+ end
+ end
+
+ context "with discovered profile" do
+ let(:new_user) { create_remote_user("example.org") }
+
+ it "updates person profile with data from entity" do
+ new_user.profile.bio = "my updated biography"
+ expect(entity.profile.bio).to eq("my updated biography")
+ expect(new_user.profile.reload.bio).not_to eq("my updated biography")
+ run_migration
+ expect(new_user.profile.reload.bio).to eq("my updated biography")
+ end
+ end
end
context "reshare" do
it "reshare of public post passes" do
post = FactoryGirl.create(:status_message, author: alice.person, public: true)
- reshare = FactoryGirl.build(
+ reshare = Fabricate(
:reshare_entity, root_author: alice.diaspora_handle, root_guid: post.guid, author: sender_id)
expect(Participation::Generator).to receive(:new).with(
alice, instance_of(Reshare)
).and_return(double(create!: true))
- post_message(generate_xml(reshare, sender))
+ post_message(generate_payload(reshare, sender))
expect(Reshare.exists?(root_guid: post.guid)).to be_truthy
expect(Reshare.where(root_guid: post.guid).last.diaspora_handle).to eq(sender_id)
@@ -46,10 +121,10 @@ describe "Receive federation messages feature" do
it "reshare of private post fails" do
post = FactoryGirl.create(:status_message, author: alice.person, public: false)
- reshare = FactoryGirl.build(
+ reshare = Fabricate(
:reshare_entity, root_author: alice.diaspora_handle, root_guid: post.guid, author: sender_id)
expect {
- post_message(generate_xml(reshare, sender))
+ post_message(generate_payload(reshare, sender))
}.to raise_error ActiveRecord::RecordInvalid, "Validation failed: Only posts which are public may be reshared."
expect(Reshare.exists?(root_guid: post.guid)).to be_falsey
@@ -73,12 +148,12 @@ describe "Receive federation messages feature" do
context "with private receive" do
let(:recipient) { alice }
- it "treats sharing request recive correctly" do
- entity = FactoryGirl.build(:request_entity, author: sender_id, recipient: alice.diaspora_handle)
+ it "treats sharing request receive correctly" do
+ entity = Fabricate(:contact_entity, author: sender_id, recipient: alice.diaspora_handle)
expect(Workers::ReceiveLocal).to receive(:perform_async).and_call_original
- post_message(generate_xml(entity, sender, alice), alice)
+ post_message(generate_payload(entity, sender, alice), alice)
expect(alice.contacts.count).to eq(2)
new_contact = alice.contacts.find {|c| c.person.diaspora_handle == sender_id }
@@ -105,8 +180,8 @@ describe "Receive federation messages feature" do
it_behaves_like "messages which can't be send without sharing"
it "treats profile receive correctly" do
- entity = FactoryGirl.build(:profile_entity, author: sender_id)
- post_message(generate_xml(entity, sender, alice), alice)
+ entity = Fabricate(:profile_entity, author: sender_id)
+ post_message(generate_payload(entity, sender, alice), alice)
received_profile = sender.profile.reload
@@ -115,35 +190,70 @@ describe "Receive federation messages feature" do
end
it "receives conversation correctly" do
- entity = FactoryGirl.build(
+ entity = Fabricate(
:conversation_entity,
author: sender_id,
participants: "#{sender_id};#{alice.diaspora_handle}"
)
- post_message(generate_xml(entity, sender, alice), alice)
+ post_message(generate_payload(entity, sender, alice), alice)
expect(Conversation.exists?(guid: entity.guid)).to be_truthy
end
context "with message" do
- let(:local_parent) {
- FactoryGirl.build(:conversation, author: alice.person).tap do |target|
- target.participants << remote_user_on_pod_b.person
- target.participants << remote_user_on_pod_c.person
- target.save
- end
- }
- let(:remote_parent) {
- FactoryGirl.build(:conversation, author: remote_user_on_pod_b.person).tap do |target|
- target.participants << alice.person
- target.participants << remote_user_on_pod_c.person
- target.save
+ context "local" do
+ let(:parent) {
+ FactoryGirl.build(:conversation, author: alice.person).tap do |target|
+ target.participants << remote_user_on_pod_b.person
+ target.participants << remote_user_on_pod_c.person
+ target.save
+ end
+ }
+ let(:message) {
+ Fabricate(
+ :message_entity,
+ conversation_guid: parent.guid,
+ author: sender_id,
+ parent: Diaspora::Federation::Entities.related_entity(parent)
+ )
+ }
+
+ it "receives the message correctly" do
+ expect(Workers::ReceiveLocal).to receive(:perform_async)
+ post_message(generate_payload(message, sender, recipient), recipient)
+
+ received_message = Message.find_by(guid: message.guid)
+ expect(received_message).not_to be_nil
+ expect(received_message.author.diaspora_handle).to eq(sender_id)
end
- }
- let(:entity_name) { :message_entity }
- let(:klass) { Message }
+ end
- it_behaves_like "it deals correctly with a relayable"
+ context "remote" do
+ let(:parent) {
+ FactoryGirl.build(:conversation, author: remote_user_on_pod_b.person).tap do |target|
+ target.participants << alice.person
+ target.participants << remote_user_on_pod_c.person
+ target.save
+ end
+ }
+ let(:message) {
+ Fabricate(
+ :message_entity,
+ conversation_guid: parent.guid,
+ author: remote_user_on_pod_c.diaspora_handle,
+ parent: Diaspora::Federation::Entities.related_entity(parent)
+ )
+ }
+
+ it "receives the message correctly" do
+ expect(Workers::ReceiveLocal).to receive(:perform_async)
+ post_message(generate_payload(message, remote_user_on_pod_c, recipient), recipient)
+
+ received_message = Message.find_by(guid: message.guid)
+ expect(received_message).not_to be_nil
+ expect(received_message.author.diaspora_handle).to eq(remote_user_on_pod_c.diaspora_handle)
+ end
+ end
end
end
end
diff --git a/spec/integration/federation/shared_receive_relayable.rb b/spec/integration/federation/shared_receive_relayable.rb
index 06e67c247..2d0e150ba 100644
--- a/spec/integration/federation/shared_receive_relayable.rb
+++ b/spec/integration/federation/shared_receive_relayable.rb
@@ -4,7 +4,7 @@ shared_examples_for "it deals correctly with a relayable" do
it "treats upstream receive correctly" do
expect(Workers::ReceiveLocal).to receive(:perform_async)
- post_message(generate_xml(entity, sender, recipient), recipient)
+ post_message(generate_payload(entity, sender, recipient), recipient)
received_entity = klass.find_by(guid: entity.guid)
expect(received_entity).not_to be_nil
@@ -15,7 +15,7 @@ shared_examples_for "it deals correctly with a relayable" do
it "rejects an upstream entity with a malformed author signature" do
expect(Workers::ReceiveLocal).not_to receive(:perform_async)
allow(remote_user_on_pod_b).to receive(:encryption_key).and_return(OpenSSL::PKey::RSA.new(1024))
- post_message(generate_xml(entity, sender, recipient), recipient)
+ post_message(generate_payload(entity, sender, recipient), recipient)
expect(klass.exists?(guid: entity.guid)).to be_falsey
end
@@ -28,7 +28,7 @@ shared_examples_for "it deals correctly with a relayable" do
it "treats downstream receive correctly" do
expect(Workers::ReceiveLocal).to receive(:perform_async)
- post_message(generate_xml(entity, sender, recipient), recipient)
+ post_message(generate_payload(entity, sender, recipient), recipient)
received_entity = klass.find_by(guid: entity.guid)
expect(received_entity).not_to be_nil
@@ -40,7 +40,7 @@ shared_examples_for "it deals correctly with a relayable" do
it "rejects a downstream entity with a malformed author signature" do
expect(Workers::ReceiveLocal).not_to receive(:perform_async)
allow(remote_user_on_pod_c).to receive(:encryption_key).and_return(OpenSSL::PKey::RSA.new(1024))
- post_message(generate_xml(entity, sender, recipient), recipient)
+ post_message(generate_payload(entity, sender, recipient), recipient)
expect(klass.exists?(guid: entity.guid)).to be_falsey
end
@@ -50,7 +50,7 @@ shared_examples_for "it deals correctly with a relayable" do
it "declines downstream receive when sender signed with a wrong key" do
expect(Workers::ReceiveLocal).not_to receive(:perform_async)
allow(sender).to receive(:encryption_key).and_return(OpenSSL::PKey::RSA.new(1024))
- post_message(generate_xml(entity, sender, recipient), recipient)
+ post_message(generate_payload(entity, sender, recipient), recipient)
expect(klass.exists?(guid: entity.guid)).to be_falsey
end
diff --git a/spec/integration/federation/shared_receive_retraction.rb b/spec/integration/federation/shared_receive_retraction.rb
index afa415993..adc8112c0 100644
--- a/spec/integration/federation/shared_receive_retraction.rb
+++ b/spec/integration/federation/shared_receive_retraction.rb
@@ -1,6 +1,6 @@
-def retraction_entity(entity_name, target_object, sender)
- FactoryGirl.build(
- entity_name,
+def retraction_entity(target_object, sender)
+ Fabricate(
+ :retraction_entity,
author: sender.diaspora_handle,
target_guid: target_object.guid,
target_type: target_object.class.to_s,
@@ -10,23 +10,23 @@ end
shared_examples_for "it retracts non-relayable object" do
it "retracts object by a correct retraction message" do
- entity = retraction_entity(entity_name, target_object, sender)
- post_message(generate_xml(entity, sender, recipient), recipient)
+ entity = retraction_entity(target_object, sender)
+ post_message(generate_payload(entity, sender, recipient), recipient)
expect(target_object.class.exists?(guid: target_object.guid)).to be_falsey
end
it "doesn't retract object when retraction has wrong signatures" do
allow(sender).to receive(:encryption_key).and_return(OpenSSL::PKey::RSA.new(1024))
- entity = retraction_entity(entity_name, target_object, sender)
- post_message(generate_xml(entity, sender, recipient), recipient)
+ entity = retraction_entity(target_object, sender)
+ post_message(generate_payload(entity, sender, recipient), recipient)
expect(target_object.class.exists?(guid: target_object.guid)).to be_truthy
end
it "doesn't retract object when sender is different from target object" do
- entity = retraction_entity(entity_name, target_object, remote_user_on_pod_c)
- post_message(generate_xml(entity, remote_user_on_pod_c, recipient), recipient)
+ entity = retraction_entity(target_object, remote_user_on_pod_c)
+ post_message(generate_payload(entity, remote_user_on_pod_c, recipient), recipient)
expect(target_object.class.exists?(guid: target_object.guid)).to be_truthy
end
@@ -34,16 +34,16 @@ end
shared_examples_for "it retracts relayable object" do
it "retracts object by a correct message" do
- entity = retraction_entity(entity_name, target_object, sender)
- post_message(generate_xml(entity, sender, recipient), recipient)
+ entity = retraction_entity(target_object, sender)
+ post_message(generate_payload(entity, sender, recipient), recipient)
expect(target_object.class.exists?(guid: target_object.guid)).to be_falsey
end
it "doesn't retract object when retraction has wrong signatures" do
allow(sender).to receive(:encryption_key).and_return(OpenSSL::PKey::RSA.new(1024))
- entity = retraction_entity(entity_name, target_object, sender)
- post_message(generate_xml(entity, sender, recipient), recipient)
+ entity = retraction_entity(target_object, sender)
+ post_message(generate_payload(entity, sender, recipient), recipient)
expect(target_object.class.exists?(guid: target_object.guid)).to be_truthy
end
diff --git a/spec/integration/federation/shared_receive_stream_items.rb b/spec/integration/federation/shared_receive_stream_items.rb
index 391c194cf..86cb4125b 100644
--- a/spec/integration/federation/shared_receive_stream_items.rb
+++ b/spec/integration/federation/shared_receive_stream_items.rb
@@ -4,18 +4,18 @@ shared_examples_for "messages which are indifferent about sharing fact" do
let(:public) { recipient.nil? }
it "treats status message receive correctly" do
- entity = FactoryGirl.build(:status_message_entity, author: sender_id, public: public)
+ entity = Fabricate(:status_message_entity, author: sender_id, public: public)
- post_message(generate_xml(entity, sender, recipient), recipient)
+ post_message(generate_payload(entity, sender, recipient), recipient)
expect(StatusMessage.exists?(guid: entity.guid)).to be_truthy
end
it "doesn't accept status message with wrong signature" do
allow(sender).to receive(:encryption_key).and_return(OpenSSL::PKey::RSA.new(1024))
- entity = FactoryGirl.build(:status_message_entity, author: sender_id, public: public)
+ entity = Fabricate(:status_message_entity, author: sender_id, public: public)
- post_message(generate_xml(entity, sender, recipient), recipient)
+ post_message(generate_payload(entity, sender, recipient), recipient)
expect(StatusMessage.exists?(guid: entity.guid)).to be_falsey
end
@@ -27,7 +27,7 @@ shared_examples_for "messages which are indifferent about sharing fact" do
describe "notifications are sent where required" do
it "for comment on local post" do
entity = create_relayable_entity(:comment_entity, local_parent, remote_user_on_pod_b.diaspora_handle)
- post_message(generate_xml(entity, sender, recipient), recipient)
+ post_message(generate_payload(entity, sender, recipient), recipient)
expect(
Notifications::CommentOnPost.exists?(
@@ -40,7 +40,7 @@ shared_examples_for "messages which are indifferent about sharing fact" do
it "for like on local post" do
entity = create_relayable_entity(:like_entity, local_parent, remote_user_on_pod_b.diaspora_handle)
- post_message(generate_xml(entity, sender, recipient), recipient)
+ post_message(generate_payload(entity, sender, recipient), recipient)
expect(
Notifications::Liked.exists?(
@@ -62,11 +62,18 @@ shared_examples_for "messages which are indifferent about sharing fact" do
end
context "with participations" do
- let(:entity) { create_relayable_entity(:participation_entity, local_parent, sender_id) }
+ let(:entity) {
+ Fabricate(
+ :participation_entity,
+ author: sender_id,
+ parent_guid: local_parent.guid,
+ parent: Diaspora::Federation::Entities.related_entity(local_parent)
+ )
+ }
it "treats participation receive correctly" do
expect(Workers::ReceiveLocal).to receive(:perform_async)
- post_message(generate_xml(entity, sender, recipient), recipient)
+ post_message(generate_payload(entity, sender, recipient), recipient)
received_entity = Participation.find_by(guid: entity.guid)
expect(received_entity).not_to be_nil
@@ -77,7 +84,7 @@ shared_examples_for "messages which are indifferent about sharing fact" do
expect(Workers::ReceiveLocal).not_to receive(:perform_async)
entity = create_relayable_entity(:participation_entity, remote_parent, sender_id)
- post_message(generate_xml(entity, sender, recipient), recipient)
+ post_message(generate_payload(entity, sender, recipient), recipient)
expect(Participation.exists?(guid: entity.guid)).to be_falsey
end
@@ -107,17 +114,11 @@ end
shared_examples_for "messages which can't be send without sharing" do
# retractions shouldn't depend on sharing fact
describe "retractions for non-relayable objects" do
- %w(retraction signed_retraction).each do |retraction_entity_name|
- context "with #{retraction_entity_name}" do
- let(:entity_name) { "#{retraction_entity_name}_entity".to_sym }
+ %w[status_message photo].each do |target|
+ context "with #{target}" do
+ let(:target_object) { FactoryGirl.create(target.to_sym, author: remote_user_on_pod_b.person) }
- %w(status_message photo).each do |target|
- context "with #{target}" do
- let(:target_object) { FactoryGirl.create(target.to_sym, author: remote_user_on_pod_b.person) }
-
- it_behaves_like "it retracts non-relayable object"
- end
- end
+ it_behaves_like "it retracts non-relayable object"
end
end
end
@@ -133,7 +134,7 @@ shared_examples_for "messages which can't be send without sharing" do
alice.participate!(remote_parent)
author_id = remote_user_on_pod_c.diaspora_handle
entity = create_relayable_entity(:comment_entity, remote_parent, author_id)
- post_message(generate_xml(entity, sender, recipient), recipient)
+ post_message(generate_payload(entity, sender, recipient), recipient)
expect(
Notifications::AlsoCommented.exists?(
@@ -146,47 +147,41 @@ shared_examples_for "messages which can't be send without sharing" do
end
describe "retractions for relayable objects" do
- %w(retraction signed_retraction relayable_retraction).each do |retraction_entity_name|
- context "with #{retraction_entity_name}" do
- let(:entity_name) { "#{retraction_entity_name}_entity".to_sym }
-
- before do
- allow(DiasporaFederation.callbacks).to receive(:trigger).with(
- :fetch_private_key, alice.diaspora_handle
- ) { alice.encryption_key }
- end
-
- context "with comment" do
- it_behaves_like "it retracts relayable object" do
- # case for to-upstream federation
- let(:target_object) {
- FactoryGirl.create(:comment, author: remote_user_on_pod_b.person, post: local_parent)
- }
- end
-
- it_behaves_like "it retracts relayable object" do
- # case for to-downsteam federation
- let(:target_object) {
- FactoryGirl.create(:comment, author: remote_user_on_pod_c.person, post: remote_parent)
- }
- end
- end
-
- context "with like" do
- it_behaves_like "it retracts relayable object" do
- # case for to-upstream federation
- let(:target_object) {
- FactoryGirl.create(:like, author: remote_user_on_pod_b.person, target: local_parent)
- }
- end
-
- it_behaves_like "it retracts relayable object" do
- # case for to-downsteam federation
- let(:target_object) {
- FactoryGirl.create(:like, author: remote_user_on_pod_c.person, target: remote_parent)
- }
- end
- end
+ before do
+ allow(DiasporaFederation.callbacks).to receive(:trigger).with(
+ :fetch_private_key, alice.diaspora_handle
+ ) { alice.encryption_key }
+ end
+
+ context "with comment" do
+ it_behaves_like "it retracts relayable object" do
+ # case for to-upstream federation
+ let(:target_object) {
+ FactoryGirl.create(:comment, author: remote_user_on_pod_b.person, post: local_parent)
+ }
+ end
+
+ it_behaves_like "it retracts relayable object" do
+ # case for to-downsteam federation
+ let(:target_object) {
+ FactoryGirl.create(:comment, author: remote_user_on_pod_c.person, post: remote_parent)
+ }
+ end
+ end
+
+ context "with like" do
+ it_behaves_like "it retracts relayable object" do
+ # case for to-upstream federation
+ let(:target_object) {
+ FactoryGirl.create(:like, author: remote_user_on_pod_b.person, target: local_parent)
+ }
+ end
+
+ it_behaves_like "it retracts relayable object" do
+ # case for to-downsteam federation
+ let(:target_object) {
+ FactoryGirl.create(:like, author: remote_user_on_pod_c.person, target: remote_parent)
+ }
end
end
end
diff --git a/spec/integration/mentioning_spec.rb b/spec/integration/mentioning_spec.rb
index 8b8af8d0b..41a231d3e 100644
--- a/spec/integration/mentioning_spec.rb
+++ b/spec/integration/mentioning_spec.rb
@@ -1,10 +1,39 @@
module MentioningSpecHelpers
- def default_aspect
- @user1.aspects.where(name: "generic").first
+ def notifications_about_mentioning(user, object)
+ table = object.class.table_name
+
+ if object.is_a?(StatusMessage)
+ klass = Notifications::MentionedInPost
+ elsif object.is_a?(Comment)
+ klass = Notifications::MentionedInComment
+ end
+
+ klass
+ .where(recipient_id: user.id)
+ .joins("LEFT OUTER JOIN mentions ON notifications.target_id = mentions.id AND "\
+ "notifications.target_type = 'Mention'")
+ .joins("LEFT OUTER JOIN #{table} ON mentions_container_id = #{table}.id AND "\
+ "mentions_container_type = '#{object.class.base_class}'").where(table.to_sym => {id: object.id})
+ end
+
+ def mention_container_path(object)
+ object.is_a?(Post) ? post_path(object) : post_path(object.parent, anchor: object.guid)
+ end
+
+ def mentioning_mail_notification(user, object)
+ ActionMailer::Base.deliveries.select {|delivery|
+ delivery.to.include?(user.email) &&
+ delivery.subject.include?(I18n.t("notifier.mentioned.subject", name: "")) &&
+ delivery.body.parts[0].body.include?(mention_container_path(object))
+ }
end
- def text_mentioning(user)
- "this is a text mentioning @{#{user.name}; #{user.diaspora_handle}} ... have fun testing!"
+ def also_commented_mail_notification(user, post)
+ ActionMailer::Base.deliveries.select {|delivery|
+ delivery.to.include?(user.email) &&
+ delivery.subject.include?(I18n.t("notifier.also_commented.limited_subject")) &&
+ delivery.body.parts[0].body.include?(post_path(post))
+ }
end
def stream_for(user)
@@ -17,77 +46,351 @@ module MentioningSpecHelpers
stream.posts
end
- def users_connected?(user1, user2)
- user1.contacts.where(person_id: user2.person).count > 0
+ def post_status_message(mentioned_user, aspects=nil)
+ aspects = user1.aspects.first.id.to_s if aspects.nil?
+ sign_in user1
+ status_msg = nil
+ inlined_jobs do
+ post "/status_messages.json", params: {
+ status_message: {text: text_mentioning(mentioned_user)},
+ aspect_ids: aspects
+ }
+ status_msg = StatusMessage.find(JSON.parse(response.body)["id"])
+ end
+ status_msg
end
-end
+ def receive_each(entity, recipients)
+ inlined_jobs do
+ recipients.each do |recipient|
+ DiasporaFederation.callbacks.trigger(:receive_entity, entity, entity.author, recipient.id)
+ end
+ end
+ end
+
+ def find_private_message(guid)
+ StatusMessage.find_by(guid: guid).tap do |status_msg|
+ expect(status_msg).not_to be_nil
+ expect(status_msg.public?).to be false
+ end
+ end
+
+ def receive_status_message_via_federation(text, *recipients)
+ entity = Fabricate(
+ :status_message_entity,
+ author: remote_raphael.diaspora_handle,
+ text: text,
+ public: false
+ )
+
+ expect {
+ receive_each(entity, recipients)
+ }.to change(Post, :count).by(1).and change(ShareVisibility, :count).by(recipients.count)
+
+ find_private_message(entity.guid)
+ end
+
+ def receive_comment_via_federation(text, parent)
+ entity = build_relayable_federation_entity(
+ :comment,
+ parent_guid: parent.guid,
+ author: remote_raphael.diaspora_handle,
+ parent: Diaspora::Federation::Entities.related_entity(parent),
+ text: text
+ )
+
+ receive_each(entity, [parent.author.owner])
+
+ Comment.find_by(guid: entity.guid)
+ end
+end
describe "mentioning", type: :request do
include MentioningSpecHelpers
- before do
- @user1 = FactoryGirl.create :user_with_aspect
- @user2 = FactoryGirl.create :user
- @user3 = FactoryGirl.create :user
+ RSpec::Matchers.define :be_mentioned_in do |object|
+ include Rails.application.routes.url_helpers
+
+ def user_notified?(user, object)
+ notifications_about_mentioning(user, object).any? && mentioning_mail_notification(user, object).any?
+ end
+
+ match do |user|
+ object.message.markdownified.include?(person_path(id: user.person.guid)) && user_notified?(user, object)
+ end
- @user1.share_with(@user2.person, default_aspect)
- sign_in @user1
+ match_when_negated do |user|
+ !user_notified?(user, object)
+ end
end
- # see: https://github.com/diaspora/diaspora/issues/4160
- it "doesn't mention people that aren't in the target aspect" do
- expect(users_connected?(@user1, @user3)).to be false
+ RSpec::Matchers.define :be_in_streams_of do |user|
+ match do |status_message|
+ stream_for(user).map(&:id).include?(status_message.id) &&
+ mention_stream_for(user).map(&:id).include?(status_message.id)
+ end
+
+ match_when_negated do |status_message|
+ !stream_for(user).map(&:id).include?(status_message.id) &&
+ !mention_stream_for(user).map(&:id).include?(status_message.id)
+ end
+ end
+ let(:user1) { FactoryGirl.create(:user_with_aspect) }
+ let(:user2) { FactoryGirl.create(:user_with_aspect, friends: [user1, user3]) }
+ let(:user3) { FactoryGirl.create(:user_with_aspect) }
+
+ # see: https://github.com/diaspora/diaspora/issues/4160
+ it "only mentions people that are in the target aspect" do
status_msg = nil
expect {
- post "/status_messages.json", status_message: {text: text_mentioning(@user3)}, aspect_ids: default_aspect.id.to_s
- status_msg = StatusMessage.find(JSON.parse(response.body)["id"])
+ status_msg = post_status_message(user3)
}.to change(Post, :count).by(1).and change(AspectVisibility, :count).by(1)
expect(status_msg).not_to be_nil
expect(status_msg.public?).to be false
- expect(status_msg.text).to include(@user3.name)
- expect(status_msg.text).not_to include(@user3.diaspora_handle)
- expect(status_msg.text).to include(user_profile_path(username: @user3.username))
+ expect(status_msg.text).to include(user3.name)
- expect(stream_for(@user3).map(&:id)).not_to include(status_msg.id)
- expect(mention_stream_for(@user3).map(&:id)).not_to include(status_msg.id)
+ expect(user3).not_to be_mentioned_in(status_msg)
+ expect(status_msg).not_to be_in_streams_of(user3)
end
- it "mentions people in public posts" do
- expect(users_connected?(@user1, @user3)).to be false
+ context "in private post via federation" do
+ let(:status_msg) {
+ receive_status_message_via_federation(text_mentioning(user2, user3), user3)
+ }
+
+ it "receiver is mentioned in status message" do
+ expect(user3).to be_mentioned_in(status_msg)
+ end
+
+ it "receiver can see status message in streams" do
+ expect(status_msg).to be_in_streams_of(user3)
+ end
+
+ it "non-receiver is not mentioned in status message" do
+ expect(user2).not_to be_mentioned_in(status_msg)
+ end
+
+ it "non-receiver can't see status message in streams" do
+ expect(status_msg).not_to be_in_streams_of(user2)
+ end
+ end
+
+ context "in private post via federation with multiple recipients" do
+ let(:status_msg) {
+ receive_status_message_via_federation(text_mentioning(user3, user2), user3, user2)
+ }
+
+ it "mentions all recipients in the status message" do
+ [user2, user3].each do |user|
+ expect(user).to be_mentioned_in(status_msg)
+ end
+ end
+ it "all recipients can see status message in streams" do
+ [user2, user3].each do |user|
+ expect(status_msg).to be_in_streams_of(user)
+ end
+ end
+ end
+
+ it "mentions people in public posts" do
status_msg = nil
expect {
- post "/status_messages.json", status_message: {text: text_mentioning(@user3)}, aspect_ids: "public"
- status_msg = StatusMessage.find(JSON.parse(response.body)["id"])
+ status_msg = post_status_message(user3, "public")
}.to change(Post, :count).by(1)
expect(status_msg).not_to be_nil
expect(status_msg.public?).to be true
- expect(status_msg.text).to include(@user3.name)
- expect(status_msg.text).to include(@user3.diaspora_handle)
+ expect(status_msg.text).to include(user3.name)
+ expect(status_msg.text).to include(user3.diaspora_handle)
- expect(stream_for(@user3).map(&:id)).to include(status_msg.id)
- expect(mention_stream_for(@user3).map(&:id)).to include(status_msg.id)
+ expect(user3).to be_mentioned_in(status_msg)
+ expect(status_msg).to be_in_streams_of(user3)
end
it "mentions people that are in the target aspect" do
- expect(users_connected?(@user1, @user2)).to be true
-
status_msg = nil
expect {
- post "/status_messages.json", status_message: {text: text_mentioning(@user2)}, aspect_ids: default_aspect.id.to_s
- status_msg = StatusMessage.find(JSON.parse(response.body)["id"])
+ status_msg = post_status_message(user2)
}.to change(Post, :count).by(1).and change(AspectVisibility, :count).by(1)
expect(status_msg).not_to be_nil
expect(status_msg.public?).to be false
- expect(status_msg.text).to include(@user2.name)
- expect(status_msg.text).to include(@user2.diaspora_handle)
+ expect(status_msg.text).to include(user2.name)
+ expect(status_msg.text).to include(user2.diaspora_handle)
+
+ expect(user2).to be_mentioned_in(status_msg)
+ expect(status_msg).to be_in_streams_of(user2)
+ end
+
+ context "in comments" do
+ let(:author) { FactoryGirl.create(:user_with_aspect) }
+
+ shared_context "commenter is author" do
+ let(:commenter) { author }
+ end
+
+ shared_context "commenter is author's friend" do
+ let(:commenter) { FactoryGirl.create(:user_with_aspect, friends: [author]) }
+ end
+
+ shared_context "commenter is not author's friend" do
+ let(:commenter) { FactoryGirl.create(:user) }
+ end
+
+ shared_context "mentioned user is author" do
+ let(:mentioned_user) { author }
+ end
+
+ shared_context "mentioned user is author's friend" do
+ let(:mentioned_user) { FactoryGirl.create(:user_with_aspect, friends: [author]) }
+ end
+
+ shared_context "mentioned user is not author's friend" do
+ let(:mentioned_user) { FactoryGirl.create(:user) }
+ end
+
+ context "with public post" do
+ let(:status_msg) { FactoryGirl.create(:status_message, author: author.person, public: true) }
+
+ [
+ ["commenter is author's friend", "mentioned user is not author's friend"],
+ ["commenter is author's friend", "mentioned user is author"],
+ ["commenter is not author's friend", "mentioned user is author's friend"],
+ ["commenter is not author's friend", "mentioned user is not author's friend"],
+ ["commenter is author", "mentioned user is author's friend"],
+ ["commenter is author", "mentioned user is not author's friend"]
+ ].each do |commenters_context, mentioned_context|
+ context "when #{commenters_context} and #{mentioned_context}" do
+ include_context commenters_context
+ include_context mentioned_context
+
+ let(:comment) {
+ inlined_jobs do
+ commenter.comment!(status_msg, text_mentioning(mentioned_user))
+ end
+ }
+
+ subject { mentioned_user }
+ it { is_expected.to be_mentioned_in(comment) }
+ end
+ end
+
+ context "when comment is received via federation" do
+ context "when mentioned user is remote" do
+ it "relays the comment to the mentioned user" do
+ mentioned_person = FactoryGirl.create(:person)
+ expect_any_instance_of(Diaspora::Federation::Dispatcher::Public)
+ .to receive(:deliver_to_remote).with([mentioned_person])
+
+ receive_comment_via_federation(text_mentioning(mentioned_person), status_msg)
+ end
+ end
+ end
+ end
+
+ context "with private post" do
+ [
+ ["commenter is author's friend", "mentioned user is author's friend"],
+ ["commenter is author", "mentioned user is author's friend"],
+ ["commenter is author's friend", "mentioned user is author"]
+ ].each do |commenters_context, mentioned_context|
+ context "when #{commenters_context} and #{mentioned_context}" do
+ include_context commenters_context
+ include_context mentioned_context
+
+ let(:parent) { FactoryGirl.create(:status_message_in_aspect, author: author.person) }
+ let(:comment) {
+ inlined_jobs do
+ commenter.comment!(parent, text_mentioning(mentioned_user))
+ end
+ }
+
+ before do
+ mentioned_user.like!(parent)
+ end
+
+ subject { mentioned_user }
+ it { is_expected.to be_mentioned_in(comment) }
+ end
+ end
+
+ context "when comment is received via federation" do
+ let(:parent) { FactoryGirl.create(:status_message_in_aspect, author: user2.person) }
+
+ before do
+ user3.like!(parent)
+ user1.like!(parent)
+ end
+
+ let(:comment_text) { text_mentioning(user2, user3, user1) }
+ let(:comment) { receive_comment_via_federation(comment_text, parent) }
+
+ it "mentions all the recepients" do
+ [user1, user2, user3].each do |user|
+ expect(user).to be_mentioned_in(comment)
+ end
+ end
+
+ context "with only post author mentioned" do
+ let(:post_author) { parent.author.owner }
+ let(:comment_text) { text_mentioning(post_author) }
+
+ it "makes only one notification for each recipient" do
+ expect {
+ comment
+ }.to change { Notifications::MentionedInComment.for(post_author).count }.by(1)
+ .and change { Notifications::AlsoCommented.for(user1).count }.by(1)
+ .and change { Notifications::AlsoCommented.for(user3).count }.by(1)
+
+ expect(mentioning_mail_notification(post_author, comment).count).to eq(1)
+
+ [user1, user3].each do |user|
+ expect(also_commented_mail_notification(user, parent).count).to eq(1)
+ end
+ end
+ end
+ end
+
+ context "commenter can't mention a non-participant" do
+ let(:status_msg) { FactoryGirl.create(:status_message_in_aspect, author: author.person) }
+
+ [
+ ["commenter is author's friend", "mentioned user is not author's friend"],
+ ["commenter is not author's friend", "mentioned user is author's friend"],
+ ["commenter is not author's friend", "mentioned user is not author's friend"],
+ ["commenter is author", "mentioned user is author's friend"],
+ ["commenter is author", "mentioned user is not author's friend"]
+ ].each do |commenters_context, mentioned_context|
+ context "when #{commenters_context} and #{mentioned_context}" do
+ include_context commenters_context
+ include_context mentioned_context
+
+ let(:comment) {
+ inlined_jobs do
+ commenter.comment!(status_msg, text_mentioning(mentioned_user))
+ end
+ }
+
+ subject { mentioned_user }
+ it { is_expected.not_to be_mentioned_in(comment) }
+ end
+ end
+ end
+
+ it "only creates one notification for the mentioned person, when mentioned person commented twice before" do
+ parent = FactoryGirl.create(:status_message_in_aspect, author: author.person)
+ mentioned_user = FactoryGirl.create(:user_with_aspect, friends: [author])
+ mentioned_user.comment!(parent, "test comment 1")
+ mentioned_user.comment!(parent, "test comment 2")
+ comment = inlined_jobs do
+ author.comment!(parent, text_mentioning(mentioned_user))
+ end
- expect(stream_for(@user2).map(&:id)).to include(status_msg.id)
- expect(mention_stream_for(@user2).map(&:id)).to include(status_msg.id)
+ expect(notifications_about_mentioning(mentioned_user, comment).count).to eq(1)
+ end
+ end
end
end
diff --git a/spec/integration/mobile_posts_spec.rb b/spec/integration/mobile_posts_spec.rb
index 1ffd10a79..1b5e53509 100644
--- a/spec/integration/mobile_posts_spec.rb
+++ b/spec/integration/mobile_posts_spec.rb
@@ -3,7 +3,7 @@ describe PostsController, type: :request do
let(:sm) { FactoryGirl.build(:status_message_with_poll, public: true) }
it "displays the poll" do
- get "/posts/#{sm.id}", format: :mobile
+ get "/posts/#{sm.id}", params: {format: :mobile}
expect(response.status).to eq(200)
expect(response.body).to match(/div class='poll'/)
@@ -13,7 +13,7 @@ describe PostsController, type: :request do
it "displays the correct percentage for the answers" do
alice.participate_in_poll!(sm, sm.poll.poll_answers.first)
bob.participate_in_poll!(sm, sm.poll.poll_answers.last)
- get "/posts/#{sm.id}", format: :mobile
+ get "/posts/#{sm.id}", params: {format: :mobile}
expect(response.status).to eq(200)
expect(response.body).to match(/div class='percentage pull-right'>\n50%/)
@@ -24,7 +24,7 @@ describe PostsController, type: :request do
let(:sm) { FactoryGirl.build(:status_message_with_location, public: true) }
it "displays the location" do
- get "/posts/#{sm.id}", format: :mobile
+ get "/posts/#{sm.id}", params: {format: :mobile}
expect(response.status).to eq(200)
expect(response.body).to match(/'location nsfw-hidden'/)
diff --git a/spec/integration/tag_people_spec.rb b/spec/integration/tag_people_spec.rb
index 336b7acf0..22b07d851 100644
--- a/spec/integration/tag_people_spec.rb
+++ b/spec/integration/tag_people_spec.rb
@@ -1,4 +1,4 @@
-describe TagsController, :type => :request do
+describe TagsController, type: :request do
describe 'will_paginate people on the tag page' do
let(:people) { (1..2).map { FactoryGirl.create(:person) } }
let(:tag) { "diaspora" }
@@ -17,7 +17,7 @@ describe TagsController, :type => :request do
end
it 'fetches the second page' do
- get "/tags/#{tag}", page: 2
+ get "/tags/#{tag}", params: {page: 2}
expect(response.status).to eq(200)
expect(response.body).to match(/<li class="active"><a href="\/tags\/diaspora\?page=2">2<\/a><\/li>/)
diff --git a/spec/javascripts/app/app_spec.js b/spec/javascripts/app/app_spec.js
index 1ade3b556..378ab84f3 100644
--- a/spec/javascripts/app/app_spec.js
+++ b/spec/javascripts/app/app_spec.js
@@ -1,4 +1,9 @@
describe("app", function() {
+ afterAll(function() {
+ Backbone.history.stop();
+ app.initialize();
+ });
+
describe("initialize", function() {
it("calls several setup functions", function() {
spyOn(app.Router.prototype, "initialize");
@@ -62,6 +67,10 @@ describe("app", function() {
});
describe("setupAjaxErrorRedirect", function() {
+ beforeEach(function() {
+ app.setupAjaxErrorRedirect();
+ });
+
it("redirects to /users/sign_in on 401 ajax responses", function() {
spyOn(app, "_changeLocation");
$.ajax("/test");
@@ -105,6 +114,10 @@ describe("app", function() {
});
describe("setupBackboneLinks", function() {
+ beforeEach(function() {
+ Backbone.history.stop();
+ });
+
it("calls Backbone.history.start", function() {
spyOn(Backbone.history, "start");
app.setupBackboneLinks();
@@ -115,7 +128,6 @@ describe("app", function() {
beforeEach(function() {
app.stream = {basePath: function() { return "/stream"; }};
app.notificationsCollection = {fetch: $.noop};
- spyOn(Backbone.history, "start");
this.link = $("<a href='/backbone-link' rel='backbone'>");
spec.content().append(this.link);
app.setupBackboneLinks();
diff --git a/spec/javascripts/app/models/stream_spec.js b/spec/javascripts/app/models/stream_spec.js
index 0778dbf1f..e107a0d52 100644
--- a/spec/javascripts/app/models/stream_spec.js
+++ b/spec/javascripts/app/models/stream_spec.js
@@ -7,6 +7,38 @@ describe("app.models.Stream", function() {
expectedPath = document.location.pathname;
});
+ describe("collectionOptions", function() {
+ beforeEach(function() {
+ this.post1 = new app.models.Post({"id": 1, "created_at": 12, "interacted_at": 123});
+ this.post2 = new app.models.Post({"id": 2, "created_at": 13, "interacted_at": 123});
+ this.post3 = new app.models.Post({"id": 3, "created_at": 13, "interacted_at": 122});
+ this.post4 = new app.models.Post({"id": 4, "created_at": 10, "interacted_at": 100});
+ });
+
+ it("returns a comparator for posts that compares created_at and ids by default", function() {
+ this.options = stream.collectionOptions();
+ expect(this.options.comparator(this.post1, this.post2)).toBe(1);
+ expect(this.options.comparator(this.post2, this.post1)).toBe(-1);
+ expect(this.options.comparator(this.post2, this.post3)).toBe(1);
+ expect(this.options.comparator(this.post3, this.post2)).toBe(-1);
+ expect(this.options.comparator(this.post1, this.post4)).toBe(-1);
+ expect(this.options.comparator(this.post4, this.post1)).toBe(1);
+ expect(this.options.comparator(this.post1, this.post1)).toBe(0);
+ });
+
+ it("returns a comparator for posts that compares interacted_at and ids for the activity stream", function() {
+ spyOn(stream, "basePath").and.returnValue("activity");
+ this.options = stream.collectionOptions();
+ expect(this.options.comparator(this.post1, this.post2)).toBe(1);
+ expect(this.options.comparator(this.post2, this.post1)).toBe(-1);
+ expect(this.options.comparator(this.post2, this.post3)).toBe(-1);
+ expect(this.options.comparator(this.post3, this.post2)).toBe(1);
+ expect(this.options.comparator(this.post1, this.post4)).toBe(-1);
+ expect(this.options.comparator(this.post4, this.post1)).toBe(1);
+ expect(this.options.comparator(this.post1, this.post1)).toBe(0);
+ });
+ });
+
describe("#_fetchOpts", function() {
it("it fetches posts from the window's url, and ads them to the collection", function() {
expect( stream._fetchOpts() ).toEqual({ remove: false, url: expectedPath});
diff --git a/spec/javascripts/app/pages/single-post-viewer_spec.js b/spec/javascripts/app/pages/single-post-viewer_spec.js
index df8f9c43c..c1db51394 100644
--- a/spec/javascripts/app/pages/single-post-viewer_spec.js
+++ b/spec/javascripts/app/pages/single-post-viewer_spec.js
@@ -1,6 +1,7 @@
describe("app.pages.SinglePostViewer", function(){
beforeEach(function() {
- window.gon={};gon.post = {id: 42};
+ window.gon = {};
+ gon.post = $.parseJSON(spec.readFixture("post_json"));
this.view = new app.pages.SinglePostViewer();
});
diff --git a/spec/javascripts/app/router_spec.js b/spec/javascripts/app/router_spec.js
index c6ac8653d..14e6dd2df 100644
--- a/spec/javascripts/app/router_spec.js
+++ b/spec/javascripts/app/router_spec.js
@@ -112,6 +112,13 @@ describe('app.Router', function () {
this.router.conversations("12");
expect(app.views.ConversationsInbox.prototype.renderConversation).toHaveBeenCalledWith("12");
});
+
+ it("passes conversation_id parameter to ConversationsInbox initializer when passed in URL", function() {
+ app.conversations = undefined;
+ spyOn(app.views.ConversationsInbox.prototype, "initialize");
+ this.router.navigate("/conversations?conversation_id=45", {trigger: true});
+ expect(app.views.ConversationsInbox.prototype.initialize).toHaveBeenCalledWith("45");
+ });
});
describe("stream", function() {
diff --git a/spec/javascripts/app/views/bookmarklet_view_spec.js b/spec/javascripts/app/views/bookmarklet_view_spec.js
index d5de57466..9d12f998c 100644
--- a/spec/javascripts/app/views/bookmarklet_view_spec.js
+++ b/spec/javascripts/app/views/bookmarklet_view_spec.js
@@ -29,23 +29,18 @@ describe("app.views.Bookmarklet", function() {
it("prefills the publisher", function() {
init_bookmarklet(test_data);
-
expect($.trim(app.publisher.inputEl.val())).not.toEqual("");
- expect($.trim(app.publisher.hiddenInputEl.val())).not.toEqual("");
});
it("handles dirty input well", function() {
init_bookmarklet(evil_test_data);
-
expect($.trim(app.publisher.inputEl.val())).not.toEqual("");
- expect($.trim(app.publisher.hiddenInputEl.val())).not.toEqual("");
});
it("allows changing a prefilled publisher", function() {
init_bookmarklet(test_data);
app.publisher.setText(app.publisher.inputEl.val()+"A");
-
- expect(app.publisher.hiddenInputEl.val()).toMatch(/.+A$/);
+ expect(app.publisher.inputEl.val()).toMatch(/.+A$/);
});
it("keeps the publisher disabled after successful post creation", function() {
diff --git a/spec/javascripts/app/views/comment_mention_view_spec.js b/spec/javascripts/app/views/comment_mention_view_spec.js
new file mode 100644
index 000000000..8de7c0f3f
--- /dev/null
+++ b/spec/javascripts/app/views/comment_mention_view_spec.js
@@ -0,0 +1,10 @@
+describe("app.views.CommentMention", function() {
+ describe("initialize", function() {
+ it("passes correct URL to PublisherMention contructor", function() {
+ spyOn(app.views.PublisherMention.prototype, "initialize");
+ new app.views.CommentMention({postId: 123});
+ var call = app.views.PublisherMention.prototype.initialize.calls.mostRecent();
+ expect(call.args[0].url).toEqual("/posts/123/mentionable");
+ });
+ });
+});
diff --git a/spec/javascripts/app/views/comment_stream_view_spec.js b/spec/javascripts/app/views/comment_stream_view_spec.js
index ecac07333..284b16c7a 100644
--- a/spec/javascripts/app/views/comment_stream_view_spec.js
+++ b/spec/javascripts/app/views/comment_stream_view_spec.js
@@ -19,6 +19,16 @@ describe("app.views.CommentStream", function(){
this.view.model.comments.pop();
expect(this.view.removeComment).toHaveBeenCalled();
});
+
+ it("calls onFormBlur when clicking outside the comment box", function() {
+ // remove existing event handlers
+ $(document.body).off("click");
+
+ spyOn(this.view, "onFormBlur");
+ this.view.setupBindings();
+ $(document.body).click();
+ expect(this.view.onFormBlur).toHaveBeenCalled();
+ });
});
describe("postRenderTemplate", function() {
@@ -50,6 +60,38 @@ describe("app.views.CommentStream", function(){
expect(this.view.commentSubmitButton).toBeDefined();
expect(this.view.commentSubmitButton).toEqual(this.view.$("input[name='commit']"));
});
+
+ it("sets mentions", function() {
+ spyOn(app.views.CommentMention.prototype, "initialize");
+ this.view.mentions = undefined;
+ this.view.postRenderTemplate();
+ var call = app.views.CommentMention.prototype.initialize.calls.mostRecent();
+ expect(call.args[0]).toEqual({el: this.view.$el, postId: this.view.model.id});
+ expect(this.view.mentions).toBeDefined();
+ });
+
+ it("creates the markdown editor", function() {
+ spyOn(Diaspora.MarkdownEditor.prototype, "initialize");
+ this.view.mdEditor = undefined;
+ this.view.postRenderTemplate();
+ expect(Diaspora.MarkdownEditor.prototype.initialize).toHaveBeenCalled();
+ expect(this.view.mdEditor).toBeDefined();
+ });
+
+ it("adds a preview method to the markdown editor that renders mentions", function() {
+ this.view.postRenderTemplate();
+ var mdInstance = {getContent: function() { return "@{test@example.org}"; }};
+ spyOn(this.view.mentions, "getMentionedPeople").and.returnValue([{
+ name: "Alice Awesome",
+ handle: "test@example.org",
+ id: "4",
+ guid: "123abc"
+ }]);
+ var renderedPreview = this.view.mdEditor.options.onPreview(mdInstance),
+ renderedText = app.helpers.textFormatter("@{test@example.org}", this.view.mentions.getMentionedPeople());
+ expect(renderedPreview).toBe("<div class='preview-content'>" + renderedText + "</div>");
+ expect(renderedPreview).toContain("Alice Awesome");
+ });
});
describe("createComment", function() {
@@ -110,6 +152,18 @@ describe("app.views.CommentStream", function(){
this.request.respondWith({status: 200, responseText: "[]"});
expect(autosize.update).toHaveBeenCalledWith(this.view.commentBox);
});
+
+ it("hides the markdown preview", function() {
+ spyOn(this.view.mdEditor, "hidePreview");
+ this.request.respondWith({status: 200, responseText: "[]"});
+ expect(this.view.mdEditor.hidePreview).toHaveBeenCalled();
+ });
+
+ it("closes the form", function() {
+ spyOn(this.view, "closeForm");
+ this.request.respondWith({status: 200, responseText: "[]"});
+ expect(this.view.closeForm).toHaveBeenCalled();
+ });
});
context("on error", function() {
@@ -128,6 +182,18 @@ describe("app.views.CommentStream", function(){
this.request.respondWith({status: 500});
expect(this.view.enableCommentBox).toHaveBeenCalled();
});
+
+ it("hides the markdown preview", function() {
+ spyOn(this.view.mdEditor, "hidePreview");
+ this.request.respondWith({status: 500, responseText: "[]"});
+ expect(this.view.mdEditor.hidePreview).toHaveBeenCalled();
+ });
+
+ it("opens the form", function() {
+ spyOn(this.view, "openForm");
+ this.request.respondWith({status: 500, responseText: "[]"});
+ expect(this.view.openForm).toHaveBeenCalled();
+ });
});
});
});
@@ -201,6 +267,14 @@ describe("app.views.CommentStream", function(){
expect(this.view.$(".comments div.comment.media").length).toEqual(6);
expect(this.view.$(".comments div.comment.media div.comment-content p").text()).toEqual("123456");
});
+
+ it("calls renderPluginWidgets", function() {
+ var comment = factory.comment();
+ this.view.CommentView = app.views.Comment;
+ spyOn(app.views.Comment.prototype, "renderPluginWidgets");
+ this.view.appendComment(comment);
+ expect(app.views.Comment.prototype.renderPluginWidgets).toHaveBeenCalled();
+ });
});
describe("removeComment", function() {
@@ -276,6 +350,84 @@ describe("app.views.CommentStream", function(){
});
});
+ describe("openForm", function() {
+ beforeEach(function() {
+ this.view.render();
+ });
+
+ it("adds the 'open' class to form", function() {
+ this.view.$("form").removeClass("open");
+ this.view.openForm();
+ expect(this.view.$("form")).toHaveClass("open");
+ });
+
+ it("adds the 'active' class to markdown editor", function() {
+ this.view.$(".md-editor").removeClass("active");
+ this.view.openForm();
+ expect(this.view.$(".md-editor")).toHaveClass("active");
+ });
+ });
+
+ describe("closeForm", function() {
+ beforeEach(function() {
+ this.view.render();
+ });
+
+ it("removes the 'open' class to form", function() {
+ this.view.$("form").addClass("open");
+ this.view.closeForm();
+ expect(this.view.$("form")).not.toHaveClass("open");
+ });
+
+ it("removes the 'active' class to markdown editor", function() {
+ this.view.$(".md-editor").addClass("active");
+ this.view.closeForm();
+ expect(this.view.$(".md-editor")).not.toHaveClass("active");
+ });
+ });
+
+ describe("onFormBlur", function() {
+ beforeEach(function() {
+ this.view.render();
+ this.view.postRenderTemplate();
+ spec.content().html("<div class='new-comment'/><div class='focus_comment_textarea'/>");
+ });
+
+ it("does not call closeForm if markdown editor is in preview mode", function() {
+ spyOn(this.view, "closeForm");
+ spyOn(this.view.mdEditor, "isPreviewMode").and.returnValue(true);
+ spyOn(this.view.mdEditor, "userInputEmpty").and.returnValue(true);
+ this.view.onFormBlur();
+ expect(this.view.closeForm).not.toHaveBeenCalled();
+ });
+
+ it("does not call closeForm if markdown editor contains text", function() {
+ spyOn(this.view, "closeForm");
+ spyOn(this.view.mdEditor, "isPreviewMode").and.returnValue(false);
+ spyOn(this.view.mdEditor, "userInputEmpty").and.returnValue(false);
+ this.view.onFormBlur();
+ expect(this.view.closeForm).not.toHaveBeenCalled();
+ });
+
+ it("does not call closeForm when the form is clicked", function() {
+ spyOn(this.view, "closeForm");
+ spyOn(this.view.mdEditor, "isPreviewMode").and.returnValue(false);
+ spyOn(this.view.mdEditor, "userInputEmpty").and.returnValue(true);
+ this.view.onFormBlur($.Event("click", {target: $(".new-comment")}));
+ expect(this.view.closeForm).not.toHaveBeenCalled();
+ this.view.onFormBlur($.Event("click", {target: $(".focus_comment_textarea")}));
+ expect(this.view.closeForm).not.toHaveBeenCalled();
+ });
+
+ it("calls closeForm when the user clicks outside of the form", function() {
+ spyOn(this.view, "closeForm");
+ spyOn(this.view.mdEditor, "isPreviewMode").and.returnValue(false);
+ spyOn(this.view.mdEditor, "userInputEmpty").and.returnValue(true);
+ this.view.onFormBlur($.Event("click", {target: $("body")}));
+ expect(this.view.closeForm).toHaveBeenCalled();
+ });
+ });
+
describe("pressing a key when typing on the new comment box", function(){
var submitCallback;
@@ -283,23 +435,34 @@ describe("app.views.CommentStream", function(){
submitCallback = jasmine.createSpy().and.returnValue(false);
});
- it("should not submit the form when enter key is pressed", function(){
+ it("should not submit the form without the ctrl or cmd keys", function() {
this.view.render();
var form = this.view.$("form");
form.submit(submitCallback);
- var e = $.Event("keydown", { which: Keycodes.ENTER, ctrlKey: false });
+ var e = $.Event("keydown", {which: Keycodes.ENTER, ctrlKey: false, metaKey: false});
this.view.keyDownOnCommentBox(e);
expect(submitCallback).not.toHaveBeenCalled();
});
- it("should submit the form when enter is pressed with ctrl", function(){
+ it("should submit the form when enter is pressed with ctrl", function() {
+ this.view.render();
+ var form = this.view.$("form");
+ form.submit(submitCallback);
+
+ var e = $.Event("keydown", {which: Keycodes.ENTER, ctrlKey: true});
+ this.view.keyDownOnCommentBox(e);
+
+ expect(submitCallback).toHaveBeenCalled();
+ });
+
+ it("should submit the form when enter is pressed with cmd", function() {
this.view.render();
var form = this.view.$("form");
form.submit(submitCallback);
- var e = $.Event("keydown", { which: Keycodes.ENTER, ctrlKey: true });
+ var e = $.Event("keydown", {which: Keycodes.ENTER, metaKey: true});
this.view.keyDownOnCommentBox(e);
expect(submitCallback).toHaveBeenCalled();
diff --git a/spec/javascripts/app/views/content_view_spec.js b/spec/javascripts/app/views/content_view_spec.js
index 90fa3c4af..2315b4473 100644
--- a/spec/javascripts/app/views/content_view_spec.js
+++ b/spec/javascripts/app/views/content_view_spec.js
@@ -4,11 +4,17 @@ describe("app.views.Content", function(){
this.view = new app.views.Content({model : this.post});
});
- describe("rendering", function(){
+ describe("smallPhotos", function() {
it("should return all but the first photo from the post", function() {
this.post.set({photos : [1,2]}); // set 2 Photos
expect(this.view.smallPhotos().length).toEqual(1);
});
+
+ it("shouldn't change the photos array", function() {
+ this.post.set({photos: [1, 2]}); // set 2 Photos
+ this.view.smallPhotos();
+ expect(this.post.get("photos").length).toEqual(2);
+ });
});
describe("presenter", function(){
diff --git a/spec/javascripts/app/views/conversations_form_view_spec.js b/spec/javascripts/app/views/conversations_form_view_spec.js
index 232a7f7de..b0d065350 100644
--- a/spec/javascripts/app/views/conversations_form_view_spec.js
+++ b/spec/javascripts/app/views/conversations_form_view_spec.js
@@ -35,6 +35,21 @@ describe("app.views.ConversationsForm", function() {
this.target.initialize({prefill: {}});
expect(app.views.ConversationsForm.prototype.prefill).toHaveBeenCalledWith({});
});
+
+ it("creates markdown editor for new conversations", function() {
+ spyOn(this.target, "renderMarkdownEditor");
+ this.target.initialize();
+ expect(this.target.renderMarkdownEditor).toHaveBeenCalledWith("#new-message-text");
+ });
+ });
+
+ describe("renderMarkdownEditor", function() {
+ it("creates MarkdownEditor", function() {
+ spec.content().html("<form><textarea id='new-message-text'/></form>");
+ var mdEditor = this.target.renderMarkdownEditor("#new-message-text");
+ expect(mdEditor).toEqual(jasmine.any(Diaspora.MarkdownEditor));
+ expect($("#new-message-text")).toHaveClass("md-input");
+ });
});
describe("addRecipient", function() {
@@ -149,9 +164,16 @@ describe("app.views.ConversationsForm", function() {
expect(this.submitCallback).toHaveBeenCalled();
});
- it("shouldn't submit the form without the ctrl key", function() {
+ it("should submit the form with cmd+enter", function() {
$("#new-conversation").submit(this.submitCallback);
- var e = $.Event("keydown", {which: Keycodes.ENTER, ctrlKey: false});
+ var e = $.Event("keydown", {which: Keycodes.ENTER, metaKey: true});
+ $("#new-message-text").trigger(e);
+ expect(this.submitCallback).toHaveBeenCalled();
+ });
+
+ it("shouldn't submit the form without the ctrl or cmd key", function() {
+ $("#new-conversation").submit(this.submitCallback);
+ var e = $.Event("keydown", {which: Keycodes.ENTER, ctrlKey: false, metaKey: false});
$("#new-message-text").trigger(e);
expect(this.submitCallback).not.toHaveBeenCalled();
});
@@ -170,9 +192,16 @@ describe("app.views.ConversationsForm", function() {
expect(this.submitCallback).toHaveBeenCalled();
});
- it("shouldn't submit the form without the ctrl key", function() {
+ it("should submit the form with cmd+enter", function() {
$("#response-message").submit(this.submitCallback);
- var e = $.Event("keydown", {which: Keycodes.ENTER, ctrlKey: false});
+ var e = $.Event("keydown", {which: Keycodes.ENTER, metaKey: true});
+ $("#response-message-text").trigger(e);
+ expect(this.submitCallback).toHaveBeenCalled();
+ });
+
+ it("shouldn't submit the form without the ctrl or cmd key", function() {
+ $("#response-message").submit(this.submitCallback);
+ var e = $.Event("keydown", {which: Keycodes.ENTER, ctrlKey: false, metaKey: false});
$("#response-message-text").trigger(e);
expect(this.submitCallback).not.toHaveBeenCalled();
});
@@ -253,6 +282,12 @@ describe("app.views.ConversationsForm", function() {
$("#new-conversation").trigger("ajax:success", [{id: 23}]);
expect(app._changeLocation).toHaveBeenCalledWith(Routes.conversation(23));
});
+
+ it("hides the preview", function() {
+ spyOn(Diaspora.MarkdownEditor.prototype, "hidePreview");
+ $("#new-conversation").trigger("ajax:success", [{id: 23}]);
+ expect(Diaspora.MarkdownEditor.prototype.hidePreview).toHaveBeenCalled();
+ });
});
describe("conversationCreateError", function() {
diff --git a/spec/javascripts/app/views/conversations_inbox_view_spec.js b/spec/javascripts/app/views/conversations_inbox_view_spec.js
index 841f189f0..f1c539a24 100644
--- a/spec/javascripts/app/views/conversations_inbox_view_spec.js
+++ b/spec/javascripts/app/views/conversations_inbox_view_spec.js
@@ -17,6 +17,14 @@ describe("app.views.ConversationsInbox", function() {
new app.views.ConversationsInbox();
expect(app.views.ConversationsInbox.prototype.setupConversation).toHaveBeenCalled();
});
+
+ it("creates markdown editor for an existing conversation", function() {
+ spyOn(app.views.ConversationsForm.prototype, "renderMarkdownEditor");
+ new app.views.ConversationsInbox(1);
+ expect(app.views.ConversationsForm.prototype.renderMarkdownEditor).toHaveBeenCalledWith(
+ "#conversation-show .conversation-message-text"
+ );
+ });
});
describe("renderConversation", function() {
@@ -34,6 +42,8 @@ describe("app.views.ConversationsInbox", function() {
spyOn($, "ajax").and.callThrough();
spyOn(app.views.ConversationsInbox.prototype, "selectConversation");
spyOn(app.views.ConversationsInbox.prototype, "setupConversation");
+ spyOn(app.views.ConversationsForm.prototype, "renderMarkdownEditor");
+ spyOn(window, "autosize");
this.target.renderConversation(this.conversationId);
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
@@ -44,6 +54,9 @@ describe("app.views.ConversationsInbox", function() {
expect(jasmine.Ajax.requests.mostRecent().url).toBe("/conversations/" + this.conversationId + "/raw");
expect(app.views.ConversationsInbox.prototype.selectConversation).toHaveBeenCalledWith(this.conversationId);
expect(app.views.ConversationsInbox.prototype.setupConversation).toHaveBeenCalled();
+ expect(app.views.ConversationsForm.prototype.renderMarkdownEditor).toHaveBeenCalled();
+ expect(window.autosize).toHaveBeenCalled();
+ expect(window.autosize.calls.mostRecent().args[0].is($("#conversation-show textarea")));
expect($("#conversation-new")).toHaveClass("hidden");
expect($("#conversation-show")).not.toHaveClass("hidden");
expect($("#conversation-show #fake-conversation-content").length).toBe(1);
diff --git a/spec/javascripts/app/views/header_view_spec.js b/spec/javascripts/app/views/header_view_spec.js
index 3bf13978f..56c2272e7 100644
--- a/spec/javascripts/app/views/header_view_spec.js
+++ b/spec/javascripts/app/views/header_view_spec.js
@@ -5,7 +5,6 @@ describe("app.views.Header", function() {
loginAs(this.userAttrs);
spec.loadFixture("aspects_index");
- gon.appConfig = {settings: {podname: "MyPod"}};
app.notificationsCollection = new app.collections.Notifications();
this.view = new app.views.Header().render();
});
@@ -45,13 +44,13 @@ describe("app.views.Header", function() {
it("displays if the current user is an admin", function(){
loginAs(_.extend(this.userAttrs, {admin : true}));
this.view.render();
- expect(this.view.$("#user_menu").html()).toContain("/admins");
+ expect(this.view.$("#user-menu").html()).toContain("/admins");
});
it("does not display if the current user is not an admin", function(){
loginAs(_.extend(this.userAttrs, {admin : false}));
this.view.render();
- expect(this.view.$("#user_menu").html()).not.toContain("/admins");
+ expect(this.view.$("#user-menu").html()).not.toContain("/admins");
});
});
});
diff --git a/spec/javascripts/app/views/help_view_spec.js b/spec/javascripts/app/views/help_view_spec.js
index 38717a620..e73830267 100644
--- a/spec/javascripts/app/views/help_view_spec.js
+++ b/spec/javascripts/app/views/help_view_spec.js
@@ -52,26 +52,21 @@ describe("app.views.Help", function(){
expect(this.view.$el.find('#faq').children().first().hasClass('faq_question_private_posts')).toBeTruthy();
});
- it('should show private profiles section', function(){
- this.view.$el.find('a[data-section=private_profiles]').trigger('click');
- expect(this.view.$el.find('#faq').children().first().hasClass('faq_question_private_profiles')).toBeTruthy();
- });
-
it('should show public posts section', function(){
this.view.$el.find('a[data-section=public_posts]').trigger('click');
expect(this.view.$el.find('#faq').children().first().hasClass('faq_question_public_posts')).toBeTruthy();
});
- it('should show public profiles section', function(){
- this.view.$el.find('a[data-section=public_profiles]').trigger('click');
- expect(this.view.$el.find('#faq').children().first().hasClass('faq_question_public_profiles')).toBeTruthy();
- });
-
it('should show resharing posts section', function(){
this.view.$el.find('a[data-section=resharing_posts]').trigger('click');
expect(this.view.$el.find('#faq').children().first().hasClass('faq_question_resharing_posts')).toBeTruthy();
});
+ it("should show profile section", function() {
+ this.view.$el.find("a[data-section=profile]").trigger("click");
+ expect(this.view.$el.find("#faq").children().first().hasClass("faq_question_profile")).toBeTruthy();
+ });
+
it('should show sharing section', function(){
this.view.$el.find('a[data-section=sharing]').trigger('click');
expect(this.view.$el.find('#faq').children().first().data('template')).toBe('faq_sharing');
diff --git a/spec/javascripts/app/views/notifications_view_spec.js b/spec/javascripts/app/views/notifications_view_spec.js
index 4e520a57c..d15e21bc1 100644
--- a/spec/javascripts/app/views/notifications_view_spec.js
+++ b/spec/javascripts/app/views/notifications_view_spec.js
@@ -142,18 +142,13 @@ describe("app.views.Notifications", function() {
});
it("changes the header notifications count", function() {
- var badge1 = $(".notifications-link:eq(0) .badge");
- var badge2 = $(".notifications-link:eq(1) .badge");
+ var badge = $(".notifications-link .badge");
- expect(parseInt(badge1.text(), 10)).toBe(this.collection.unreadCount);
- expect(parseInt(badge2.text(), 10)).toBe(this.collection.unreadCount);
+ expect(parseInt(badge.text(), 10)).toBe(this.collection.unreadCount);
this.collection.unreadCount++;
this.view.updateView();
- expect(parseInt(badge1.text(), 10)).toBe(this.collection.unreadCount);
-
- this.view.updateView();
- expect(parseInt(badge2.text(), 10)).toBe(this.collection.unreadCount);
+ expect(parseInt(badge.text(), 10)).toBe(this.collection.unreadCount);
});
it("disables the mark-all-read-link button", function() {
diff --git a/spec/javascripts/app/views/preview_post_view_spec.js b/spec/javascripts/app/views/preview_post_view_spec.js
index e2c1b5aec..af5f0a455 100644
--- a/spec/javascripts/app/views/preview_post_view_spec.js
+++ b/spec/javascripts/app/views/preview_post_view_spec.js
@@ -36,12 +36,6 @@ describe("app.views.PreviewPost", function() {
});
describe("render", function() {
- it("calls feedbackView", function() {
- spyOn(app.views.PreviewPost.prototype, "feedbackView");
- this.view.render();
- expect(app.views.PreviewPost.prototype.feedbackView).toHaveBeenCalled();
- });
-
it("calls postContentView", function() {
spyOn(app.views.PreviewPost.prototype, "postContentView");
this.view.render();
@@ -55,14 +49,6 @@ describe("app.views.PreviewPost", function() {
});
});
- describe("feedbackView", function() {
- it("calls app.views.Feedback.initialise", function() {
- spyOn(app.views.Feedback.prototype, "initialize");
- this.view.feedbackView();
- expect(app.views.Feedback.prototype.initialize).toHaveBeenCalledWith({model: this.model});
- });
- });
-
describe("postContentView", function() {
it("calls app.views.Feedback.initialise", function() {
spyOn(app.views.StatusMessage.prototype, "initialize");
diff --git a/spec/javascripts/app/views/publisher_mention_view_spec.js b/spec/javascripts/app/views/publisher_mention_view_spec.js
index 7f5ced47c..15371a01f 100644
--- a/spec/javascripts/app/views/publisher_mention_view_spec.js
+++ b/spec/javascripts/app/views/publisher_mention_view_spec.js
@@ -7,7 +7,6 @@ describe("app.views.PublisherMention", function() {
it("initializes object properties", function() {
this.view = new app.views.PublisherMention({ el: "#publisher" });
expect(this.view.mentionedPeople).toEqual([]);
- expect(this.view.invisibleChar).toBe("\u200B");
expect(this.view.triggerChar).toBe("@");
});
@@ -29,6 +28,17 @@ describe("app.views.PublisherMention", function() {
});
});
+ describe("mentionSyntaxTemplate", function() {
+ beforeEach(function() {
+ this.view = new app.views.PublisherMention({el: "#publisher"});
+ this.person = {handle: "alice@pod.tld", name: "Alice Awesome"};
+ });
+
+ it("returns the correct mention syntax", function() {
+ expect(this.view.mentionSyntaxTemplate(this.person)).toBe("@{alice@pod.tld}");
+ });
+ });
+
describe("bindTypeaheadEvents", function() {
beforeEach(function() {
this.view = new app.views.PublisherMention({ el: "#publisher" });
@@ -92,30 +102,30 @@ describe("app.views.PublisherMention", function() {
});
it("removes person from mentioned people if not mentioned anymore", function() {
- this.view.addPersonToMentions({name: "user1", handle: "user1@pod.tld"});
+ this.view.addPersonToMentions({name: "User Name", handle: "user1@pod.tld"});
expect(this.view.mentionedPeople.length).toBe(1);
this.view.cleanMentionedPeople();
expect(this.view.mentionedPeople.length).toBe(0);
});
it("removes person from ignored people if not mentioned anymore", function() {
- this.view.addPersonToMentions({name: "user1", handle: "user1@pod.tld"});
+ this.view.addPersonToMentions({name: "User Name", handle: "user1@pod.tld"});
expect(this.view.ignoreDiasporaIds.length).toBe(1);
this.view.cleanMentionedPeople();
expect(this.view.ignoreDiasporaIds.length).toBe(0);
});
it("keeps mentioned persons", function() {
- this.view.addPersonToMentions({name: "user1", handle: "user1@pod.tld"});
- this.view.inputBox.val("user1");
+ this.view.addPersonToMentions({name: "User Name", handle: "user1@pod.tld"});
+ this.view.inputBox.val("@{user1@pod.tld}");
expect(this.view.mentionedPeople.length).toBe(1);
this.view.cleanMentionedPeople();
expect(this.view.mentionedPeople.length).toBe(1);
});
it("keeps mentioned persons for ignored diaspora ids", function() {
- this.view.addPersonToMentions({name: "user1", handle: "user1@pod.tld"});
- this.view.inputBox.val("user1");
+ this.view.addPersonToMentions({name: "User Name", handle: "user1@pod.tld"});
+ this.view.inputBox.val("@{user1@pod.tld}");
expect(this.view.ignoreDiasporaIds.length).toBe(1);
this.view.cleanMentionedPeople();
expect(this.view.ignoreDiasporaIds.length).toBe(1);
@@ -151,61 +161,29 @@ describe("app.views.PublisherMention", function() {
it("correctly formats the text", function() {
this.view.onSuggestionSelection({name: "user1337", handle: "user1@pod.tld"});
- expect(this.view.inputBox.val()).toBe("@user1337 Text before \u200Buser1337 text after");
+ expect(this.view.inputBox.val()).toBe("@user1337 Text before @{user1@pod.tld} text after");
});
it("replaces the correct mention", function() {
this.view.inputBox.val("@user1337 123 user2 @user2 456 @user3 789");
this.view.inputBox[0].setSelectionRange(26, 26);
this.view.onSuggestionSelection({name: "user23", handle: "user2@pod.tld"});
- expect(this.view.inputBox.val()).toBe("@user1337 123 user2 \u200Buser23 456 @user3 789");
+ expect(this.view.inputBox.val()).toBe("@user1337 123 user2 @{user2@pod.tld} 456 @user3 789");
this.view.inputBox[0].setSelectionRange(9, 9);
this.view.onSuggestionSelection({name: "user1337", handle: "user1@pod.tld"});
- expect(this.view.inputBox.val()).toBe("\u200Buser1337 123 user2 \u200Buser23 456 @user3 789");
- this.view.inputBox[0].setSelectionRange(38, 38);
+ expect(this.view.inputBox.val()).toBe("@{user1@pod.tld} 123 user2 @{user2@pod.tld} 456 @user3 789");
+ this.view.inputBox[0].setSelectionRange(54, 54);
this.view.onSuggestionSelection({name: "user32", handle: "user3@pod.tld"});
- expect(this.view.inputBox.val()).toBe("\u200Buser1337 123 user2 \u200Buser23 456 \u200Buser32 789");
- });
-
- it("calls updateMessageTexts", function() {
- spyOn(this.view, "updateMessageTexts");
- this.view.onSuggestionSelection({name: "user1337", handle: "user1@pod.tld"});
- expect(this.view.updateMessageTexts).toHaveBeenCalled();
+ expect(this.view.inputBox.val()).toBe("@{user1@pod.tld} 123 user2 @{user2@pod.tld} 456 @{user3@pod.tld} 789");
});
it("places the caret at the right position", function() {
this.view.onSuggestionSelection({"name": "user1WithLongName", "handle": "user1@pod.tld"});
- var expectedCaretPosition = ("@user1337 Text before \u200Buser1WithLongName").length;
+ var expectedCaretPosition = ("@user1337 Text before @{user1@pod.tld}").length;
expect(this.view.inputBox[0].selectionStart).toBe(expectedCaretPosition);
});
});
- describe("updateMessageTexts", function() {
- beforeEach(function() {
- this.view = new app.views.PublisherMention({ el: "#publisher" });
- this.view.inputBox.val("@user1 Text before \u200Buser1\ntext after");
- this.view.mentionedPeople.push({"name": "user1", "handle": "user1@pod.tld"});
- });
-
- it("sets the correct messageText", function() {
- this.view.updateMessageTexts();
- expect(this.view.inputBox.data("messageText")).toBe("@user1 Text before @{user1 ; user1@pod.tld}\ntext after");
- });
-
- it("formats overlay text to HTML", function() {
- this.view.updateMessageTexts();
- expect(this.view.mentionsBox.find(".mentions").html())
- .toBe("@user1 Text before <strong><span>user1</span></strong>\ntext after");
- });
-
- it("properly escapes the user input", function() {
- this.view.inputBox.val("<img src=\"/default.png\"> @user1 Text before \u200Buser1\ntext after");
- this.view.updateMessageTexts();
- expect(this.view.mentionsBox.find(".mentions").html())
- .toBe("&lt;img src=\"/default.png\"&gt; @user1 Text before <strong><span>user1</span></strong>\ntext after");
- });
- });
-
describe("updateTypeaheadInput", function() {
beforeEach(function() {
this.view = new app.views.PublisherMention({ el: "#publisher" });
@@ -251,20 +229,34 @@ describe("app.views.PublisherMention", function() {
expect(this.view.closeSuggestions).not.toHaveBeenCalled();
expect(this.view.typeaheadInput.val()).toBe("user");
});
+
+ it("doesn't call 'cleanMentionedPeople' if there is no '@' in front of the caret", function() {
+ spyOn(this.view, "cleanMentionedPeople");
+ this.view.inputBox.val("user1337 Text before @user1 text after");
+ this.view.inputBox[0].setSelectionRange(9, 9);
+ this.view.updateTypeaheadInput();
+ expect(this.view.cleanMentionedPeople).not.toHaveBeenCalled();
+ });
+
+ it("calls 'cleanMentionedPeople' if there is an '@' in front of the caret", function() {
+ spyOn(this.view, "cleanMentionedPeople");
+ this.view.inputBox.val("@user1337 Text before @user1 text after");
+ this.view.inputBox[0].setSelectionRange(9, 9);
+ this.view.updateTypeaheadInput();
+ expect(this.view.cleanMentionedPeople).toHaveBeenCalled();
+ });
});
describe("prefillMention", function() {
beforeEach(function() {
this.view = new app.views.PublisherMention({ el: "#publisher" });
spyOn(this.view, "addPersonToMentions");
- spyOn(this.view, "updateMessageTexts");
});
it("prefills one mention", function() {
this.view.prefillMention([{"name": "user1", "handle": "user1@pod.tld"}]);
expect(this.view.addPersonToMentions).toHaveBeenCalledWith({"name": "user1", "handle": "user1@pod.tld"});
- expect(this.view.updateMessageTexts).toHaveBeenCalled();
- expect(this.view.inputBox.val()).toBe("\u200Buser1");
+ expect(this.view.inputBox.val()).toBe("@{user1@pod.tld}");
});
it("prefills multiple mentions", function() {
@@ -275,8 +267,7 @@ describe("app.views.PublisherMention", function() {
expect(this.view.addPersonToMentions).toHaveBeenCalledWith({"name": "user1", "handle": "user1@pod.tld"});
expect(this.view.addPersonToMentions).toHaveBeenCalledWith({"name": "user2", "handle": "user2@pod.tld"});
- expect(this.view.updateMessageTexts).toHaveBeenCalled();
- expect(this.view.inputBox.val()).toBe("\u200Buser1 \u200Buser2");
+ expect(this.view.inputBox.val()).toBe("@{user1@pod.tld} @{user2@pod.tld}");
});
});
@@ -372,30 +363,6 @@ describe("app.views.PublisherMention", function() {
});
});
- describe("onInputBoxInput", function() {
- beforeEach(function() {
- this.view = new app.views.PublisherMention({ el: "#publisher" });
- });
-
- it("calls 'cleanMentionedPeople'", function() {
- spyOn(this.view, "cleanMentionedPeople");
- this.view.onInputBoxInput();
- expect(this.view.cleanMentionedPeople).toHaveBeenCalled();
- });
-
- it("calls 'updateMessageTexts'", function() {
- spyOn(this.view, "updateMessageTexts");
- this.view.onInputBoxInput();
- expect(this.view.updateMessageTexts).toHaveBeenCalled();
- });
-
- it("calls 'updateTypeaheadInput'", function() {
- spyOn(this.view, "updateTypeaheadInput");
- this.view.onInputBoxInput();
- expect(this.view.updateTypeaheadInput).toHaveBeenCalled();
- });
- });
-
describe("onInputBoxClick", function() {
beforeEach(function() {
this.view = new app.views.PublisherMention({ el: "#publisher" });
@@ -423,13 +390,13 @@ describe("app.views.PublisherMention", function() {
describe("reset", function() {
beforeEach(function() {
this.view = new app.views.PublisherMention({ el: "#publisher" });
- spyOn(this.view, "onInputBoxInput");
+ spyOn(this.view, "updateTypeaheadInput");
});
it("resets the mention box", function() {
this.view.reset();
expect(this.view.inputBox.val()).toBe("");
- expect(this.view.onInputBoxInput).toHaveBeenCalled();
+ expect(this.view.updateTypeaheadInput).toHaveBeenCalled();
});
});
@@ -454,27 +421,21 @@ describe("app.views.PublisherMention", function() {
});
});
- describe("getTextForSubmit", function() {
+ describe("getMentionedPeople", function() {
beforeEach(function() {
- this.view = new app.views.PublisherMention({ el: "#publisher" });
- this.view.bloodhound.add([
- {person: true, name: "user1", handle: "user1@pod.tld"}
- ]);
+ this.view = new app.views.PublisherMention({el: "#publisher"});
});
- it("returns text with mention if someone has been mentioned", function() {
- this.view.inputBox.val("@user");
- this.view.inputBox[0].setSelectionRange(5, 5);
- this.view.typeaheadInput.typeahead("val", "user");
- this.view.typeaheadInput.typeahead("open");
- this.view.$(".tt-suggestion").first().click();
- expect(this.view.getTextForSubmit()).toBe("@{user1 ; user1@pod.tld}");
+ it("calls 'cleanMentionedPeople'", function() {
+ spyOn(this.view, "cleanMentionedPeople");
+ this.view.getMentionedPeople();
+ expect(this.view.cleanMentionedPeople).toHaveBeenCalled();
});
- it("returns normal text if nobody has been mentioned", function() {
- this.view.inputBox.data("messageText", "Bad text");
- this.view.inputBox.val("Good text");
- expect(this.view.getTextForSubmit()).toBe("Good text");
+ it("returns the cleaned mentionedPeople", function() {
+ this.view.inputBox.val("@{user1@pod.tld} user2@pod.tld");
+ this.view.mentionedPeople = [{name: "user1", handle: "user1@pod.tld"}, {name: "user2", handle: "user2@pod.tld"}];
+ expect(this.view.getMentionedPeople()).toEqual([{name: "user1", handle: "user1@pod.tld"}]);
});
});
});
diff --git a/spec/javascripts/app/views/publisher_view_spec.js b/spec/javascripts/app/views/publisher_view_spec.js
index 2e7c3b4dd..1a8b4a3bf 100644
--- a/spec/javascripts/app/views/publisher_view_spec.js
+++ b/spec/javascripts/app/views/publisher_view_spec.js
@@ -43,17 +43,11 @@ describe("app.views.Publisher", function() {
});
describe("#initSubviews", function() {
- it("calls handleTextchange if the publisher is prefilled with mentions", function() {
- spyOn(this.view, "handleTextchange");
+ it("calls checkSubmitAvailability if the publisher is prefilled with mentions", function() {
+ spyOn(this.view, "checkSubmitAvailability");
this.view.prefillMention = "user@example.org";
this.view.initSubviews();
- expect(this.view.handleTextchange).toHaveBeenCalled();
- });
-
- it("doesn't call handleTextchange if there are no prefilled mentions", function() {
- spyOn(this.view, "handleTextchange");
- this.view.initSubviews();
- expect(this.view.handleTextchange).not.toHaveBeenCalled();
+ expect(this.view.checkSubmitAvailability).toHaveBeenCalled();
});
});
@@ -82,9 +76,9 @@ describe("app.views.Publisher", function() {
});
it("resets the element's height", function() {
- $(this.view.el).find("#status_message_fake_text").height(100);
+ $(this.view.el).find("#status_message_text").height(100);
this.view.close($.Event());
- expect($(this.view.el).find("#status_message_fake_text").attr("style")).not.toContain("height");
+ expect($(this.view.el).find("#status_message_text").attr("style")).not.toContain("height");
});
it("calls autosize.update", function() {
@@ -203,12 +197,6 @@ describe("app.views.Publisher", function() {
});
describe("createStatusMessage", function(){
- it("calls handleTextchange to complete missing mentions", function(){
- spyOn(this.view, "handleTextchange");
- this.view.createStatusMessage($.Event());
- expect(this.view.handleTextchange).toHaveBeenCalled();
- });
-
it("adds the status message to the stream", function() {
app.stream = { addNow: $.noop };
spyOn(app.stream, "addNow");
@@ -224,20 +212,10 @@ describe("app.views.Publisher", function() {
});
});
- describe("createPostPreview", function(){
- it("calls handleTextchange to complete missing mentions", function(){
- spyOn(this.view, "handleTextchange");
- this.view.createPostPreview();
- expect(this.view.handleTextchange).toHaveBeenCalled();
- });
- });
-
describe('#setText', function() {
it("sets the content text", function() {
this.view.setText("FOO bar");
-
expect(this.view.inputEl.val()).toEqual("FOO bar");
- expect(this.view.hiddenInputEl.val()).toEqual("FOO bar");
});
});
@@ -248,7 +226,6 @@ describe("app.views.Publisher", function() {
expect(this.view.disabled).toBeTruthy();
expect(this.view.inputEl.prop("disabled")).toBeTruthy();
- expect(this.view.hiddenInputEl.prop("disabled")).toBeTruthy();
});
it("disables submitting", function() {
@@ -273,6 +250,44 @@ describe("app.views.Publisher", function() {
expect(submitCallback).toHaveBeenCalled();
expect($(this.view.el)).not.toHaveClass("closed");
});
+
+ it("should submit the form when cmd+enter is pressed", function() {
+ this.view.render();
+ var form = this.view.$("form");
+ var submitCallback = jasmine.createSpy().and.returnValue(false);
+ form.submit(submitCallback);
+
+ var e = $.Event("keydown", {which: Keycodes.ENTER, metaKey: true});
+ this.view.keyDown(e);
+
+ expect(submitCallback).toHaveBeenCalled();
+ expect($(this.view.el)).not.toHaveClass("closed");
+ });
+ });
+
+ describe("tryClose", function() {
+ it("doesn't close the publisher if it is submittable", function() {
+ spyOn(this.view, "_submittable").and.returnValue(true);
+ spyOn(this.view, "close");
+ this.view.tryClose();
+ expect(this.view.close).not.toHaveBeenCalled();
+ });
+
+ it("doesn't close the publisher if it is in preview mode", function() {
+ spyOn(this.view, "_submittable").and.returnValue(false);
+ spyOn(this.view.markdownEditor, "isPreviewMode").and.returnValue(true);
+ spyOn(this.view, "close");
+ this.view.tryClose();
+ expect(this.view.close).not.toHaveBeenCalled();
+ });
+
+ it("closes the publisher if it is neither submittable nor in preview mode", function() {
+ spyOn(this.view, "_submittable").and.returnValue(false);
+ spyOn(this.view.markdownEditor, "isPreviewMode").and.returnValue(false);
+ spyOn(this.view, "close");
+ this.view.tryClose();
+ expect(this.view.close).toHaveBeenCalled();
+ });
});
describe("_beforeUnload", function(){
diff --git a/spec/javascripts/app/views/single-post-view/single_post_comment_stream_spec.js b/spec/javascripts/app/views/single-post-view/single_post_comment_stream_spec.js
index 3e32ca3ee..28c80225d 100644
--- a/spec/javascripts/app/views/single-post-view/single_post_comment_stream_spec.js
+++ b/spec/javascripts/app/views/single-post-view/single_post_comment_stream_spec.js
@@ -9,14 +9,6 @@ describe("app.views.SinglePostCommentStream", function() {
expect(this.view.CommentView).toBe(app.views.ExpandedComment);
});
- it("calls render when the comments collection has been resetted", function() {
- spyOn(app.views.SinglePostCommentStream.prototype, "render");
- this.view.initialize();
- expect(app.views.SinglePostCommentStream.prototype.render).not.toHaveBeenCalled();
- this.post.comments.reset();
- expect(app.views.SinglePostCommentStream.prototype.render).toHaveBeenCalled();
- });
-
it("calls setupBindings", function() {
spyOn(app.views.SinglePostCommentStream.prototype, "setupBindings");
this.view.initialize();
diff --git a/spec/javascripts/app/views/single-post-view/single_post_interaction_counts_spec.js b/spec/javascripts/app/views/single-post-view/single_post_interaction_counts_spec.js
index 35abf7afe..0ff6959bc 100644
--- a/spec/javascripts/app/views/single-post-view/single_post_interaction_counts_spec.js
+++ b/spec/javascripts/app/views/single-post-view/single_post_interaction_counts_spec.js
@@ -1,6 +1,6 @@
describe("app.views.SinglePostInteractionCounts", function() {
beforeEach(function() {
- this.post = factory.post();
+ this.post = factory.postWithInteractions();
this.view = new app.views.SinglePostInteractionCounts({model: this.post});
});
@@ -12,5 +12,151 @@ describe("app.views.SinglePostInteractionCounts", function() {
this.post.interactions.trigger("change");
expect(app.views.SinglePostInteractionCounts.prototype.render).toHaveBeenCalled();
});
+
+ it("calls render when the likes change", function() {
+ spyOn(app.views.SinglePostInteractionCounts.prototype, "render");
+ this.view.initialize();
+ expect(app.views.SinglePostInteractionCounts.prototype.render).not.toHaveBeenCalled();
+ this.post.interactions.likes.trigger("change");
+ expect(app.views.SinglePostInteractionCounts.prototype.render).toHaveBeenCalled();
+ });
+
+ it("calls render when the reshares change", function() {
+ spyOn(app.views.SinglePostInteractionCounts.prototype, "render");
+ this.view.initialize();
+ expect(app.views.SinglePostInteractionCounts.prototype.render).not.toHaveBeenCalled();
+ this.post.interactions.reshares.trigger("change");
+ expect(app.views.SinglePostInteractionCounts.prototype.render).toHaveBeenCalled();
+ });
+ });
+
+ describe("render", function() {
+ it("doesn't show a #show-all-likes link if there are no additional likes", function() {
+ this.view.render();
+ expect(this.view.$("#show-all-likes").length).toBe(0);
+ });
+
+ it("shows a #show-all-likes link if there are additional likes", function() {
+ this.view.model.interactions.set("likes_count", this.view.model.interactions.likes.length + 1);
+ this.view.render();
+ expect(this.view.$("#show-all-likes").length).toBe(1);
+ });
+
+ it("doesn't show a #show-all-reshares link if there are no additional reshares", function() {
+ this.view.render();
+ expect(this.view.$("#show-all-reshares").length).toBe(0);
+ });
+
+ it("shows a #show-all-reshares link if there are additional reshares", function() {
+ this.view.model.interactions.set("reshares_count", this.view.model.interactions.reshares.length + 1);
+ this.view.render();
+ expect(this.view.$("#show-all-reshares").length).toBe(1);
+ });
+ });
+
+ describe("showAllLikes", function() {
+ it("is called when clicking #show-all-likes", function() {
+ spyOn(this.view, "showAllLikes");
+ this.view.delegateEvents();
+ this.view.model.interactions.set("likes_count", this.view.model.interactions.likes.length + 1);
+ this.view.render();
+ expect(this.view.showAllLikes).not.toHaveBeenCalled();
+ this.view.$("#show-all-likes").click();
+ expect(this.view.showAllLikes).toHaveBeenCalled();
+ });
+
+ it("calls _showAll", function() {
+ spyOn(this.view, "_showAll");
+ this.view.showAllLikes($.Event());
+ expect(this.view._showAll).toHaveBeenCalledWith("likes", this.view.model.interactions.likes);
+ });
+ });
+
+ describe("showAllReshares", function() {
+ it("is called when clicking #show-all-reshares", function() {
+ spyOn(this.view, "showAllReshares");
+ this.view.delegateEvents();
+ this.view.model.interactions.set("reshares_count", this.view.model.interactions.reshares.length + 1);
+ this.view.render();
+ expect(this.view.showAllReshares).not.toHaveBeenCalled();
+ this.view.$("#show-all-reshares").click();
+ expect(this.view.showAllReshares).toHaveBeenCalled();
+ });
+
+ it("calls _showAll", function() {
+ spyOn(this.view, "_showAll");
+ this.view.showAllReshares($.Event());
+ expect(this.view._showAll).toHaveBeenCalledWith("reshares", this.view.model.interactions.reshares);
+ });
+ });
+
+ describe("_showAll", function() {
+ beforeEach(function() {
+ this.view.model.interactions.set("likes_count", this.view.model.interactions.likes.length + 1);
+ this.view.model.interactions.set("reshares_count", this.view.model.interactions.reshares.length + 1);
+ this.view.render();
+ });
+
+ context("with likes", function() {
+ it("hides the #show-all-likes link", function() {
+ expect(this.view.$("#show-all-likes")).not.toHaveClass("hidden");
+ expect(this.view.$("#show-all-reshares")).not.toHaveClass("hidden");
+ this.view._showAll("likes", this.view.model.interactions.likes);
+ expect(this.view.$("#show-all-likes")).toHaveClass("hidden");
+ expect(this.view.$("#show-all-reshares")).not.toHaveClass("hidden");
+ });
+
+ it("shows the likes loader", function() {
+ expect(this.view.$("#likes .loader")).toHaveClass("hidden");
+ expect(this.view.$("#reshares .loader")).toHaveClass("hidden");
+ this.view._showAll("likes", this.view.model.interactions.likes);
+ expect(this.view.$("#likes .loader")).not.toHaveClass("hidden");
+ expect(this.view.$("#reshares .loader")).toHaveClass("hidden");
+ });
+
+ it("calls #fetch on the model", function() {
+ spyOn(this.view.model.interactions.likes, "fetch");
+ this.view._showAll("likes", this.view.model.interactions.likes);
+ expect(this.view.model.interactions.likes.fetch).toHaveBeenCalled();
+ });
+
+ it("triggers 'change' after a successfull fetch", function() {
+ spyOn(this.view.model.interactions.likes, "trigger");
+ this.view._showAll("likes", this.view.model.interactions.likes);
+ jasmine.Ajax.requests.mostRecent().respondWith({status: 200, responseText: "{\"id\": 1}"});
+ expect(this.view.model.interactions.likes.trigger).toHaveBeenCalledWith("change");
+ });
+ });
+
+ context("with reshares", function() {
+ it("hides the #show-all-reshares link", function() {
+ expect(this.view.$("#show-all-likes")).not.toHaveClass("hidden");
+ expect(this.view.$("#show-all-reshares")).not.toHaveClass("hidden");
+ this.view._showAll("reshares", this.view.model.interactions.reshares);
+ expect(this.view.$("#show-all-likes")).not.toHaveClass("hidden");
+ expect(this.view.$("#show-all-reshares")).toHaveClass("hidden");
+ });
+
+ it("shows the reshares loader", function() {
+ expect(this.view.$("#likes .loader")).toHaveClass("hidden");
+ expect(this.view.$("#reshares .loader")).toHaveClass("hidden");
+ this.view._showAll("reshares", this.view.model.interactions.reshares);
+ expect(this.view.$("#likes .loader")).toHaveClass("hidden");
+ expect(this.view.$("#reshares .loader")).not.toHaveClass("hidden");
+ });
+
+ it("calls #fetch on the model", function() {
+ spyOn(this.view.model.interactions.reshares, "fetch");
+ this.view._showAll("reshares", this.view.model.interactions.reshares);
+ expect(this.view.model.interactions.reshares.fetch).toHaveBeenCalled();
+ });
+
+ it("triggers 'change' after a successfull fetch", function() {
+ spyOn(this.view.model.interactions.reshares, "trigger");
+ this.view._showAll("reshares", this.view.model.interactions.reshares);
+ jasmine.Ajax.requests.mostRecent().respondWith({status: 200, responseText: "{\"id\": 1}"});
+ expect(this.view.model.interactions.reshares.trigger).toHaveBeenCalledWith("change");
+ });
+ });
});
});
diff --git a/spec/javascripts/helpers/markdown_editor_spec.js b/spec/javascripts/helpers/markdown_editor_spec.js
index 9c2ab4cff..55bc68942 100644
--- a/spec/javascripts/helpers/markdown_editor_spec.js
+++ b/spec/javascripts/helpers/markdown_editor_spec.js
@@ -31,6 +31,7 @@ describe("Diaspora.MarkdownEditor", function() {
it("call $.fn.markdown with correct default options", function() {
spyOn($.fn, "markdown");
+ spyOn(autosize, "update");
this.target.initialize(this.$el, {});
expect($.fn.markdown).toHaveBeenCalled();
var args = $.fn.markdown.calls.mostRecent().args[0];
@@ -40,6 +41,9 @@ describe("Diaspora.MarkdownEditor", function() {
expect(args.onPostPreview).toBe($.noop);
expect(args.fullscreen).toEqual({enable: false, icons: {}});
expect(args.hiddenButtons).toEqual(["cmdPreview"]);
+
+ args.onChange({$textarea: "el"});
+ expect(autosize.update).toHaveBeenCalledWith("el");
});
it("overrides fullscreen, hiddenButtons, language and onShow options", function() {
@@ -220,6 +224,48 @@ describe("Diaspora.MarkdownEditor", function() {
});
});
+ describe("isPreviewMode", function() {
+ beforeEach(function() {
+ this.target = new Diaspora.MarkdownEditor(this.$el, {onPreview: $.noop, onPostPreview: $.noop()});
+ });
+
+ it("return false if editor is not visible yet", function() {
+ this.target.instance = undefined;
+ expect(this.target.isPreviewMode()).toBe(false);
+ });
+
+ it("returns false if the editor is in write (default) mode", function() {
+ expect(this.target.instance).toBeDefined();
+ expect(this.target.isPreviewMode()).toBe(false);
+ });
+
+ it("returns true if editor is in preview mode", function() {
+ this.target.showPreview();
+ expect(this.target.isPreviewMode()).toBe(true);
+ });
+ });
+
+ describe("userInputEmpty", function() {
+ beforeEach(function() {
+ this.target = new Diaspora.MarkdownEditor(this.$el, {onPreview: $.noop, onPostPreview: $.noop()});
+ });
+
+ it("return true if editor is not visible yet", function() {
+ this.target.instance = undefined;
+ expect(this.target.userInputEmpty()).toBe(true);
+ });
+
+ it("returns true if editor has no content", function() {
+ $("textarea").text("");
+ expect(this.target.userInputEmpty()).toBe(true);
+ });
+
+ it("returns false if editor has content", function() {
+ $("textarea").text("Yolo");
+ expect(this.target.userInputEmpty()).toBe(false);
+ });
+ });
+
describe("localize", function() {
beforeEach(function() {
this.target = new Diaspora.MarkdownEditor(this.$el, {});
@@ -234,4 +280,18 @@ describe("Diaspora.MarkdownEditor", function() {
expect($.fn.markdown.messages[Diaspora.I18n.language]).toBeDefined();
});
});
+
+ describe("simplePreview", function() {
+ beforeEach(function() {
+ this.target = new Diaspora.MarkdownEditor(this.$el, {});
+ });
+
+ it("generates HTML for preview", function() {
+ spyOn(app.helpers, "textFormatter").and.callThrough();
+ this.$el[0].value = "<p>hello</p>";
+ var res = Diaspora.MarkdownEditor.simplePreview(this.target.instance);
+ expect(app.helpers.textFormatter).toHaveBeenCalledWith("<p>hello</p>");
+ expect(res).toBe("<div class='preview-content'><p>hello</p></div>");
+ });
+ });
});
diff --git a/spec/javascripts/jasmine_helpers/SpecHelper.js b/spec/javascripts/jasmine_helpers/SpecHelper.js
index 67d167c16..4b0bd9175 100644
--- a/spec/javascripts/jasmine_helpers/SpecHelper.js
+++ b/spec/javascripts/jasmine_helpers/SpecHelper.js
@@ -72,6 +72,24 @@ beforeEach(function() {
};
};
/* jshint +W121 */
+
+ // add gon defaults
+ window.gon = {
+ appConfig: {
+ chat: {enabled: false},
+ settings: {podname: "MyPod"},
+ map: {
+ mapbox: {
+ enabled: false,
+ /* eslint-disable camelcase */
+ access_token: null,
+ /* eslint-enable camelcase */
+ style: "mapbox/streets-v9"
+ }
+ }
+ },
+ preloads: {}
+ };
});
afterEach(function() {
@@ -84,6 +102,7 @@ afterEach(function() {
expect($(".modal-backdrop").length).toBe(0);
$(".modal-backdrop").remove();
spec.loadFixtureCount = 0;
+ $(document.body).off();
});
diff --git a/spec/javascripts/jasmine_helpers/factory.js b/spec/javascripts/jasmine_helpers/factory.js
index 551fe87bc..ba97e5b71 100644
--- a/spec/javascripts/jasmine_helpers/factory.js
+++ b/spec/javascripts/jasmine_helpers/factory.js
@@ -21,6 +21,16 @@ var factory = {
return _.extend(defaultAttrs, overrides);
},
+ reshare: function(overrides) {
+ var defaultAttrs = {
+ "created_at": "2012-01-04T00:55:30Z",
+ "author": this.author(),
+ "guid": this.guid(),
+ "id": this.id.next()
+ };
+ return _.extend(defaultAttrs, overrides);
+ },
+
aspectMembershipAttrs: function(overrides) {
var id = this.id.next();
var defaultAttrs = {
@@ -207,6 +217,24 @@ var factory = {
return new app.models.Post(_.extend(defaultAttrs, overrides));
},
+ postWithInteractions: function(overrides) {
+ var likes = _.range(10).map(function() { return factory.like(); });
+ var reshares = _.range(15).map(function() { return factory.reshare(); });
+ var comments = _.range(20).map(function() { return factory.comment(); });
+ var defaultAttrs = _.extend(factory.postAttrs(), {
+ "author": this.author(),
+ "interactions": {
+ "reshares_count": 15,
+ "likes_count": 10,
+ "comments_count": 20,
+ "comments": comments,
+ "likes": likes,
+ "reshares": reshares
+ }
+ });
+ return new app.models.Post(_.extend(defaultAttrs, overrides));
+ },
+
statusMessage : function(overrides){
//intentionally doesn't have an author to mirror creation process, maybe we should change the creation process
return new app.models.StatusMessage(_.extend(factory.postAttrs(), overrides));
diff --git a/spec/javascripts/mobile/mobile_comments_spec.js b/spec/javascripts/mobile/mobile_comments_spec.js
index e87a81adc..af12f644c 100644
--- a/spec/javascripts/mobile/mobile_comments_spec.js
+++ b/spec/javascripts/mobile/mobile_comments_spec.js
@@ -10,7 +10,7 @@ describe("Diaspora.Mobile.Comments", function(){
spyOn(Diaspora.Mobile.Comments, "submitComment").and.returnValue(false);
Diaspora.Mobile.Comments.initialize();
Diaspora.Mobile.Comments.showCommentBox($(".stream .comment-action").first());
- $(".stream .new_comment").first().submit();
+ $(".stream .new-comment").first().submit();
expect(Diaspora.Mobile.Comments.submitComment).toHaveBeenCalled();
});
});
@@ -97,28 +97,28 @@ describe("Diaspora.Mobile.Comments", function(){
});
it("doesn't submit an empty comment", function() {
- $(".stream .new_comment").first().submit();
+ $(".stream .new-comment").first().submit();
expect(jasmine.Ajax.requests.count()).toBe(0);
});
it("submits comments with text", function() {
- $(".stream .new_comment textarea").val("comment text");
- $(".stream .new_comment").first().submit();
+ $(".stream .new-comment textarea").val("comment text");
+ $(".stream .new-comment").first().submit();
expect(jasmine.Ajax.requests.mostRecent().data().text).toEqual(["comment text"]);
});
it("calls updateStream on success", function() {
spyOn(Diaspora.Mobile.Comments, "updateStream");
- $(".stream .new_comment textarea").val("comment text");
- $(".stream .new_comment").first().submit();
+ $(".stream .new-comment textarea").val("comment text");
+ $(".stream .new-comment").first().submit();
jasmine.Ajax.requests.mostRecent().respondWith({status: 200, responseText: "foo"});
- expect(Diaspora.Mobile.Comments.updateStream).toHaveBeenCalledWith($(".stream .new_comment").first(), "foo");
+ expect(Diaspora.Mobile.Comments.updateStream).toHaveBeenCalledWith($(".stream .new-comment").first(), "foo");
});
it("lets Diaspora.Mobile.Alert handle AJAX errors", function() {
spyOn(Diaspora.Mobile.Alert, "handleAjaxError");
- $(".stream .new_comment textarea").val("comment text");
- $(".stream .new_comment").first().submit();
+ $(".stream .new-comment textarea").val("comment text");
+ $(".stream .new-comment").first().submit();
jasmine.Ajax.requests.mostRecent().respondWith({status: 400, responseText: "oh noez! comment failed!"});
expect(Diaspora.Mobile.Alert.handleAjaxError).toHaveBeenCalled();
expect(Diaspora.Mobile.Alert.handleAjaxError.calls.argsFor(0)[0].responseText).toBe("oh noez! comment failed!");
@@ -126,10 +126,10 @@ describe("Diaspora.Mobile.Comments", function(){
it("calls resetCommentBox on errors", function() {
spyOn(Diaspora.Mobile.Comments, "resetCommentBox");
- $(".stream .new_comment textarea").val("comment text");
- $(".stream .new_comment").first().submit();
+ $(".stream .new-comment textarea").val("comment text");
+ $(".stream .new-comment").first().submit();
jasmine.Ajax.requests.mostRecent().respondWith({status: 400, responseText: "oh noez! comment failed!"});
- expect(Diaspora.Mobile.Comments.resetCommentBox).toHaveBeenCalledWith($(".stream .new_comment").first());
+ expect(Diaspora.Mobile.Comments.resetCommentBox).toHaveBeenCalledWith($(".stream .new-comment").first());
});
});
diff --git a/spec/javascripts/mobile/mobile_post_actions_spec.js b/spec/javascripts/mobile/mobile_post_actions_spec.js
index a33a29994..bbb65b23d 100644
--- a/spec/javascripts/mobile/mobile_post_actions_spec.js
+++ b/spec/javascripts/mobile/mobile_post_actions_spec.js
@@ -88,7 +88,7 @@ describe("Diaspora.Mobile.PostActions", function(){
spec.loadFixture("aspects_index_mobile_public_post");
Diaspora.Mobile.PostActions.initialize();
this.link = $(".stream .like-action").first();
- this.likeCounter = this.link.closest(".stream-element").find(".like-count");
+ this.likeCounter = this.link.find(".like-count");
});
it("always calls showLoader before sending request", function(){
@@ -143,7 +143,7 @@ describe("Diaspora.Mobile.PostActions", function(){
spec.loadFixture("aspects_index_mobile_public_post");
Diaspora.Mobile.PostActions.initialize();
this.link = $(".stream .like-action").first();
- this.likeCounter = this.link.closest(".stream-element").find(".like-count");
+ this.likeCounter = this.link.find(".like-count");
Diaspora.Mobile.PostActions.like(this.likeCounter, this.link);
jasmine.Ajax.requests.mostRecent().respondWith({status: 201, responseText: "{\"id\": \"18\"}"});
});
@@ -238,6 +238,17 @@ describe("Diaspora.Mobile.PostActions", function(){
expect(Diaspora.Mobile.PostActions.toggleActive).toHaveBeenCalledWith(this.reshareLink);
});
+ it("increases the reshare count on success", function() {
+ spyOn(Diaspora.Mobile.PostActions, "toggleActive");
+ var reshareCounter = this.reshareLink.find(".reshare-count");
+ reshareCounter.text("8");
+
+ this.reshareLink.click();
+ jasmine.Ajax.requests.mostRecent().respondWith({status: 201, responseText: "{}"});
+ expect(Diaspora.Mobile.PostActions.toggleActive).toHaveBeenCalledWith(this.reshareLink);
+ expect(reshareCounter.text()).toBe("9");
+ });
+
it("lets Diaspora.Mobile.Alert handle AJAX errors", function() {
spyOn(Diaspora.Mobile.Alert, "handleAjaxError");
this.reshareLink.click();
diff --git a/spec/lib/account_deleter_spec.rb b/spec/lib/account_deleter_spec.rb
index e67920157..01552e3ab 100644
--- a/spec/lib/account_deleter_spec.rb
+++ b/spec/lib/account_deleter_spec.rb
@@ -4,35 +4,29 @@
describe AccountDeleter do
before do
- @account_deletion = AccountDeleter.new(bob.person.diaspora_handle)
+ @account_deletion = AccountDeleter.new(bob.person)
@account_deletion.user = bob
end
it "attaches the user" do
- expect(AccountDeleter.new(bob.person.diaspora_handle).user).to eq(bob)
- expect(AccountDeleter.new(remote_raphael.diaspora_handle).user).to eq(nil)
+ expect(AccountDeleter.new(bob.person).user).to eq(bob)
+ expect(AccountDeleter.new(remote_raphael).user).to eq(nil)
end
describe '#perform' do
- user_removal_methods = %i(
- delete_standard_user_associations
- remove_share_visibilities_on_contacts_posts
- disconnect_contacts tombstone_user
- )
-
- person_removal_methods = %i(
+ person_removal_methods = %i[
delete_contacts_of_me
delete_standard_person_associations
tombstone_person_and_profile
remove_conversation_visibilities
- )
+ ]
context "user deletion" do
after do
@account_deletion.perform!
end
- (user_removal_methods + person_removal_methods).each do |method|
+ [*person_removal_methods, :close_user].each do |method|
it "calls ##{method.to_s}" do
expect(@account_deletion).to receive(method)
@@ -42,7 +36,7 @@ describe AccountDeleter do
context "profile deletion" do
before do
- @profile_deletion = AccountDeleter.new(remote_raphael.diaspora_handle)
+ @profile_deletion = AccountDeleter.new(remote_raphael)
@profile = remote_raphael.profile
end
@@ -57,18 +51,15 @@ describe AccountDeleter do
context "person deletion" do
before do
- @person_deletion = AccountDeleter.new(remote_raphael.diaspora_handle)
+ @person_deletion = AccountDeleter.new(remote_raphael)
end
after do
@person_deletion.perform!
end
- (user_removal_methods).each do |method|
-
- it "does not call ##{method.to_s}" do
- expect(@person_deletion).not_to receive(method)
- end
+ it "does not call #close_user" do
+ expect(@person_deletion).not_to receive(:close_user)
end
(person_removal_methods).each do |method|
@@ -81,6 +72,24 @@ describe AccountDeleter do
end
+ describe "#close_user" do
+ user_removal_methods = %i[
+ delete_standard_user_associations
+ remove_share_visibilities_on_contacts_posts
+ disconnect_contacts tombstone_user
+ ]
+
+ after do
+ @account_deletion.perform!
+ end
+
+ user_removal_methods.each do |method|
+ it "calls ##{method}" do
+ expect(@account_deletion).to receive(method)
+ end
+ end
+ end
+
describe "#delete_standard_user_associations" do
it 'removes all standard user associaltions' do
@account_deletion.normal_ar_user_associates_to_delete.each do |asso|
@@ -108,14 +117,16 @@ describe AccountDeleter do
end
end
- context 'person associations' do
- describe '#disconnect_contacts' do
+ context "user associations" do
+ describe "#disconnect_contacts" do
it "deletes all of user's contacts" do
expect(bob.contacts).to receive(:destroy_all)
@account_deletion.disconnect_contacts
end
end
+ end
+ context 'person associations' do
describe '#delete_contacts_of_me' do
it 'deletes all the local contact objects where deleted account is the person' do
contacts = double
diff --git a/spec/lib/api/openid_connect/protected_resource_endpoint_spec.rb b/spec/lib/api/openid_connect/protected_resource_endpoint_spec.rb
index e93a995ef..fc2f4cb11 100644
--- a/spec/lib/api/openid_connect/protected_resource_endpoint_spec.rb
+++ b/spec/lib/api/openid_connect/protected_resource_endpoint_spec.rb
@@ -11,7 +11,7 @@ describe Api::OpenidConnect::ProtectedResourceEndpoint, type: :request do
context "when valid access token is provided" do
before do
- get api_openid_connect_user_info_path, access_token: access_token_with_read
+ get api_openid_connect_user_info_path, params: {access_token: access_token_with_read}
end
it "includes private in the cache-control header" do
@@ -21,7 +21,7 @@ describe Api::OpenidConnect::ProtectedResourceEndpoint, type: :request do
context "when access token is expired" do
before do
- get api_openid_connect_user_info_path, access_token: expired_access_token
+ get api_openid_connect_user_info_path, params: {access_token: expired_access_token}
end
it "should respond with a 401 Unauthorized response" do
@@ -47,7 +47,7 @@ describe Api::OpenidConnect::ProtectedResourceEndpoint, type: :request do
context "when an invalid access token is provided" do
before do
- get api_openid_connect_user_info_path, access_token: invalid_token
+ get api_openid_connect_user_info_path, params: {access_token: invalid_token}
end
it "should respond with a 401 Unauthorized response" do
@@ -66,7 +66,7 @@ describe Api::OpenidConnect::ProtectedResourceEndpoint, type: :request do
context "when authorization has been destroyed" do
before do
auth_with_read.destroy
- get api_openid_connect_user_info_path, access_token: access_token_with_read
+ get api_openid_connect_user_info_path, params: {access_token: access_token_with_read}
end
it "should respond with a 401 Unauthorized response" do
diff --git a/spec/lib/api/openid_connect/token_endpoint_spec.rb b/spec/lib/api/openid_connect/token_endpoint_spec.rb
index a455f8ffa..440d8132a 100644
--- a/spec/lib/api/openid_connect/token_endpoint_spec.rb
+++ b/spec/lib/api/openid_connect/token_endpoint_spec.rb
@@ -5,7 +5,7 @@ describe Api::OpenidConnect::TokenEndpoint, type: :request do
o_auth_application: client, user: bob, redirect_uri: "http://localhost:3000/", scopes: ["openid"])
}
let!(:code) { auth.create_code }
- let!(:client_with_specific_id) { FactoryGirl.create(:o_auth_application_with_ppid_with_specific_id) }
+ let!(:client_with_specific_id) { FactoryGirl.create(:o_auth_application_with_ppid) }
let!(:auth_with_specific_id) do
client_with_specific_id.client_id = "14d692cd53d9c1a9f46fd69e0e57443e"
client_with_specific_id.jwks = File.read(jwks_file_path)
@@ -19,9 +19,9 @@ describe Api::OpenidConnect::TokenEndpoint, type: :request do
describe "the authorization code grant type" do
context "when the authorization code is valid" do
before do
- post api_openid_connect_access_tokens_path, grant_type: "authorization_code",
+ post api_openid_connect_access_tokens_path, params: {grant_type: "authorization_code",
client_id: client.client_id, client_secret: client.client_secret,
- redirect_uri: "http://localhost:3000/", code: code
+ redirect_uri: "http://localhost:3000/", code: code}
end
it "should return a valid id token" do
@@ -53,26 +53,26 @@ describe Api::OpenidConnect::TokenEndpoint, type: :request do
it "should not allow code to be reused" do
auth.reload
- post api_openid_connect_access_tokens_path, grant_type: "authorization_code",
+ post api_openid_connect_access_tokens_path, params: {grant_type: "authorization_code",
client_id: client.client_id, client_secret: client.client_secret,
- redirect_uri: "http://localhost:3000/", code: code
+ redirect_uri: "http://localhost:3000/", code: code}
expect(JSON.parse(response.body)["error"]).to eq("invalid_grant")
end
it "should not allow a nil code" do
- post api_openid_connect_access_tokens_path, grant_type: "authorization_code",
+ post api_openid_connect_access_tokens_path, params: {grant_type: "authorization_code",
client_id: client.client_id, client_secret: client.client_secret,
- redirect_uri: "http://localhost:3000/", code: nil
+ redirect_uri: "http://localhost:3000/", code: nil}
expect(JSON.parse(response.body)["error"]).to eq("invalid_request")
end
end
context "when the authorization code is valid with jwt bearer" do
before do
- post api_openid_connect_access_tokens_path, grant_type: "authorization_code",
+ post api_openid_connect_access_tokens_path, params: {grant_type: "authorization_code",
redirect_uri: "http://localhost:3000/", code: code_with_specific_id,
client_assertion_type: "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
- client_assertion: File.read(valid_client_assertion_path)
+ client_assertion: File.read(valid_client_assertion_path)}
end
it "should return a valid id token" do
@@ -97,27 +97,27 @@ describe Api::OpenidConnect::TokenEndpoint, type: :request do
it "should not allow code to be reused" do
auth_with_specific_id.reload
- post api_openid_connect_access_tokens_path, grant_type: "authorization_code",
+ post api_openid_connect_access_tokens_path, params: {grant_type: "authorization_code",
client_id: client.client_id, client_secret: client.client_secret,
- redirect_uri: "http://localhost:3000/", code: code_with_specific_id
+ redirect_uri: "http://localhost:3000/", code: code_with_specific_id}
expect(JSON.parse(response.body)["error"]).to eq("invalid_grant")
end
end
context "when the authorization code is not valid" do
it "should return an invalid grant error" do
- post api_openid_connect_access_tokens_path, grant_type: "authorization_code",
- client_id: client.client_id, client_secret: client.client_secret, code: "123456"
+ post api_openid_connect_access_tokens_path, params: {grant_type: "authorization_code",
+ client_id: client.client_id, client_secret: client.client_secret, code: "123456"}
expect(response.body).to include "invalid_grant"
end
end
context "when the client assertion is in an invalid format" do
before do
- post api_openid_connect_access_tokens_path, grant_type: "authorization_code",
+ post api_openid_connect_access_tokens_path, params: {grant_type: "authorization_code",
redirect_uri: "http://localhost:3000/", code: code_with_specific_id,
client_assertion_type: "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
- client_assertion: "invalid_client_assertion.random"
+ client_assertion: "invalid_client_assertion.random"}
end
it "should return an error" do
@@ -127,10 +127,10 @@ describe Api::OpenidConnect::TokenEndpoint, type: :request do
context "when the client assertion is not matching with jwks keys" do
before do
- post api_openid_connect_access_tokens_path, grant_type: "authorization_code",
+ post api_openid_connect_access_tokens_path, params: {grant_type: "authorization_code",
redirect_uri: "http://localhost:3000/", code: code_with_specific_id,
client_assertion_type: "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
- client_assertion: File.read(client_assertion_with_tampered_sig_path)
+ client_assertion: File.read(client_assertion_with_tampered_sig_path)}
end
it "should return an error" do
@@ -140,10 +140,10 @@ describe Api::OpenidConnect::TokenEndpoint, type: :request do
context "when kid doesn't exist in jwks keys" do
before do
- post api_openid_connect_access_tokens_path, grant_type: "authorization_code",
+ post api_openid_connect_access_tokens_path, params: {grant_type: "authorization_code",
redirect_uri: "http://localhost:3000/", code: code_with_specific_id,
client_assertion_type: "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
- client_assertion: File.read(client_assertion_with_nonexistent_kid_path)
+ client_assertion: File.read(client_assertion_with_nonexistent_kid_path)}
end
it "should return an error" do
@@ -153,18 +153,18 @@ describe Api::OpenidConnect::TokenEndpoint, type: :request do
context "when the client is unregistered" do
it "should return an error" do
- post api_openid_connect_access_tokens_path, grant_type: "authorization_code", code: auth.refresh_token,
- client_id: SecureRandom.hex(16).to_s, client_secret: client.client_secret
+ post api_openid_connect_access_tokens_path, params: {grant_type: "authorization_code", code: auth.refresh_token,
+ client_id: SecureRandom.hex(16).to_s, client_secret: client.client_secret}
expect(response.body).to include "invalid_client"
end
end
context "when the client is unregistered with jwks keys" do
before do
- post api_openid_connect_access_tokens_path, grant_type: "authorization_code",
+ post api_openid_connect_access_tokens_path, params: {grant_type: "authorization_code",
redirect_uri: "http://localhost:3000/", code: code_with_specific_id,
client_assertion_type: "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
- client_assertion: File.read(client_assertion_with_nonexistent_client_id_path)
+ client_assertion: File.read(client_assertion_with_nonexistent_client_id_path)}
end
it "should return an error" do
@@ -174,16 +174,16 @@ describe Api::OpenidConnect::TokenEndpoint, type: :request do
context "when the code field is missing" do
it "should return an invalid request error" do
- post api_openid_connect_access_tokens_path, grant_type: "authorization_code",
- client_id: client.client_id, client_secret: client.client_secret
+ post api_openid_connect_access_tokens_path, params: {grant_type: "authorization_code",
+ client_id: client.client_id, client_secret: client.client_secret}
expect(response.body).to include "invalid_request"
end
end
context "when the client_secret doesn't match" do
it "should return an invalid client error" do
- post api_openid_connect_access_tokens_path, grant_type: "authorization_code", code: auth.refresh_token,
- client_id: client.client_id, client_secret: "client.client_secret"
+ post api_openid_connect_access_tokens_path, params: {grant_type: "authorization_code", code: auth.refresh_token,
+ client_id: client.client_id, client_secret: "client.client_secret"}
expect(response.body).to include "invalid_client"
end
end
@@ -191,8 +191,8 @@ describe Api::OpenidConnect::TokenEndpoint, type: :request do
describe "an unsupported grant type" do
it "should return an unsupported grant type error" do
- post api_openid_connect_access_tokens_path, grant_type: "noexistgrant", username: "bob",
- password: "bluepin7", client_id: client.client_id, client_secret: client.client_secret, scope: "read"
+ post api_openid_connect_access_tokens_path, params: {grant_type: "noexistgrant", username: "bob",
+ password: "bluepin7", client_id: client.client_id, client_secret: client.client_secret, scope: "read"}
expect(response.body).to include "unsupported_grant_type"
end
end
@@ -200,8 +200,8 @@ describe Api::OpenidConnect::TokenEndpoint, type: :request do
describe "the refresh token grant type" do
context "when the refresh token is valid" do
it "should return an access token" do
- post api_openid_connect_access_tokens_path, grant_type: "refresh_token",
- client_id: client.client_id, client_secret: client.client_secret, refresh_token: auth.refresh_token
+ post api_openid_connect_access_tokens_path, params: {grant_type: "refresh_token",
+ client_id: client.client_id, client_secret: client.client_secret, refresh_token: auth.refresh_token}
json = JSON.parse(response.body)
expect(response.body).to include "expires_in"
expect(json["access_token"].length).to eq(64)
@@ -211,32 +211,34 @@ describe Api::OpenidConnect::TokenEndpoint, type: :request do
context "when the refresh token is not valid" do
it "should return an invalid grant error" do
- post api_openid_connect_access_tokens_path, grant_type: "refresh_token",
- client_id: client.client_id, client_secret: client.client_secret, refresh_token: "123456"
+ post api_openid_connect_access_tokens_path, params: {grant_type: "refresh_token",
+ client_id: client.client_id, client_secret: client.client_secret, refresh_token: "123456"}
expect(response.body).to include "invalid_grant"
end
end
context "when the client is unregistered" do
it "should return an error" do
- post api_openid_connect_access_tokens_path, grant_type: "refresh_token", refresh_token: auth.refresh_token,
- client_id: SecureRandom.hex(16).to_s, client_secret: client.client_secret
+ post api_openid_connect_access_tokens_path, params: {grant_type: "refresh_token",
+ refresh_token: auth.refresh_token,
+ client_id: SecureRandom.hex(16).to_s, client_secret: client.client_secret}
expect(response.body).to include "invalid_client"
end
end
context "when the refresh_token field is missing" do
it "should return an invalid request error" do
- post api_openid_connect_access_tokens_path, grant_type: "refresh_token",
- client_id: client.client_id, client_secret: client.client_secret
+ post api_openid_connect_access_tokens_path, params: {grant_type: "refresh_token",
+ client_id: client.client_id, client_secret: client.client_secret}
expect(response.body).to include "'refresh_token' required"
end
end
context "when the client_secret doesn't match" do
it "should return an invalid client error" do
- post api_openid_connect_access_tokens_path, grant_type: "refresh_token", refresh_token: auth.refresh_token,
- client_id: client.client_id, client_secret: "client.client_secret"
+ post api_openid_connect_access_tokens_path, params: {grant_type: "refresh_token",
+ refresh_token: auth.refresh_token,
+ client_id: client.client_id, client_secret: "client.client_secret"}
expect(response.body).to include "invalid_client"
end
end
diff --git a/spec/lib/diaspora/exporter/non_contact_authors_spec.rb b/spec/lib/diaspora/exporter/non_contact_authors_spec.rb
new file mode 100644
index 000000000..cac8c3ca0
--- /dev/null
+++ b/spec/lib/diaspora/exporter/non_contact_authors_spec.rb
@@ -0,0 +1,25 @@
+describe Diaspora::Exporter::NonContactAuthors do
+ describe "#query" do
+ let(:user) { FactoryGirl.create(:user_with_aspect) }
+ let(:post) { FactoryGirl.create(:status_message) }
+ let(:instance) {
+ Diaspora::Exporter::NonContactAuthors.new(Post.where(id: post.id), user)
+ }
+
+ context "without contact relationship" do
+ it "includes post author to the result set" do
+ expect(instance.query).to eq([post.author])
+ end
+ end
+
+ context "with contact relationship" do
+ before do
+ user.share_with(post.author, user.aspects.first)
+ end
+
+ it "doesn't include post author to the result set" do
+ expect(instance.query).to be_empty
+ end
+ end
+ end
+end
diff --git a/spec/lib/diaspora/exporter/others_relayables_spec.rb b/spec/lib/diaspora/exporter/others_relayables_spec.rb
new file mode 100644
index 000000000..95595739f
--- /dev/null
+++ b/spec/lib/diaspora/exporter/others_relayables_spec.rb
@@ -0,0 +1,35 @@
+describe Diaspora::Exporter::OthersRelayables do
+ let(:status_message) { FactoryGirl.create(:status_message) }
+ let(:person) { status_message.author }
+ let(:instance) { Diaspora::Exporter::OthersRelayables.new(person.id) }
+
+ describe "#comments" do
+ let(:comment) { FactoryGirl.create(:comment, post: status_message) }
+
+ it "has a comment in the data set" do
+ expect(instance.comments).to eq([comment])
+ end
+ end
+
+ describe "#likes" do
+ let(:like) { FactoryGirl.create(:like, target: status_message) }
+
+ it "has a like in the data set" do
+ expect(instance.likes).to eq([like])
+ end
+ end
+
+ describe "#poll_participations" do
+ let(:status_message) { FactoryGirl.create(:status_message_with_poll) }
+ let(:poll_participation) {
+ FactoryGirl.create(
+ :poll_participation,
+ poll_answer: status_message.poll.poll_answers.first
+ )
+ }
+
+ it "has a poll participation in the data set" do
+ expect(instance.poll_participations).to eq([poll_participation])
+ end
+ end
+end
diff --git a/spec/lib/diaspora/exporter/posts_with_activity_spec.rb b/spec/lib/diaspora/exporter/posts_with_activity_spec.rb
new file mode 100644
index 000000000..4dc27495c
--- /dev/null
+++ b/spec/lib/diaspora/exporter/posts_with_activity_spec.rb
@@ -0,0 +1,24 @@
+describe Diaspora::Exporter::PostsWithActivity do
+ let(:user) { FactoryGirl.create(:user) }
+ let(:instance) { Diaspora::Exporter::PostsWithActivity.new(user) }
+
+ describe "#query" do
+ let(:activity) {
+ [
+ user.person.likes.first.target,
+ user.person.comments.first.parent,
+ user.person.poll_participations.first.parent.status_message,
+ user.person.participations.first.target,
+ user.person.posts.reshares.first.root
+ ]
+ }
+
+ before do
+ DataGenerator.create(user, %i[activity participation])
+ end
+
+ it "returns all posts with person's activity" do
+ expect(instance.query).to match_array(activity)
+ end
+ end
+end
diff --git a/spec/lib/diaspora/exporter_spec.rb b/spec/lib/diaspora/exporter_spec.rb
index d12cfd2d0..7db86e82f 100644
--- a/spec/lib/diaspora/exporter_spec.rb
+++ b/spec/lib/diaspora/exporter_spec.rb
@@ -1,86 +1,15 @@
-# Copyright (c) 2010-2011, Diaspora Inc. This file is
-# licensed under the Affero General Public License version 3 or later. See
-# the COPYRIGHT file.
-
-require Rails.root.join('lib', 'diaspora', 'exporter')
-
describe Diaspora::Exporter do
-
- before do
- @user1 = alice
-
- @user1.person.profile.first_name = "<script>"
- @user1.person.profile.gender = "<script>"
- @user1.person.profile.bio = "<script>"
- @user1.person.profile.location = "<script>"
- @user1.person.profile.save
-
- @aspect = @user1.aspects.first
- @aspect1 = @user1.aspects.create(:name => "Work", :contacts_visible => false)
- @aspect.name = "<script>"
- @aspect.save
- end
-
- context "json" do
-
- def json
- @json ||= JSON.parse Diaspora::Exporter.new(@user1).execute
- end
-
- it { matches :version, to: '1.0' }
- it { matches :user, :name }
- it { matches :user, :email }
- it { matches :user, :username }
- it { matches :user, :language }
- it { matches :user, :disable_mail }
- it { matches :user, :show_community_spotlight_in_stream }
- it { matches :user, :auto_follow_back }
- it { matches :user, :auto_follow_back_aspect }
- it { matches :user, :strip_exif }
-
- it { matches :user, :profile, :first_name, root: @user1.person.profile }
- it { matches :user, :profile, :last_name, root: @user1.person.profile }
- it { matches :user, :profile, :gender, root: @user1.person.profile }
- it { matches :user, :profile, :bio, root: @user1.person.profile }
- it { matches :user, :profile, :location, root: @user1.person.profile }
- it { matches :user, :profile, :image_url, root: @user1.person.profile }
- it { matches :user, :profile, :diaspora_handle, root: @user1.person.profile }
- it { matches :user, :profile, :searchable, root: @user1.person.profile }
- it { matches :user, :profile, :nsfw, root: @user1.person.profile }
-
- it { matches_relation :aspects, :name,
- :contacts_visible,
- :chat_enabled }
-
- it { matches_relation :contacts, :sharing,
- :receiving,
- :person_guid,
- :person_name,
- :person_first_name,
- :person_diaspora_handle }
-
- private
-
- def matches(*fields, to: nil, root: @user1)
- expected = to || root.send(fields.last)
- expect(recurse_field(json, fields)).to eq expected
+ describe "#execute" do
+ it "calls exporters and forms JSON" do
+ expect_any_instance_of(Export::UserSerializer).to receive(:as_json).and_return(user: "user_data")
+ expect_any_instance_of(Export::OthersDataSerializer).to receive(:as_json).and_return(others_date: "others_data")
+
+ json = Diaspora::Exporter.new(nil).execute
+ expect(json).to include_json(
+ version: "2.0",
+ user: "user_data",
+ others_date: "others_data"
+ )
end
-
- def matches_relation(relation, *fields, to: nil, root: @user1)
- array = json['user'][to || relation.to_s]
- fields.each do |field|
- expected = root.send(relation).map(&:"#{field}")
- expect(array.map { |f| f[field.to_s] }).to eq expected
- end
- end
-
- def recurse_field(json, fields)
- if fields.any?
- recurse_field json[fields.shift.to_s], fields
- else
- json
- end
- end
-
end
end
diff --git a/spec/lib/diaspora/federated/contact_retraction_spec.rb b/spec/lib/diaspora/federated/contact_retraction_spec.rb
new file mode 100644
index 000000000..bd5c7c3dd
--- /dev/null
+++ b/spec/lib/diaspora/federated/contact_retraction_spec.rb
@@ -0,0 +1,66 @@
+describe ContactRetraction do
+ let(:contact) { FactoryGirl.build(:contact, sharing: true, receiving: true) }
+ let(:retraction) { ContactRetraction.for(contact) }
+
+ describe "#subscribers" do
+ it "contains the contact person" do
+ expect(retraction.subscribers).to eq([contact.person])
+ end
+ end
+
+ describe "#data" do
+ it "contains the hash with all data from the federation-retraction" do
+ federation_retraction_data = Diaspora::Federation::Entities.contact(contact).to_h
+ federation_retraction_data[:sharing] = false
+ federation_retraction_data[:following] = false
+
+ expect(retraction.data).to eq(federation_retraction_data)
+ end
+ end
+
+ describe ".retraction_data_for" do
+ it "creates a retraction for a contact" do
+ contact = FactoryGirl.build(:contact, sharing: false, receiving: false)
+ expect(Diaspora::Federation::Entities).to receive(:contact).with(contact).and_call_original
+ data = ContactRetraction.retraction_data_for(contact)
+
+ expect(data[:author]).to eq(contact.user.diaspora_handle)
+ expect(data[:recipient]).to eq(contact.person.diaspora_handle)
+ expect(data[:sharing]).to be_falsey
+ expect(data[:following]).to be_falsey
+ end
+ end
+
+ describe ".for" do
+ it "creates a retraction for a contact" do
+ expect(ContactRetraction).to receive(:retraction_data_for).with(contact)
+ ContactRetraction.for(contact)
+ end
+
+ it "create contact entity with 'sharing' and 'following' set to false" do
+ data = ContactRetraction.for(contact).data
+ expect(data[:sharing]).to be_falsey
+ expect(data[:following]).to be_falsey
+ end
+ end
+
+ describe ".defer_dispatch" do
+ it "queues a job to send the retraction later" do
+ contact = FactoryGirl.build(:contact, user: local_luke, person: remote_raphael)
+ retraction = ContactRetraction.for(contact)
+ federation_retraction_data = Diaspora::Federation::Entities.contact(contact).to_h
+
+ expect(Workers::DeferredRetraction).to receive(:perform_async).with(
+ local_luke.id, "ContactRetraction", federation_retraction_data, [remote_raphael.id], {}
+ )
+
+ retraction.defer_dispatch(local_luke)
+ end
+ end
+
+ describe "#public?" do
+ it "returns false for a contact retraction" do
+ expect(retraction.public?).to be_falsey
+ end
+ end
+end
diff --git a/spec/lib/diaspora/federated/retraction_spec.rb b/spec/lib/diaspora/federated/retraction_spec.rb
index 3f7b9f39b..565f22387 100644
--- a/spec/lib/diaspora/federated/retraction_spec.rb
+++ b/spec/lib/diaspora/federated/retraction_spec.rb
@@ -4,13 +4,13 @@
describe Retraction do
let(:post) { alice.post(:status_message, text: "destroy!", public: true) }
- let(:retraction) { Retraction.for(post, alice) }
+ let(:retraction) { Retraction.for(post) }
describe "#subscribers" do
it "contains all remote-subscribers of target object" do
post = local_luke.post(:status_message, text: "destroy!", public: true)
- retraction = Retraction.for(post, local_luke)
+ retraction = Retraction.for(post)
expect(retraction.subscribers).to eq([remote_raphael])
end
@@ -18,46 +18,60 @@ describe Retraction do
describe "#data" do
it "contains the hash with all data from the federation-retraction" do
- federation_retraction = Diaspora::Federation::Entities.signed_retraction(post, alice)
+ expect(retraction.data[:target_guid]).to eq(post.guid)
+ expect(retraction.data[:target]).to eq(Diaspora::Federation::Entities.related_entity(post).to_h)
+ expect(retraction.data[:target_type]).to eq("Post")
+ expect(retraction.data[:author]).to eq(alice.diaspora_handle)
+ end
+ end
- expect(retraction.data).to eq(federation_retraction.to_h)
+ describe ".retraction_data_for" do
+ it "creates the retraction data for a post" do
+ data = Retraction.retraction_data_for(post)
+ expect(data[:target_guid]).to eq(post.guid)
+ expect(data[:target]).to eq(Diaspora::Federation::Entities.related_entity(post).to_h)
+ expect(data[:target_type]).to eq("Post")
+ expect(data[:author]).to eq(alice.diaspora_handle)
+ end
+
+ it "creates the retraction data for a relayable" do
+ comment = FactoryGirl.create(:comment, author: alice.person, post: post)
+
+ data = Retraction.retraction_data_for(comment)
+ expect(data[:target_guid]).to eq(comment.guid)
+ expect(data[:target]).to eq(Diaspora::Federation::Entities.related_entity(comment).to_h)
+ expect(data[:target_type]).to eq("Comment")
+ expect(data[:author]).to eq(alice.diaspora_handle)
end
end
describe ".for" do
it "creates a retraction for a post" do
- expect(Diaspora::Federation::Entities).to receive(:signed_retraction).with(post, alice)
+ expect(Retraction).to receive(:retraction_data_for).with(post)
- Retraction.for(post, alice)
+ Retraction.for(post)
end
it "creates a retraction for a relayable" do
comment = FactoryGirl.create(:comment, author: alice.person, post: post)
- expect(Diaspora::Federation::Entities).to receive(:relayable_retraction).with(comment, alice)
+ expect(Retraction).to receive(:retraction_data_for).with(comment)
- Retraction.for(comment, alice)
- end
-
- it "creates a retraction for a contact" do
- contact = FactoryGirl.create(:contact)
-
- expect(Diaspora::Federation::Entities).to receive(:retraction).with(contact)
-
- Retraction.for(contact, contact.user)
+ Retraction.for(comment)
end
end
describe ".defer_dispatch" do
it "queues a job to send the retraction later" do
post = local_luke.post(:status_message, text: "destroy!", public: true)
- federation_retraction = Diaspora::Federation::Entities.signed_retraction(post, local_luke)
+ retraction = Retraction.for(post)
+ federation_retraction = Diaspora::Federation::Entities.retraction(retraction)
expect(Workers::DeferredRetraction).to receive(:perform_async).with(
- local_luke.id, federation_retraction.to_h, [remote_raphael.id], service_types: []
+ local_luke.id, "Retraction", federation_retraction.to_h, [remote_raphael.id], service_types: []
)
- Retraction.for(post, local_luke).defer_dispatch(local_luke)
+ retraction.defer_dispatch(local_luke)
end
it "adds service metadata to queued job for deletion" do
@@ -66,47 +80,38 @@ describe Retraction do
facebook = Services::Facebook.new(access_token: "facebook")
alice.services << twitter << facebook
- federation_retraction = Diaspora::Federation::Entities.signed_retraction(post, alice)
+ retraction = Retraction.for(post)
+ federation_retraction = Diaspora::Federation::Entities.retraction(retraction)
expect(Workers::DeferredRetraction).to receive(:perform_async).with(
- alice.id, federation_retraction.to_h, [], service_types: ["Services::Twitter"], tweet_id: "123"
+ alice.id, "Retraction", federation_retraction.to_h, [], service_types: ["Services::Twitter"], tweet_id: "123"
)
- Retraction.for(post, alice).defer_dispatch(alice)
+ retraction.defer_dispatch(alice)
end
it "queues also a job if subscribers is empty" do
- federation_retraction = Diaspora::Federation::Entities.signed_retraction(post, alice)
+ retraction = Retraction.for(post)
+ federation_retraction = Diaspora::Federation::Entities.retraction(retraction)
expect(Workers::DeferredRetraction).to receive(:perform_async).with(
- alice.id, federation_retraction.to_h, [], service_types: []
+ alice.id, "Retraction", federation_retraction.to_h, [], service_types: []
)
- Retraction.for(post, alice).defer_dispatch(alice)
+ retraction.defer_dispatch(alice)
end
it "queues a job with empty opts for non-StatusMessage" do
post = local_luke.post(:status_message, text: "hello", public: true)
comment = local_luke.comment!(post, "destroy!")
- federation_retraction = Diaspora::Federation::Entities.relayable_retraction(comment, local_luke)
-
- expect(Workers::DeferredRetraction).to receive(:perform_async).with(
- local_luke.id, federation_retraction.to_h, [remote_raphael.id], {}
- )
-
- Retraction.for(comment, local_luke).defer_dispatch(local_luke)
- end
-
- it "uses the author of the target parent as sender for a comment-retraction if the parent is local" do
- post = local_luke.post(:status_message, text: "hello", public: true)
- comment = local_leia.comment!(post, "destroy!")
- federation_retraction = Diaspora::Federation::Entities.relayable_retraction(comment, local_leia)
+ retraction = Retraction.for(comment)
+ federation_retraction = Diaspora::Federation::Entities.retraction(retraction)
expect(Workers::DeferredRetraction).to receive(:perform_async).with(
- local_luke.id, federation_retraction.to_h, [remote_raphael.id], {}
+ local_luke.id, "Retraction", federation_retraction.to_h, [remote_raphael.id], {}
)
- Retraction.for(comment, local_leia).defer_dispatch(local_leia)
+ retraction.defer_dispatch(local_luke)
end
context "relayable" do
@@ -114,23 +119,25 @@ describe Retraction do
let(:comment) { FactoryGirl.create(:comment, post: post, author: remote_raphael) }
it "sends retraction to target author if deleted by parent author" do
- federation_retraction = Diaspora::Federation::Entities.relayable_retraction(comment, local_luke)
+ retraction = Retraction.for(comment)
+ federation_retraction = Diaspora::Federation::Entities.retraction(retraction)
expect(Workers::DeferredRetraction).to receive(:perform_async).with(
- local_luke.id, federation_retraction.to_h, [remote_raphael.id], {}
+ local_luke.id, "Retraction", federation_retraction.to_h, [remote_raphael.id], {}
)
- Retraction.for(comment, local_luke).defer_dispatch(local_luke)
+ retraction.defer_dispatch(local_luke)
end
it "don't sends retraction back to target author if relayed by parent author" do
- federation_retraction = Diaspora::Federation::Entities.relayable_retraction(comment, local_luke)
+ retraction = Retraction.for(comment)
+ federation_retraction = Diaspora::Federation::Entities.retraction(retraction)
expect(Workers::DeferredRetraction).to receive(:perform_async).with(
- local_luke.id, federation_retraction.to_h, [], {}
+ local_luke.id, "Retraction", federation_retraction.to_h, [], {}
)
- Retraction.for(comment, local_luke).defer_dispatch(local_luke, false)
+ retraction.defer_dispatch(local_luke, false)
end
end
end
@@ -138,29 +145,29 @@ describe Retraction do
describe "#perform" do
it "destroys the target object" do
expect(post).to receive(:destroy!)
- Retraction.for(post, alice).perform
+ Retraction.for(post).perform
end
end
describe "#public?" do
it "returns true for a public post" do
- expect(Retraction.for(post, alice).public?).to be_truthy
+ expect(Retraction.for(post).public?).to be_truthy
end
it "returns true for a public comment if parent post is local" do
comment = bob.comment!(post, "destroy!")
- expect(Retraction.for(comment, bob).public?).to be_truthy
+ expect(Retraction.for(comment).public?).to be_truthy
end
- it "returns false for a public comment if parent post is not local" do
- remote_post = FactoryGirl.create(:status_message, author: remote_raphael)
+ it "returns true for a public comment if parent post is not local" do
+ remote_post = FactoryGirl.create(:status_message, author: remote_raphael, public: true)
comment = alice.comment!(remote_post, "destroy!")
- expect(Retraction.for(comment, alice).public?).to be_falsey
+ expect(Retraction.for(comment).public?).to be_truthy
end
it "returns false for a private target" do
private_post = alice.post(:status_message, text: "destroy!", to: alice.aspects.first.id)
- expect(Retraction.for(private_post, alice).public?).to be_falsey
+ expect(Retraction.for(private_post).public?).to be_falsey
end
end
end
diff --git a/spec/lib/diaspora/federation/dispatcher/private_spec.rb b/spec/lib/diaspora/federation/dispatcher/private_spec.rb
index 9f20ece51..b1fd867a6 100644
--- a/spec/lib/diaspora/federation/dispatcher/private_spec.rb
+++ b/spec/lib/diaspora/federation/dispatcher/private_spec.rb
@@ -28,18 +28,29 @@ describe Diaspora::Federation::Dispatcher::Private do
end
context "deliver to remote user" do
- let(:xml) { "<diaspora/>" }
+ let(:encryption_key) { double }
+ let(:magic_env) { double }
+ let(:magic_env_xml) { double }
+ let(:json) { "{\"aes_key\": \"...\", \"encrypted_magic_envelope\": \"...\"}" }
+
it "queues a private send job" do
expect(Workers::SendPrivate).to receive(:perform_async) do |user_id, _entity_string, targets|
expect(user_id).to eq(alice.id)
expect(targets.size).to eq(1)
expect(targets).to have_key(remote_raphael.receive_url)
- expect(targets[remote_raphael.receive_url]).to eq(xml)
+ expect(targets[remote_raphael.receive_url]).to eq(json)
end
- salmon = double
- expect(DiasporaFederation::Salmon::EncryptedSlap).to receive(:prepare).and_return(salmon)
- expect(salmon).to receive(:generate_xml).and_return(xml)
+ expect(alice).to receive(:encryption_key).and_return(encryption_key)
+ expect(DiasporaFederation::Salmon::MagicEnvelope).to receive(:new).with(
+ instance_of(DiasporaFederation::Entities::StatusMessage), alice.diaspora_handle
+ ).and_return(magic_env)
+ expect(magic_env).to receive(:envelop).with(encryption_key).and_return(magic_env_xml)
+ expect(DiasporaFederation::Salmon::EncryptedMagicEnvelope).to receive(:encrypt) do |magic_env, public_key|
+ expect(magic_env).to eq(magic_env_xml)
+ expect(public_key.to_s).to eq(remote_raphael.public_key.to_s)
+ json
+ end
Diaspora::Federation::Dispatcher.build(alice, post).dispatch
end
@@ -60,12 +71,19 @@ describe Diaspora::Federation::Dispatcher::Private do
expect(user_id).to eq(alice.id)
expect(targets.size).to eq(1)
expect(targets).to have_key(remote_person.receive_url)
- expect(targets[remote_person.receive_url]).to eq(xml)
+ expect(targets[remote_person.receive_url]).to eq(json)
end
- salmon = double
- expect(DiasporaFederation::Salmon::EncryptedSlap).to receive(:prepare).and_return(salmon)
- expect(salmon).to receive(:generate_xml).and_return(xml)
+ expect(alice).to receive(:encryption_key).and_return(encryption_key)
+ expect(DiasporaFederation::Salmon::MagicEnvelope).to receive(:new).with(
+ instance_of(DiasporaFederation::Entities::StatusMessage), alice.diaspora_handle
+ ).and_return(magic_env)
+ expect(magic_env).to receive(:envelop).with(encryption_key).and_return(magic_env_xml)
+ expect(DiasporaFederation::Salmon::EncryptedMagicEnvelope).to receive(:encrypt) do |magic_env, public_key|
+ expect(magic_env).to eq(magic_env_xml)
+ expect(public_key.to_s).to eq(remote_raphael.public_key.to_s)
+ json
+ end
Diaspora::Federation::Dispatcher.build(alice, post, subscribers: [remote_person]).dispatch
end
@@ -79,12 +97,19 @@ describe Diaspora::Federation::Dispatcher::Private do
expect(user_id).to eq(alice.id)
expect(targets.size).to eq(1)
expect(targets).to have_key(remote_person.receive_url)
- expect(targets[remote_person.receive_url]).to eq(xml)
+ expect(targets[remote_person.receive_url]).to eq(json)
end
- salmon = double
- expect(DiasporaFederation::Salmon::EncryptedSlap).to receive(:prepare).and_return(salmon)
- expect(salmon).to receive(:generate_xml).and_return(xml)
+ expect(alice).to receive(:encryption_key).and_return(encryption_key)
+ expect(DiasporaFederation::Salmon::MagicEnvelope).to receive(:new).with(
+ instance_of(DiasporaFederation::Entities::StatusMessage), alice.diaspora_handle
+ ).and_return(magic_env)
+ expect(magic_env).to receive(:envelop).with(encryption_key).and_return(magic_env_xml)
+ expect(DiasporaFederation::Salmon::EncryptedMagicEnvelope).to receive(:encrypt) do |magic_env, public_key|
+ expect(magic_env).to eq(magic_env_xml)
+ expect(public_key.to_s).to eq(remote_raphael.public_key.to_s)
+ json
+ end
Diaspora::Federation::Dispatcher.build(alice, post, subscribers: [remote_person, offline_person]).dispatch
end
diff --git a/spec/lib/diaspora/federation/dispatcher/public_spec.rb b/spec/lib/diaspora/federation/dispatcher/public_spec.rb
index bb5bac652..f893c7a57 100644
--- a/spec/lib/diaspora/federation/dispatcher/public_spec.rb
+++ b/spec/lib/diaspora/federation/dispatcher/public_spec.rb
@@ -48,7 +48,9 @@ describe Diaspora::Federation::Dispatcher::Public do
end
context "deliver to remote user" do
- let(:salmon_xml) { "<diaspora/>" }
+ let(:encryption_key) { double }
+ let(:magic_env) { double }
+ let(:magic_env_xml) { double(to_xml: "<diaspora/>") }
it "queues a public send job" do
alice.share_with(remote_raphael, alice.aspects.first)
@@ -57,10 +59,14 @@ describe Diaspora::Federation::Dispatcher::Public do
expect(user_id).to eq(alice.id)
expect(urls.size).to eq(1)
expect(urls[0]).to eq(remote_raphael.pod.url_to("/receive/public"))
- expect(xml).to eq(salmon_xml)
+ expect(xml).to eq(magic_env_xml.to_xml)
end
- expect(DiasporaFederation::Salmon::Slap).to receive(:generate_xml).and_return(salmon_xml)
+ expect(alice).to receive(:encryption_key).and_return(encryption_key)
+ expect(DiasporaFederation::Salmon::MagicEnvelope).to receive(:new).with(
+ instance_of(DiasporaFederation::Entities::StatusMessage), alice.diaspora_handle
+ ).and_return(magic_env)
+ expect(magic_env).to receive(:envelop).with(encryption_key).and_return(magic_env_xml)
Diaspora::Federation::Dispatcher.build(alice, post).dispatch
end
@@ -76,11 +82,14 @@ describe Diaspora::Federation::Dispatcher::Public do
expect(user_id).to eq(alice.id)
expect(urls.size).to eq(1)
expect(urls[0]).to eq(remote_raphael.pod.url_to("/receive/public"))
- expect(xml).to eq(salmon_xml)
+ expect(xml).to eq(magic_env_xml.to_xml)
end
- expect(DiasporaFederation::Salmon::Slap).to receive(:generate_xml).and_return(salmon_xml)
-
+ expect(alice).to receive(:encryption_key).and_return(encryption_key)
+ expect(DiasporaFederation::Salmon::MagicEnvelope).to receive(:new).with(
+ instance_of(DiasporaFederation::Entities::StatusMessage), alice.diaspora_handle
+ ).and_return(magic_env)
+ expect(magic_env).to receive(:envelop).with(encryption_key).and_return(magic_env_xml)
Diaspora::Federation::Dispatcher.build(alice, post, subscribers: [remote_raphael]).dispatch
end
@@ -92,10 +101,14 @@ describe Diaspora::Federation::Dispatcher::Public do
expect(user_id).to eq(alice.id)
expect(urls.size).to eq(1)
expect(urls[0]).to eq(remote_raphael.pod.url_to("/receive/public"))
- expect(xml).to eq(salmon_xml)
+ expect(xml).to eq(magic_env_xml.to_xml)
end
- expect(DiasporaFederation::Salmon::Slap).to receive(:generate_xml).and_return(salmon_xml)
+ expect(alice).to receive(:encryption_key).and_return(encryption_key)
+ expect(DiasporaFederation::Salmon::MagicEnvelope).to receive(:new).with(
+ instance_of(DiasporaFederation::Entities::StatusMessage), alice.diaspora_handle
+ ).and_return(magic_env)
+ expect(magic_env).to receive(:envelop).with(encryption_key).and_return(magic_env_xml)
Diaspora::Federation::Dispatcher.build(alice, post, subscribers: [remote_raphael, offline_person]).dispatch
end
diff --git a/spec/lib/diaspora/federation/entities_spec.rb b/spec/lib/diaspora/federation/entities_spec.rb
index 671cbd562..82bad8fb0 100644
--- a/spec/lib/diaspora/federation/entities_spec.rb
+++ b/spec/lib/diaspora/federation/entities_spec.rb
@@ -8,6 +8,16 @@ describe Diaspora::Federation::Entities do
expect(federation_entity.author).to eq(diaspora_entity.person.diaspora_handle)
end
+ it "builds an account migration" do
+ diaspora_entity = FactoryGirl.build(:account_migration)
+ diaspora_entity.old_private_key = OpenSSL::PKey::RSA.generate(1024).export
+ federation_entity = described_class.build(diaspora_entity)
+
+ expect(federation_entity).to be_instance_of(DiasporaFederation::Entities::AccountMigration)
+ expect(federation_entity.author).to eq(diaspora_entity.old_person.diaspora_handle)
+ expect(federation_entity.profile.author).to eq(diaspora_entity.new_person.diaspora_handle)
+ end
+
it "builds a comment" do
diaspora_entity = FactoryGirl.build(:comment)
federation_entity = described_class.build(diaspora_entity)
@@ -18,8 +28,7 @@ describe Diaspora::Federation::Entities do
expect(federation_entity.parent_guid).to eq(diaspora_entity.post.guid)
expect(federation_entity.text).to eq(diaspora_entity.text)
expect(federation_entity.author_signature).to be_nil
- expect(federation_entity.xml_order).to be_nil
- expect(federation_entity.additional_xml_elements).to be_empty
+ expect(federation_entity.additional_data).to be_empty
end
it "builds a comment with signature" do
@@ -32,17 +41,19 @@ describe Diaspora::Federation::Entities do
expect(federation_entity.parent_guid).to eq(diaspora_entity.post.guid)
expect(federation_entity.text).to eq(diaspora_entity.text)
expect(federation_entity.author_signature).to eq(diaspora_entity.signature.author_signature)
- expect(federation_entity.xml_order).to eq(diaspora_entity.signature.signature_order.order.split)
- expect(federation_entity.additional_xml_elements).to eq(diaspora_entity.signature.additional_data)
+ expect(federation_entity.signature_order.map(&:to_s)).to eq(diaspora_entity.signature.signature_order.order.split)
+ expect(federation_entity.additional_data).to eq(diaspora_entity.signature.additional_data)
end
- it "builds a contact (request)" do
- diaspora_entity = FactoryGirl.build(:contact)
+ it "builds a contact" do
+ diaspora_entity = FactoryGirl.build(:contact, receiving: true)
federation_entity = described_class.build(diaspora_entity)
- expect(federation_entity).to be_instance_of(DiasporaFederation::Entities::Request)
+ expect(federation_entity).to be_instance_of(DiasporaFederation::Entities::Contact)
expect(federation_entity.author).to eq(diaspora_entity.user.diaspora_handle)
expect(federation_entity.recipient).to eq(diaspora_entity.person.diaspora_handle)
+ expect(federation_entity.sharing).to be_truthy
+ expect(federation_entity.following).to be_truthy
end
context "Conversation" do
@@ -85,8 +96,7 @@ describe Diaspora::Federation::Entities do
expect(federation_entity.parent_guid).to eq(diaspora_entity.target.guid)
expect(federation_entity.positive).to eq(diaspora_entity.positive)
expect(federation_entity.author_signature).to be_nil
- expect(federation_entity.xml_order).to be_nil
- expect(federation_entity.additional_xml_elements).to be_empty
+ expect(federation_entity.additional_data).to be_empty
end
it "builds a like with signature" do
@@ -99,12 +109,12 @@ describe Diaspora::Federation::Entities do
expect(federation_entity.parent_guid).to eq(diaspora_entity.target.guid)
expect(federation_entity.positive).to eq(diaspora_entity.positive)
expect(federation_entity.author_signature).to eq(diaspora_entity.signature.author_signature)
- expect(federation_entity.xml_order).to eq(diaspora_entity.signature.signature_order.order.split)
- expect(federation_entity.additional_xml_elements).to eq(diaspora_entity.signature.additional_data)
+ expect(federation_entity.signature_order.map(&:to_s)).to eq(diaspora_entity.signature.signature_order.order.split)
+ expect(federation_entity.additional_data).to eq(diaspora_entity.signature.additional_data)
end
it "builds a message" do
- diaspora_entity = FactoryGirl.create(:message, author_signature: "abc")
+ diaspora_entity = FactoryGirl.create(:message)
federation_entity = described_class.build(diaspora_entity)
expect(federation_entity).to be_instance_of(DiasporaFederation::Entities::Message)
@@ -113,7 +123,6 @@ describe Diaspora::Federation::Entities do
expect(federation_entity.conversation_guid).to eq(diaspora_entity.conversation.guid)
expect(federation_entity.text).to eq(diaspora_entity.text)
expect(federation_entity.created_at).to eq(diaspora_entity.created_at)
- expect(federation_entity.author_signature).to eq(diaspora_entity.author_signature)
end
it "builds a participation" do
@@ -153,8 +162,7 @@ describe Diaspora::Federation::Entities do
expect(federation_entity.parent_guid).to eq(diaspora_entity.poll_answer.poll.guid)
expect(federation_entity.poll_answer_guid).to eq(diaspora_entity.poll_answer.guid)
expect(federation_entity.author_signature).to be_nil
- expect(federation_entity.xml_order).to be_nil
- expect(federation_entity.additional_xml_elements).to be_empty
+ expect(federation_entity.additional_data).to be_empty
end
it "builds a poll participation with signature" do
@@ -168,8 +176,8 @@ describe Diaspora::Federation::Entities do
expect(federation_entity.parent_guid).to eq(diaspora_entity.poll_answer.poll.guid)
expect(federation_entity.poll_answer_guid).to eq(diaspora_entity.poll_answer.guid)
expect(federation_entity.author_signature).to eq(signature.author_signature)
- expect(federation_entity.xml_order).to eq(signature.signature_order.order.split)
- expect(federation_entity.additional_xml_elements).to eq(signature.additional_data)
+ expect(federation_entity.signature_order.map(&:to_s)).to eq(signature.signature_order.order.split)
+ expect(federation_entity.additional_data).to eq(signature.additional_data)
end
it "builds a profile" do
@@ -190,6 +198,7 @@ describe Diaspora::Federation::Entities do
expect(federation_entity.searchable).to eq(diaspora_entity.searchable)
expect(federation_entity.nsfw).to eq(diaspora_entity.nsfw)
expect(federation_entity.tag_string.split(" ")).to match_array(diaspora_entity.tag_string.split(" "))
+ expect(federation_entity.public).to eq(diaspora_entity.public_details)
end
it "builds a reshare" do
@@ -206,6 +215,31 @@ describe Diaspora::Federation::Entities do
expect(federation_entity.provider_display_name).to eq(diaspora_entity.provider_display_name)
end
+ context "Retraction" do
+ it "builds a Retraction entity for a Photo retraction" do
+ target = FactoryGirl.create(:photo, author: alice.person)
+ retraction = Retraction.for(target)
+ federation_entity = described_class.build(retraction)
+
+ expect(federation_entity).to be_instance_of(DiasporaFederation::Entities::Retraction)
+ expect(federation_entity.author).to eq(target.author.diaspora_handle)
+ expect(federation_entity.target_guid).to eq(target.guid)
+ expect(federation_entity.target_type).to eq("Photo")
+ end
+
+ it "builds a Contact for a Contact retraction" do
+ target = FactoryGirl.create(:contact, receiving: false)
+ retraction = ContactRetraction.for(target)
+ federation_entity = described_class.build(retraction)
+
+ expect(federation_entity).to be_instance_of(DiasporaFederation::Entities::Contact)
+ expect(federation_entity.author).to eq(target.user.diaspora_handle)
+ expect(federation_entity.recipient).to eq(target.person.diaspora_handle)
+ expect(federation_entity.sharing).to be_falsey
+ expect(federation_entity.following).to be_falsey
+ end
+ end
+
context "StatusMessage" do
it "builds a status message" do
diaspora_entity = FactoryGirl.create(:status_message)
@@ -274,89 +308,4 @@ describe Diaspora::Federation::Entities do
end
end
end
-
- describe ".build_retraction" do
- context "Retraction" do
- it "builds a Retraction for a Photo" do
- target = FactoryGirl.create(:photo, author: alice.person)
- retraction = Retraction.for(target, alice)
- federation_retraction = described_class.build_retraction(retraction)
-
- expect(federation_retraction).to be_instance_of(DiasporaFederation::Entities::Retraction)
- expect(federation_retraction.author).to eq(target.author.diaspora_handle)
- expect(federation_retraction.target_guid).to eq(target.guid)
- expect(federation_retraction.target_type).to eq("Photo")
- end
-
- it "builds a Retraction for a Contact" do
- target = FactoryGirl.create(:contact)
- retraction = Retraction.for(target, target.user)
- federation_retraction = described_class.build_retraction(retraction)
-
- expect(federation_retraction).to be_instance_of(DiasporaFederation::Entities::Retraction)
- expect(federation_retraction.author).to eq(target.user.diaspora_handle)
- expect(federation_retraction.target_guid).to eq(target.user.guid)
- expect(federation_retraction.target_type).to eq("Person")
- end
- end
-
- context "SignedRetraction" do
- it "builds a SignedRetraction for a StatusMessage" do
- target = FactoryGirl.create(:status_message, author: alice.person)
- retraction = Retraction.for(target, alice)
- federation_retraction = described_class.build_retraction(retraction)
-
- expect(federation_retraction).to be_instance_of(DiasporaFederation::Entities::SignedRetraction)
- expect(federation_retraction.author).to eq(target.author.diaspora_handle)
- expect(federation_retraction.target_guid).to eq(target.guid)
- expect(federation_retraction.target_type).to eq("Post")
- end
-
- it "builds a SignedRetraction for a Reshare" do
- target = FactoryGirl.create(:reshare, author: alice.person)
- retraction = Retraction.for(target, alice)
- federation_retraction = described_class.build_retraction(retraction)
-
- expect(federation_retraction).to be_instance_of(DiasporaFederation::Entities::SignedRetraction)
- expect(federation_retraction.author).to eq(target.author.diaspora_handle)
- expect(federation_retraction.target_guid).to eq(target.guid)
- expect(federation_retraction.target_type).to eq("Post")
- end
- end
-
- context "RelayableRetraction" do
- it "builds a RelayableRetraction for a Comment" do
- target = FactoryGirl.create(:comment, author: alice.person)
- retraction = Retraction.for(target, alice)
- federation_retraction = described_class.build_retraction(retraction)
-
- expect(federation_retraction).to be_instance_of(DiasporaFederation::Entities::RelayableRetraction)
- expect(federation_retraction.author).to eq(alice.diaspora_handle)
- expect(federation_retraction.target_guid).to eq(target.guid)
- expect(federation_retraction.target_type).to eq("Comment")
- end
-
- it "builds a RelayableRetraction for a Like" do
- target = FactoryGirl.create(:like, author: alice.person)
- retraction = Retraction.for(target, alice)
- federation_retraction = described_class.build_retraction(retraction)
-
- expect(federation_retraction).to be_instance_of(DiasporaFederation::Entities::RelayableRetraction)
- expect(federation_retraction.author).to eq(alice.diaspora_handle)
- expect(federation_retraction.target_guid).to eq(target.guid)
- expect(federation_retraction.target_type).to eq("Like")
- end
-
- it "builds a RelayableRetraction for a PollParticipation" do
- target = FactoryGirl.create(:poll_participation, author: alice.person)
- retraction = Retraction.for(target, alice)
- federation_retraction = described_class.build_retraction(retraction)
-
- expect(federation_retraction).to be_instance_of(DiasporaFederation::Entities::RelayableRetraction)
- expect(federation_retraction.author).to eq(alice.diaspora_handle)
- expect(federation_retraction.target_guid).to eq(target.guid)
- expect(federation_retraction.target_type).to eq("PollParticipation")
- end
- end
- end
end
diff --git a/spec/lib/diaspora/federation/receive_spec.rb b/spec/lib/diaspora/federation/receive_spec.rb
index 7e55bb7b8..a28dacf7f 100644
--- a/spec/lib/diaspora/federation/receive_spec.rb
+++ b/spec/lib/diaspora/federation/receive_spec.rb
@@ -3,29 +3,39 @@ describe Diaspora::Federation::Receive do
let(:post) { FactoryGirl.create(:status_message, text: "hello", public: true, author: alice.person) }
describe ".account_deletion" do
- let(:account_deletion_entity) { FactoryGirl.build(:account_deletion_entity, author: sender.diaspora_handle) }
+ let(:account_deletion_entity) { Fabricate(:account_deletion_entity, author: sender.diaspora_handle) }
it "saves the account deletion" do
Diaspora::Federation::Receive.account_deletion(account_deletion_entity)
- account_deletion = AccountDeletion.find_by!(diaspora_handle: sender.diaspora_handle)
+ expect(AccountDeletion.exists?(person: sender)).to be_truthy
+ end
+ end
- expect(account_deletion.person).to eq(sender)
+ describe ".account_migration" do
+ let(:new_person) { FactoryGirl.create(:person) }
+ let(:profile_entity) { Fabricate(:profile_entity, author: new_person.diaspora_handle) }
+ let(:account_migration_entity) {
+ Fabricate(:account_migration_entity, author: sender.diaspora_handle, profile: profile_entity)
+ }
+
+ it "saves the account deletion" do
+ Diaspora::Federation::Receive.account_migration(account_migration_entity)
+
+ expect(AccountMigration.exists?(old_person: sender, new_person: new_person)).to be_truthy
end
end
describe ".comment" do
- let(:comment_data) {
- FactoryGirl.attributes_for(
- :comment_entity,
- author: sender.diaspora_handle,
- parent_guid: post.guid,
- author_signature: "aa"
- )
- }
let(:comment_entity) {
- DiasporaFederation::Entities::Comment.new(
- comment_data, [:author, :guid, :parent_guid, :text, "new_property"], "new_property" => "data"
+ build_relayable_federation_entity(
+ :comment,
+ {
+ author: sender.diaspora_handle,
+ parent_guid: post.guid,
+ author_signature: "aa"
+ },
+ "new_property" => "data"
)
}
@@ -57,7 +67,7 @@ describe Diaspora::Federation::Receive do
expect(comment.signature).not_to be_nil
expect(comment.signature.author_signature).to eq("aa")
expect(comment.signature.additional_data).to eq("new_property" => "data")
- expect(comment.signature.order).to eq(%w(author guid parent_guid text new_property))
+ expect(comment.signature.order).to eq(comment_entity.signature_order.map(&:to_s))
end
let(:entity) { comment_entity }
@@ -68,7 +78,7 @@ describe Diaspora::Federation::Receive do
describe ".contact" do
let(:contact_entity) {
- FactoryGirl.build(:contact_entity, author: sender.diaspora_handle, recipient: alice.diaspora_handle)
+ Fabricate(:contact_entity, author: sender.diaspora_handle, recipient: alice.diaspora_handle)
}
it "creates the contact if it doesn't exist" do
@@ -101,11 +111,11 @@ describe Diaspora::Federation::Receive do
context "sharing=false" do
let(:unshare_contact_entity) {
- FactoryGirl.build(
+ Fabricate(
:contact_entity,
author: sender.diaspora_handle,
recipient: alice.diaspora_handle,
- sharing: "false"
+ sharing: false
)
}
@@ -130,9 +140,9 @@ describe Diaspora::Federation::Receive do
end
describe ".conversation" do
- let(:conv_guid) { FactoryGirl.generate(:guid) }
+ let(:conv_guid) { Fabricate.sequence(:guid) }
let(:message_entity) {
- FactoryGirl.build(
+ Fabricate(
:message_entity,
author: alice.diaspora_handle,
parent_guid: conv_guid,
@@ -140,7 +150,7 @@ describe Diaspora::Federation::Receive do
)
}
let(:conversation_entity) {
- FactoryGirl.build(
+ Fabricate(
:conversation_entity,
guid: conv_guid,
author: alice.diaspora_handle,
@@ -185,17 +195,15 @@ describe Diaspora::Federation::Receive do
end
describe ".like" do
- let(:like_data) {
- FactoryGirl.attributes_for(
- :like_entity,
- author: sender.diaspora_handle,
- parent_guid: post.guid,
- author_signature: "aa"
- )
- }
let(:like_entity) {
- DiasporaFederation::Entities::Like.new(
- like_data, [:author, :guid, :parent_guid, :parent_type, :positive, "new_property"], "new_property" => "data"
+ build_relayable_federation_entity(
+ :like,
+ {
+ author: sender.diaspora_handle,
+ parent_guid: post.guid,
+ author_signature: "aa"
+ },
+ "new_property" => "data"
)
}
@@ -226,7 +234,7 @@ describe Diaspora::Federation::Receive do
expect(like.signature).not_to be_nil
expect(like.signature.author_signature).to eq("aa")
expect(like.signature.additional_data).to eq("new_property" => "data")
- expect(like.signature.order).to eq(%w(author guid parent_guid parent_type positive new_property))
+ expect(like.signature.order).to eq(like_entity.signature_order.map(&:to_s))
end
let(:entity) { like_entity }
@@ -243,7 +251,7 @@ describe Diaspora::Federation::Receive do
end
}
let(:message_entity) {
- FactoryGirl.build(
+ Fabricate(
:message_entity,
author: sender.diaspora_handle,
parent_guid: conversation.guid,
@@ -273,12 +281,11 @@ describe Diaspora::Federation::Receive do
let(:entity) { message_entity }
it_behaves_like "it ignores existing object received twice", Message
- it_behaves_like "it relays relayables", Message
end
describe ".participation" do
let(:participation_entity) {
- FactoryGirl.build(:participation_entity, author: sender.diaspora_handle, parent_guid: post.guid)
+ Fabricate(:participation_entity, author: sender.diaspora_handle, parent_guid: post.guid)
}
it "saves the participation" do
@@ -305,7 +312,7 @@ describe Diaspora::Federation::Receive do
end
describe ".photo" do
- let(:photo_entity) { FactoryGirl.build(:photo_entity, author: sender.diaspora_handle) }
+ let(:photo_entity) { Fabricate(:photo_entity, author: sender.diaspora_handle) }
it "saves the photo if it does not already exist" do
received = Diaspora::Federation::Receive.perform(photo_entity)
@@ -354,19 +361,15 @@ describe Diaspora::Federation::Receive do
describe ".poll_participation" do
let(:post_with_poll) { FactoryGirl.create(:status_message_with_poll, author: alice.person) }
- let(:poll_participation_data) {
- FactoryGirl.attributes_for(
- :poll_participation_entity,
- author: sender.diaspora_handle,
- parent_guid: post_with_poll.poll.guid,
- poll_answer_guid: post_with_poll.poll.poll_answers.first.guid,
- author_signature: "aa"
- )
- }
let(:poll_participation_entity) {
- DiasporaFederation::Entities::PollParticipation.new(
- poll_participation_data,
- [:author, :guid, :parent_guid, :poll_answer_guid, "new_property"],
+ build_relayable_federation_entity(
+ :poll_participation,
+ {
+ author: sender.diaspora_handle,
+ parent_guid: post_with_poll.poll.guid,
+ poll_answer_guid: post_with_poll.poll.poll_answers.first.guid,
+ author_signature: "aa"
+ },
"new_property" => "data"
)
}
@@ -398,7 +401,7 @@ describe Diaspora::Federation::Receive do
expect(poll_participation.signature).not_to be_nil
expect(poll_participation.signature.author_signature).to eq("aa")
expect(poll_participation.signature.additional_data).to eq("new_property" => "data")
- expect(poll_participation.signature.order).to eq(%w(author guid parent_guid poll_answer_guid new_property))
+ expect(poll_participation.signature.order).to eq(poll_participation_entity.signature_order.map(&:to_s))
end
let(:entity) { poll_participation_entity }
@@ -408,7 +411,7 @@ describe Diaspora::Federation::Receive do
end
describe ".profile" do
- let(:profile_entity) { FactoryGirl.build(:profile_entity, author: sender.diaspora_handle) }
+ let(:profile_entity) { Fabricate(:profile_entity, author: sender.diaspora_handle) }
it "updates the profile of the person" do
received = Diaspora::Federation::Receive.perform(profile_entity)
@@ -424,11 +427,12 @@ describe Diaspora::Federation::Receive do
expect(profile.searchable).to eq(profile_entity.searchable)
expect(profile.nsfw).to eq(profile_entity.nsfw)
expect(profile.tag_string.split(" ")).to match_array(profile_entity.tag_string.split(" "))
+ expect(profile.public_details).to eq(profile_entity.public)
end
end
describe ".reshare" do
- let(:reshare_entity) { FactoryGirl.build(:reshare_entity, author: sender.diaspora_handle, root_guid: post.guid) }
+ let(:reshare_entity) { Fabricate(:reshare_entity, author: sender.diaspora_handle, root_guid: post.guid) }
it "saves the reshare" do
received = Diaspora::Federation::Receive.perform(reshare_entity)
@@ -458,7 +462,7 @@ describe Diaspora::Federation::Receive do
it "destroys the post" do
remote_post = FactoryGirl.create(:status_message, author: sender, public: true)
- retraction = FactoryGirl.build(
+ retraction = Fabricate(
:retraction_entity,
author: sender.diaspora_handle,
target_guid: remote_post.guid,
@@ -473,12 +477,7 @@ describe Diaspora::Federation::Receive do
end
it "raises when the post does not exist" do
- retraction = FactoryGirl.build(
- :retraction_entity,
- author: sender.diaspora_handle,
- target_guid: FactoryGirl.generate(:guid),
- target_type: "Post"
- )
+ retraction = Fabricate(:retraction_entity, author: sender.diaspora_handle, target_type: "Post")
expect {
Diaspora::Federation::Receive.retraction(retraction, nil)
@@ -488,7 +487,7 @@ describe Diaspora::Federation::Receive do
it "disconnects on Person-Retraction" do
alice.contacts.find_or_initialize_by(person_id: sender.id, receiving: true, sharing: true).save!
- retraction = FactoryGirl.build(
+ retraction = Fabricate(
:retraction_entity,
author: sender.diaspora_handle,
target_guid: sender.guid,
@@ -508,16 +507,16 @@ describe Diaspora::Federation::Receive do
local_post = FactoryGirl.create(:status_message, author: alice.person, public: true)
remote_comment = FactoryGirl.create(:comment, author: sender, post: local_post)
- retraction = FactoryGirl.build(
+ retraction = Fabricate(
:retraction_entity,
author: sender.diaspora_handle,
target_guid: remote_comment.guid,
target_type: "Comment"
)
- comment_retraction = Retraction.for(remote_comment, alice)
+ comment_retraction = Retraction.for(remote_comment)
- expect(Retraction).to receive(:for).with(instance_of(Comment), alice).and_return(comment_retraction)
+ expect(Retraction).to receive(:for).with(instance_of(Comment)).and_return(comment_retraction)
expect(comment_retraction).to receive(:defer_dispatch).with(alice, false)
expect(comment_retraction).to receive(:perform).and_call_original
expect_any_instance_of(Comment).to receive(:destroy!).and_call_original
@@ -531,7 +530,7 @@ describe Diaspora::Federation::Receive do
remote_post = FactoryGirl.create(:status_message, author: sender, public: true)
remote_comment = FactoryGirl.create(:comment, author: sender, post: remote_post)
- retraction = FactoryGirl.build(
+ retraction = Fabricate(
:retraction_entity,
author: sender.diaspora_handle,
target_guid: remote_comment.guid,
@@ -549,7 +548,7 @@ describe Diaspora::Federation::Receive do
describe ".status_message" do
context "basic status message" do
- let(:status_message_entity) { FactoryGirl.build(:status_message_entity, author: sender.diaspora_handle) }
+ let(:status_message_entity) { Fabricate(:status_message_entity, author: sender.diaspora_handle) }
it "saves the status message" do
received = Diaspora::Federation::Receive.perform(status_message_entity)
@@ -585,7 +584,7 @@ describe Diaspora::Federation::Receive do
end
it "finds the correct author if the author is not lowercase" do
- status_message_entity = FactoryGirl.build(:status_message_entity, author: sender.diaspora_handle.upcase)
+ status_message_entity = Fabricate(:status_message_entity, author: sender.diaspora_handle.upcase)
received = Diaspora::Federation::Receive.perform(status_message_entity)
@@ -597,9 +596,9 @@ describe Diaspora::Federation::Receive do
end
context "with poll" do
- let(:poll_entity) { FactoryGirl.build(:poll_entity) }
+ let(:poll_entity) { Fabricate(:poll_entity) }
let(:status_message_entity) {
- FactoryGirl.build(:status_message_entity, author: sender.diaspora_handle, poll: poll_entity)
+ Fabricate(:status_message_entity, author: sender.diaspora_handle, poll: poll_entity)
}
it "saves the status message" do
@@ -618,9 +617,9 @@ describe Diaspora::Federation::Receive do
end
context "with location" do
- let(:location_entity) { FactoryGirl.build(:location_entity) }
+ let(:location_entity) { Fabricate(:location_entity) }
let(:status_message_entity) {
- FactoryGirl.build(:status_message_entity, author: sender.diaspora_handle, location: location_entity)
+ Fabricate(:status_message_entity, author: sender.diaspora_handle, location: location_entity)
}
it "saves the status message" do
@@ -638,15 +637,15 @@ describe Diaspora::Federation::Receive do
end
context "with photos" do
- let(:status_message_guid) { FactoryGirl.generate(:guid) }
+ let(:status_message_guid) { Fabricate.sequence(:guid) }
let(:photo1) {
- FactoryGirl.build(:photo_entity, author: sender.diaspora_handle, status_message_guid: status_message_guid)
+ Fabricate(:photo_entity, author: sender.diaspora_handle, status_message_guid: status_message_guid)
}
let(:photo2) {
- FactoryGirl.build(:photo_entity, author: sender.diaspora_handle, status_message_guid: status_message_guid)
+ Fabricate(:photo_entity, author: sender.diaspora_handle, status_message_guid: status_message_guid)
}
let(:status_message_entity) {
- FactoryGirl.build(
+ Fabricate(
:status_message_entity,
author: sender.diaspora_handle,
guid: status_message_guid,
diff --git a/spec/lib/diaspora/mentionable_spec.rb b/spec/lib/diaspora/mentionable_spec.rb
index 365d2dd04..477e6837b 100644
--- a/spec/lib/diaspora/mentionable_spec.rb
+++ b/spec/lib/diaspora/mentionable_spec.rb
@@ -1,46 +1,76 @@
describe Diaspora::Mentionable do
include PeopleHelper
- before do
- @people = [alice, bob, eve].map(&:person)
- @names = %w(Alice\ A Bob\ B "Eve>\ E)
- @test_txt = <<-STR
+ let(:people) { [alice, bob, eve].map(&:person) }
+ let(:names) { %w(Alice\ A Bob\ B "Eve>\ E) }
+
+ let(:test_text_with_names) { <<-STR }
This post contains a lot of mentions
-one @{#{@names[0]}; #{@people[0].diaspora_handle}},
-two @{#{@names[1]}; #{@people[1].diaspora_handle}} and finally
-three @{#{@names[2]}; #{@people[2].diaspora_handle}}.
+one @{#{names[0]}; #{people[0].diaspora_handle}},
+two @{#{names[1]}; #{people[1].diaspora_handle}} and finally
+three @{#{names[2]}; #{people[2].diaspora_handle}}.
STR
- @test_txt_plain = <<-STR
+
+ let(:test_text_without_names) { <<-STR }
This post contains a lot of mentions
-one Alice A,
-two Bob B and finally
-three &quot;Eve&gt; E.
+one @{#{people[0].diaspora_handle}},
+two @{#{people[1].diaspora_handle}} and finally
+three @{#{people[2].diaspora_handle}}.
STR
+
+ describe ".mention_attrs" do
+ it "returns name and diaspora ID" do
+ name, diaspora_id = Diaspora::Mentionable.mention_attrs("@{#{names[0]}; #{people[0].diaspora_handle}}")
+ expect(name).to eq(names[0])
+ expect(diaspora_id).to eq(people[0].diaspora_handle)
+ end
+
+ it "returns only diaspora-ID when no name is included" do
+ name, diaspora_id = Diaspora::Mentionable.mention_attrs("@{#{people[0].diaspora_handle}}")
+ expect(diaspora_id).to eq(people[0].diaspora_handle)
+ expect(name).to be_nil
+ end
+
+ it "trims the name if available" do
+ name, diaspora_id = Diaspora::Mentionable.mention_attrs("@{#{names[0]} ; #{people[0].diaspora_handle}}")
+ expect(name).to eq(names[0])
+ expect(diaspora_id).to eq(people[0].diaspora_handle)
+ end
end
- describe "#format" do
+ describe ".format" do
context "html output" do
it "adds the links to the formatted message" do
- fmt_msg = Diaspora::Mentionable.format(@test_txt, @people)
+ fmt_msg = Diaspora::Mentionable.format(test_text_with_names, people)
- [@people, @names].transpose.each do |person, name|
- expect(fmt_msg).to include person_link(person, class: "mention hovercardable", display_name: name)
+ [people, names].transpose.each do |person, name|
+ link = person_link(person, class: "mention hovercardable", display_name: name)
+ expect(fmt_msg).to include "@#{link}"
+ end
+ end
+
+ it "adds the links to the formatted message and uses the names from the people" do
+ fmt_msg = Diaspora::Mentionable.format(test_text_without_names, people)
+
+ people.each do |person|
+ link = person_link(person, class: "mention hovercardable", display_name: person.name)
+ expect(fmt_msg).to include "@#{link}"
end
end
it "should work correct when message is escaped html" do
- fmt_msg = Diaspora::Mentionable.format(CGI.escapeHTML(@test_txt), @people)
+ fmt_msg = Diaspora::Mentionable.format(CGI.escapeHTML(test_text_with_names), people)
- [@people, @names].transpose.each do |person, name|
+ [people, names].transpose.each do |person, name|
expect(fmt_msg).to include person_link(person, class: "mention hovercardable", display_name: name)
end
end
it "escapes the link title (name)" do
name = "</a><script>alert('h')</script>"
- test_txt = "two @{#{name}; #{@people[0].diaspora_handle}} and finally"
+ test_txt = "two @{#{name}; #{people[0].diaspora_handle}} and finally"
- fmt_msg = Diaspora::Mentionable.format(test_txt, @people)
+ fmt_msg = Diaspora::Mentionable.format(test_txt, people)
expect(fmt_msg).not_to include(name)
expect(fmt_msg).to include("&gt;", "&lt;", "&#39;") # ">", "<", "'"
@@ -49,25 +79,56 @@ STR
context "plain text output" do
it "removes mention markup and displays unformatted name" do
- fmt_msg = Diaspora::Mentionable.format(@test_txt, @people, plain_text: true)
+ fmt_msg = Diaspora::Mentionable.format(test_text_with_names, people, plain_text: true)
- @names.each do |name|
- expect(fmt_msg).to include CGI.escapeHTML(name)
+ names.each do |name|
+ expect(fmt_msg).to include "@#{CGI.escapeHTML(name)}"
end
expect(fmt_msg).not_to include "<a", "</a>", "hovercardable"
end
end
it "leaves the names of people that cannot be found" do
- fmt_msg = Diaspora::Mentionable.format(@test_txt, [])
- expect(fmt_msg).to eql @test_txt_plain
+ test_txt_plain = <<-STR
+This post contains a lot of mentions
+one @Alice A,
+two @Bob B and finally
+three @&quot;Eve&gt; E.
+STR
+
+ fmt_msg = Diaspora::Mentionable.format(test_text_with_names, [])
+ expect(fmt_msg).to eql test_txt_plain
+ end
+
+ it "uses the diaspora ID when the person cannot be found" do
+ test_txt_plain = <<-STR
+This post contains a lot of mentions
+one @#{people[0].diaspora_handle},
+two @#{people[1].diaspora_handle} and finally
+three @#{people[2].diaspora_handle}.
+STR
+
+ fmt_msg = Diaspora::Mentionable.format(test_text_without_names, [])
+ expect(fmt_msg).to eql test_txt_plain
end
end
- describe "#people_from_string" do
+ describe ".people_from_string" do
it "extracts the mentioned people from the text" do
- ppl = Diaspora::Mentionable.people_from_string(@test_txt)
- expect(ppl).to match_array(@people)
+ ppl = Diaspora::Mentionable.people_from_string(test_text_with_names)
+ expect(ppl).to match_array(people)
+ end
+
+ it "extracts the mentioned people from the text without name" do
+ text = "test @{#{people[0].diaspora_handle}} test"
+ ppl = Diaspora::Mentionable.people_from_string(text)
+ expect(ppl).to match_array([people[0]])
+ end
+
+ it "extracts the mentioned people from the text mixed mentions (with and without name)" do
+ text = "@{#{people[0].diaspora_handle}} and @{#{names[1]}; #{people[1].diaspora_handle}}"
+ ppl = Diaspora::Mentionable.people_from_string(text)
+ expect(ppl).to match_array([people[0], people[1]])
end
describe "returns an empty array if nobody was found" do
@@ -102,48 +163,81 @@ STR
end
end
- describe "#filter_for_aspects" do
- before do
- @user_a = FactoryGirl.create(:user_with_aspect, username: "user_a")
- @user_b = FactoryGirl.create(:user, username: "user_b")
- @user_c = FactoryGirl.create(:user, username: "user_c")
-
- @user_a.aspects.create!(name: "second")
-
- @mention_b = "@{user B; #{@user_b.diaspora_handle}}"
- @mention_c = "@{user C; #{@user_c.diaspora_handle}}"
+ describe ".filter_people" do
+ let(:user_a) { FactoryGirl.create(:user_with_aspect, username: "user_a") }
+ let(:user_b) { FactoryGirl.create(:user, username: "user_b") }
+ let(:user_c) { FactoryGirl.create(:user, username: "user_c") }
- @user_a.share_with(@user_b.person, @user_a.aspects.where(name: "generic"))
- @user_a.share_with(@user_c.person, @user_a.aspects.where(name: "second"))
+ before do
+ user_a.aspects.create!(name: "second")
- @test_txt_b = "mentioning #{@mention_b}"
- @test_txt_c = "mentioning #{@mention_c}"
- @test_txt_bc = "mentioning #{@mention_b}} and #{@mention_c}"
+ user_a.share_with(user_b.person, user_a.aspects.where(name: "generic"))
+ user_a.share_with(user_c.person, user_a.aspects.where(name: "second"))
end
it "filters mention, if contact is not in a given aspect" do
- aspect_id = @user_a.aspects.where(name: "generic").first.id
- txt = Diaspora::Mentionable.filter_for_aspects(@test_txt_c, @user_a, aspect_id)
+ mention = "@{user C; #{user_c.diaspora_handle}}"
+ txt = Diaspora::Mentionable.filter_people(
+ "mentioning #{mention}",
+ user_a.aspects.where(name: "generic").first.contacts.map(&:person_id)
+ )
- expect(txt).to include("user C")
- expect(txt).to include(local_or_remote_person_path(@user_c.person))
+ expect(txt).to include("@[user C](#{local_or_remote_person_path(user_c.person)}")
expect(txt).not_to include("href")
- expect(txt).not_to include(@mention_c)
+ expect(txt).not_to include(mention)
end
it "leaves mention, if contact is in a given aspect" do
- aspect_id = @user_a.aspects.where(name: "generic").first.id
- txt = Diaspora::Mentionable.filter_for_aspects(@test_txt_b, @user_a, aspect_id)
+ mention = "@{user B; #{user_b.diaspora_handle}}"
+ txt = Diaspora::Mentionable.filter_people(
+ "mentioning #{mention}",
+ user_a.aspects.where(name: "generic").first.contacts.map(&:person_id)
+ )
expect(txt).to include("user B")
- expect(txt).to include(@mention_b)
+ expect(txt).to include(mention)
+ end
+
+ it "works if the person cannot be found" do
+ expect(Person).to receive(:find_or_fetch_by_identifier).with("non_existing_user@example.org").and_return(nil)
+
+ mention = "@{non_existing_user@example.org}"
+ txt = Diaspora::Mentionable.filter_people("mentioning #{mention}", [])
+
+ expect(txt).to eq "mentioning @non_existing_user@example.org"
+ end
+ end
+
+ describe ".backport_mention_syntax" do
+ it "replaces the new syntax with the old syntax" do
+ text = "mention @{#{people[0].diaspora_handle}} text"
+ expected_text = "mention @{#{people[0].name}; #{people[0].diaspora_handle}} text"
+ expect(Diaspora::Mentionable.backport_mention_syntax(text)).to eq(expected_text)
end
- it "recognizes 'all' as keyword for aspects" do
- txt = Diaspora::Mentionable.filter_for_aspects(@test_txt_bc, @user_a, "all")
+ it "removes curly braces from name of the mentioned person when adding it" do
+ profile = FactoryGirl.build(:profile, first_name: "{Alice}", last_name: "(Smith) [123]")
+ person = FactoryGirl.create(:person, profile: profile)
+ text = "mention @{#{person.diaspora_handle}} text"
+ expected_text = "mention @{Alice (Smith) [123]; #{person.diaspora_handle}} text"
+ expect(Diaspora::Mentionable.backport_mention_syntax(text)).to eq(expected_text)
+ end
+
+ it "does not change the text, when the mention includes a name" do
+ text = "mention @{#{names[0]}; #{people[0].diaspora_handle}} text"
+ expect(Diaspora::Mentionable.backport_mention_syntax(text)).to eq(text)
+ end
+
+ it "does not change the text, when the person is not found" do
+ text = "mention @{non_existing_user@example.org} text"
+ expect(Person).to receive(:find_or_fetch_by_identifier).with("non_existing_user@example.org").and_return(nil)
+ expect(Diaspora::Mentionable.backport_mention_syntax(text)).to eq(text)
+ end
- expect(txt).to include(@mention_b)
- expect(txt).to include(@mention_c)
+ it "does not change the text, when the diaspora ID is invalid" do
+ text = "mention @{invalid_diaspora_id} text"
+ expect(Person).not_to receive(:find_or_fetch_by_identifier)
+ expect(Diaspora::Mentionable.backport_mention_syntax(text)).to eq(text)
end
end
end
diff --git a/spec/lib/diaspora/message_renderer_spec.rb b/spec/lib/diaspora/message_renderer_spec.rb
index fa0aa3b3b..f72adc240 100644
--- a/spec/lib/diaspora/message_renderer_spec.rb
+++ b/spec/lib/diaspora/message_renderer_spec.rb
@@ -191,6 +191,23 @@ describe Diaspora::MessageRenderer do
text = "#hashtag message"
expect(message(text).plain_text_without_markdown).to eq text
end
+
+ context "with mention" do
+ it "contains the name of the mentioned person" do
+ msg = message("@{#{alice.diaspora_handle}} is cool", mentioned_people: alice.person)
+ expect(msg.plain_text_without_markdown).to eq "@#{alice.name} is cool"
+ end
+
+ it "uses the name from mention when the mention contains a name" do
+ msg = message("@{Alice; #{alice.diaspora_handle}} is cool", mentioned_people: alice.person)
+ expect(msg.plain_text_without_markdown).to eq "@Alice is cool"
+ end
+
+ it "uses the diaspora ID when the person cannot be found" do
+ msg = message("@{#{alice.diaspora_handle}} is cool", mentioned_people: [])
+ expect(msg.plain_text_without_markdown).to eq "@#{alice.diaspora_handle} is cool"
+ end
+ end
end
describe "#urls" do
diff --git a/spec/lib/evil_query_spec.rb b/spec/lib/evil_query_spec.rb
index 082cccead..dbaaf3b02 100644
--- a/spec/lib/evil_query_spec.rb
+++ b/spec/lib/evil_query_spec.rb
@@ -28,6 +28,18 @@ describe EvilQuery::MultiStream do
expect(evil_query.make_relation!.map(&:id)).not_to include(public_post.id)
expect(evil_query.make_relation!.map(&:id)).not_to include(private_post.id)
end
+
+ it "doesn't include posts with tags from ignored users" do
+ tag = ActsAsTaggableOn::Tag.find_or_create_by(name: "test")
+ alice.tag_followings.create(tag_id: tag.id)
+ alice.blocks.create(person_id: eve.person_id)
+
+ bob_post = bob.post(:status_message, text: "public #test post 1", to: "all", public: true)
+ eve_post = eve.post(:status_message, text: "public #test post 2", to: "all", public: true)
+
+ expect(evil_query.make_relation!.map(&:id)).to include(bob_post.id)
+ expect(evil_query.make_relation!.map(&:id)).not_to include(eve_post.id)
+ end
end
end
diff --git a/spec/lib/publisher_spec.rb b/spec/lib/publisher_spec.rb
index 8eeb76d24..f8479d884 100644
--- a/spec/lib/publisher_spec.rb
+++ b/spec/lib/publisher_spec.rb
@@ -16,7 +16,7 @@ describe Publisher do
describe '#text' do
it 'is a formatted version of the prefill' do
p = Publisher.new(alice, prefill: "@{alice; #{alice.diaspora_handle}}")
- expect(p.text).to eq("alice")
+ expect(p.text).to eq("@alice")
end
end
diff --git a/spec/lib/stream/person_spec.rb b/spec/lib/stream/person_spec.rb
index b5cd7422b..2c44377bc 100644
--- a/spec/lib/stream/person_spec.rb
+++ b/spec/lib/stream/person_spec.rb
@@ -32,7 +32,7 @@ describe Stream::Person do
end
posts = posts.reverse.slice(0..14)
- fetched_posts = fetched_posts.slice(0..14)
+ fetched_posts = fetched_posts.first(15)
expect(fetched_posts).to eq(posts)
end
diff --git a/spec/mailers/notifier_spec.rb b/spec/mailers/notifier_spec.rb
index a23b796b8..12ee1dd78 100644
--- a/spec/mailers/notifier_spec.rb
+++ b/spec/mailers/notifier_spec.rb
@@ -1,5 +1,7 @@
describe Notifier, type: :mailer do
let(:person) { FactoryGirl.create(:person) }
+ let(:pod_name) { AppConfig.settings.pod_name }
+
before do
Notifier.deliveries = []
@@ -64,7 +66,7 @@ describe Notifier, type: :mailer do
end
describe ".started_sharing" do
- let!(:request_mail) { Notifier.started_sharing(bob.id, person.id) }
+ let!(:request_mail) { Notifier.send_notification("started_sharing", bob.id, person.id) }
it "goes to the right person" do
expect(request_mail.to).to eq([bob.email])
@@ -79,9 +81,9 @@ describe Notifier, type: :mailer do
before do
@user = alice
@post = FactoryGirl.create(:status_message, public: true)
- @mention = Mention.create(person: @user.person, post: @post)
+ @mention = Mention.create(person: @user.person, mentions_container: @post)
- @mail = Notifier.mentioned(@user.id, @post.author.id, @mention.id)
+ @mail = Notifier.send_notification("mentioned", @user.id, @post.author.id, @mention.id)
end
it "TO: goes to the right person" do
@@ -106,13 +108,46 @@ describe Notifier, type: :mailer do
end
end
+ describe ".mentioned_in_comment" do
+ let(:user) { alice }
+ let(:comment) { FactoryGirl.create(:comment) }
+ let(:mention) { Mention.create(person: user.person, mentions_container: comment) }
+ let(:mail) { Notifier.send_notification("mentioned_in_comment", user.id, comment.author.id, mention.id) }
+
+ it "TO: goes to the right person" do
+ expect(mail.to).to eq([user.email])
+ end
+
+ it "SUBJECT: has the name of person mentioning in the subject" do
+ expect(mail.subject).to include(comment.author.name)
+ end
+
+ it "IN-REPLY-TO and REFERENCES: references the commented post" do
+ expect(mail.in_reply_to).to eq("#{comment.parent.guid}@#{AppConfig.pod_uri.host}")
+ expect(mail.references).to eq("#{comment.parent.guid}@#{AppConfig.pod_uri.host}")
+ end
+
+ it "has the comment link in the body" do
+ expect(mail.body.encoded).to include(post_url(comment.parent, anchor: comment.guid))
+ end
+
+ it "renders proper wording when limited" do
+ expect(mail.body.encoded).to include(I18n.translate("notifier.mentioned_in_comment.limited_post"))
+ end
+
+ it "renders comment text when public" do
+ comment.parent.update(public: true)
+ expect(mail.body.encoded).to include(comment.message.plain_text_without_markdown)
+ end
+ end
+
describe ".mentioned limited" do
before do
@user = alice
@post = FactoryGirl.create(:status_message, public: false)
- @mention = Mention.create(person: @user.person, post: @post)
+ @mention = Mention.create(person: @user.person, mentions_container: @post)
- @mail = Notifier.mentioned(@user.id, @post.author.id, @mention.id)
+ @mail = Notifier.send_notification("mentioned", @user.id, @post.author.id, @mention.id)
end
it "TO: goes to the right person" do
@@ -136,7 +171,7 @@ describe Notifier, type: :mailer do
before do
@post = FactoryGirl.create(:status_message, author: alice.person, public: true)
@like = @post.likes.create!(author: bob.person)
- @mail = Notifier.liked(alice.id, @like.author.id, @like.id)
+ @mail = Notifier.send_notification("liked", alice.id, @like.author.id, @like.id)
end
it "TO: goes to the right person" do
@@ -158,7 +193,7 @@ describe Notifier, type: :mailer do
it "can handle a reshare" do
reshare = FactoryGirl.create(:reshare)
like = reshare.likes.create!(author: bob.person)
- Notifier.liked(alice.id, like.author.id, like.id)
+ Notifier.send_notification("liked", alice.id, like.author.id, like.id)
end
end
@@ -166,7 +201,7 @@ describe Notifier, type: :mailer do
before do
@post = FactoryGirl.create(:status_message, author: alice.person, public: true)
@reshare = FactoryGirl.create(:reshare, root: @post, author: bob.person)
- @mail = Notifier.reshared(alice.id, @reshare.author.id, @reshare.id)
+ @mail = Notifier.send_notification("reshared", alice.id, @reshare.author.id, @reshare.id)
end
it "TO: goes to the right person" do
@@ -205,7 +240,7 @@ describe Notifier, type: :mailer do
@cnv = Conversation.create(@create_hash)
- @mail = Notifier.private_message(bob.id, @cnv.author.id, @cnv.messages.first.id)
+ @mail = Notifier.send_notification("private_message", bob.id, @cnv.author.id, @cnv.messages.first.id)
end
it "TO: goes to the right person" do
@@ -213,7 +248,7 @@ describe Notifier, type: :mailer do
end
it "FROM: contains the sender's name" do
- expect(@mail["From"].to_s).to eq("\"#{@cnv.author.name} (diaspora*)\" <#{AppConfig.mail.sender_address}>")
+ expect(@mail["From"].to_s).to eq("\"#{pod_name} (#{@cnv.author.name})\" <#{AppConfig.mail.sender_address}>")
end
it "should use a generic subject" do
@@ -248,14 +283,16 @@ describe Notifier, type: :mailer do
let(:comment) { eve.comment!(commented_post, "Totally is") }
describe ".comment_on_post" do
- let(:comment_mail) { Notifier.comment_on_post(bob.id, person.id, comment.id).deliver_now }
+ let(:comment_mail) {
+ Notifier.send_notification("comment_on_post", bob.id, eve.person.id, comment.id).deliver_now
+ }
it "TO: goes to the right person" do
expect(comment_mail.to).to eq([bob.email])
end
it "FROM: contains the sender's name" do
- expect(comment_mail["From"].to_s).to eq("\"#{eve.name} (diaspora*)\" <#{AppConfig.mail.sender_address}>")
+ expect(comment_mail["From"].to_s).to eq("\"#{pod_name} (#{eve.name})\" <#{AppConfig.mail.sender_address}>")
end
it "SUBJECT: has a snippet of the post contents, without markdown and without newlines" do
@@ -289,14 +326,14 @@ describe Notifier, type: :mailer do
end
describe ".also_commented" do
- let(:comment_mail) { Notifier.also_commented(bob.id, person.id, comment.id) }
+ let(:comment_mail) { Notifier.send_notification("also_commented", bob.id, eve.person.id, comment.id) }
it "TO: goes to the right person" do
expect(comment_mail.to).to eq([bob.email])
end
it "FROM: has the name of person commenting as the sender" do
- expect(comment_mail["From"].to_s).to eq("\"#{eve.name} (diaspora*)\" <#{AppConfig.mail.sender_address}>")
+ expect(comment_mail["From"].to_s).to eq("\"#{pod_name} (#{eve.name})\" <#{AppConfig.mail.sender_address}>")
end
it "SUBJECT: has a snippet of the post contents, without markdown and without newlines" do
@@ -344,14 +381,14 @@ describe Notifier, type: :mailer do
let(:comment) { bob.comment!(limited_post, "Totally is") }
describe ".also_commented" do
- let(:mail) { Notifier.also_commented(alice.id, bob.person.id, comment.id) }
+ let(:mail) { Notifier.send_notification("also_commented", alice.id, bob.person.id, comment.id) }
it "TO: goes to the right person" do
expect(mail.to).to eq([alice.email])
end
it "FROM: contains the sender's name" do
- expect(mail["From"].to_s).to eq("\"#{bob.name} (diaspora*)\" <#{AppConfig.mail.sender_address}>")
+ expect(mail["From"].to_s).to eq("\"#{pod_name} (#{bob.name})\" <#{AppConfig.mail.sender_address}>")
end
it "SUBJECT: does not show the limited post" do
@@ -369,14 +406,14 @@ describe Notifier, type: :mailer do
describe ".comment_on_post" do
let(:comment) { bob.comment!(limited_post, "Totally is") }
- let(:mail) { Notifier.comment_on_post(alice.id, bob.person.id, comment.id) }
+ let(:mail) { Notifier.send_notification("comment_on_post", alice.id, bob.person.id, comment.id) }
it "TO: goes to the right person" do
expect(mail.to).to eq([alice.email])
end
it "FROM: contains the sender's name" do
- expect(mail["From"].to_s).to eq("\"#{bob.name} (diaspora*)\" <#{AppConfig.mail.sender_address}>")
+ expect(mail["From"].to_s).to eq("\"#{pod_name} (#{bob.name})\" <#{AppConfig.mail.sender_address}>")
end
it "SUBJECT: does not show the limited post" do
@@ -400,14 +437,14 @@ describe Notifier, type: :mailer do
describe ".liked" do
let(:like) { bob.like!(limited_post) }
- let(:mail) { Notifier.liked(alice.id, bob.person.id, like.id) }
+ let(:mail) { Notifier.send_notification("liked", alice.id, bob.person.id, like.id) }
it "TO: goes to the right person" do
expect(mail.to).to eq([alice.email])
end
it "FROM: contains the sender's name" do
- expect(mail["From"].to_s).to eq("\"#{bob.name} (diaspora*)\" <#{AppConfig.mail.sender_address}>")
+ expect(mail["From"].to_s).to eq("\"#{pod_name} (#{bob.name})\" <#{AppConfig.mail.sender_address}>")
end
it "SUBJECT: does not show the limited post" do
@@ -436,14 +473,18 @@ describe Notifier, type: :mailer do
describe ".confirm_email" do
before do
bob.update_attribute(:unconfirmed_email, "my@newemail.com")
- @confirm_email = Notifier.confirm_email(bob.id)
+ @confirm_email = Notifier.send_notification("confirm_email", bob.id)
end
it "goes to the right person" do
expect(@confirm_email.to).to eq([bob.unconfirmed_email])
end
- it "has the unconfirmed emil in the subject" do
+ it "FROM: header should be the pod name with default sender address" do
+ expect(@confirm_email["From"].to_s).to eq("#{pod_name} <#{AppConfig.mail.sender_address}>")
+ end
+
+ it "has the unconfirmed email in the subject" do
expect(@confirm_email.subject).to include(bob.unconfirmed_email)
end
@@ -460,13 +501,48 @@ describe Notifier, type: :mailer do
end
end
+ describe ".invite" do
+ let(:email) { Notifier.invite(alice.email, nil, bob, "1234", "en") }
+
+ it "goes to the right person" do
+ expect(email.to).to eq([alice.email])
+ end
+
+ it "FROM: header should be the pod name + default sender address" do
+ expect(email["From"].to_s).to eq("#{pod_name} <#{AppConfig.mail.sender_address}>")
+ end
+
+ it "has the correct subject" do
+ expect(email.subject).to eq(I18n.translate("notifier.invited_you", name: bob.name))
+ end
+
+ it "has the inviter name in the body" do
+ expect(email.body.encoded).to include("#{bob.name} (#{bob.diaspora_handle})")
+ end
+
+ it "has the inviter id if the name is nil" do
+ bob.person.profile.update_attributes(first_name: "", last_name: "")
+ mail = Notifier.invite(alice.email, nil, bob, "1234", "en")
+ expect(email.body.encoded).to_not include("#{bob.name} (#{bob.diaspora_handle})")
+ expect(mail.body.encoded).to include(bob.person.diaspora_handle)
+ end
+
+ it "has the invitation code in the body" do
+ expect(email.body.encoded).to include("/i/1234")
+ end
+ end
+
describe ".csrf_token_fail" do
- let(:email) { Notifier.csrf_token_fail(alice.id) }
+ let(:email) { Notifier.send_notification("csrf_token_fail", alice.id) }
it "goes to the right person" do
expect(email.to).to eq([alice.email])
end
+ it "FROM: header should be the pod name + default sender address" do
+ expect(email["From"].to_s).to eq("#{pod_name} <#{AppConfig.mail.sender_address}>")
+ end
+
it "has the correct subject" do
expect(email.subject).to eq(I18n.translate("notifier.csrf_token_fail.subject", name: alice.name))
end
@@ -497,8 +573,14 @@ describe Notifier, type: :mailer do
it "handles idn addresses" do
bob.update_attribute(:email, "ŧoo@ŧexample.com")
expect {
- Notifier.started_sharing(bob.id, person.id)
+ Notifier.send_notification("started_sharing", bob.id, person.id)
}.to_not raise_error
end
+
+ it "FROM: header should be 'pod_name (username)' when there is no first and last name" do
+ bob.person.profile.update_attributes(first_name: "", last_name: "")
+ mail = Notifier.send_notification("started_sharing", alice.id, bob.person.id)
+ expect(mail["From"].to_s).to eq("\"#{pod_name} (#{bob.person.username})\" <#{AppConfig.mail.sender_address}>")
+ end
end
end
diff --git a/spec/mailers/report_spec.rb b/spec/mailers/report_spec.rb
index ce168bb3b..96699f562 100644
--- a/spec/mailers/report_spec.rb
+++ b/spec/mailers/report_spec.rb
@@ -41,6 +41,12 @@ describe Report, type: :mailer do
expect(ActionMailer::Base.deliveries[1].to[0]).to include(@user2.email)
end
+ it "FROM: header should be the pod name + default sender address" do
+ ReportMailer.new_report(@post_report.id).each(&:deliver_now)
+ pod_name = AppConfig.settings.pod_name
+ expect(ReportMailer.default[:from].to_s).to eq("\"#{pod_name}\" <#{AppConfig.mail.sender_address}>")
+ end
+
it "should send mail in recipent's prefered language" do
ReportMailer.new_report(@post_report.id).each(&:deliver_now)
expect(ActionMailer::Base.deliveries[0].subject).to match("Ein neuer post wurde als anstößig markiert")
diff --git a/spec/models/account_deletion_spec.rb b/spec/models/account_deletion_spec.rb
index 972435818..7fc069984 100644
--- a/spec/models/account_deletion_spec.rb
+++ b/spec/models/account_deletion_spec.rb
@@ -16,7 +16,7 @@ describe AccountDeletion, type: :model do
describe "#perform!" do
it "creates a deleter" do
- expect(AccountDeleter).to receive(:new).with(alice.person.diaspora_handle).and_return(double(perform!: true))
+ expect(AccountDeleter).to receive(:new).with(alice.person).and_return(double(perform!: true))
account_deletion.perform!
end
diff --git a/spec/models/account_migration_spec.rb b/spec/models/account_migration_spec.rb
new file mode 100644
index 000000000..0f62a4d8b
--- /dev/null
+++ b/spec/models/account_migration_spec.rb
@@ -0,0 +1,148 @@
+require "integration/federation/federation_helper"
+
+describe AccountMigration, type: :model do
+ describe "create!" do
+ include_context "with local old user"
+
+ it "locks old local user after creation" do
+ expect {
+ AccountMigration.create!(old_person: old_person, new_person: FactoryGirl.create(:person))
+ }.to change { old_user.reload.access_locked? }.to be_truthy
+ end
+ end
+
+ let(:old_person) { FactoryGirl.create(:person) }
+ let(:new_person) { FactoryGirl.create(:person) }
+ let(:account_migration) {
+ AccountMigration.create!(old_person: old_person, new_person: new_person)
+ }
+
+ describe "receive" do
+ it "calls perform!" do
+ expect(account_migration).to receive(:perform!)
+ account_migration.receive
+ end
+ end
+
+ describe "sender" do
+ context "with remote old user" do
+ include_context "with remote old user"
+
+ it "creates ephemeral user when private key is provided" do
+ account_migration.old_private_key = old_user.serialized_private_key
+ sender = account_migration.sender
+ expect(sender.id).to eq(old_user.diaspora_handle)
+ expect(sender.diaspora_handle).to eq(old_user.diaspora_handle)
+ expect(sender.encryption_key.to_s).to eq(old_user.encryption_key.to_s)
+ end
+
+ it "raises when no private key is provided" do
+ expect {
+ account_migration.sender
+ }.to raise_error("can't build sender without old private key defined")
+ end
+ end
+
+ context "with local old user" do
+ include_context "with local old user"
+
+ it "matches the old user" do
+ expect(account_migration.sender).to eq(old_user)
+ end
+ end
+ end
+
+ describe "performed?" do
+ it "is changed after perform!" do
+ expect {
+ account_migration.perform!
+ }.to change(account_migration, :performed?).to be_truthy
+ end
+
+ it "calls old_person.closed_account?" do
+ expect(account_migration.old_person).to receive(:closed_account?)
+ account_migration.performed?
+ end
+ end
+
+ context "with local new user" do
+ include_context "with local new user"
+
+ describe "subscribers" do
+ it "picks remote subscribers of new user profile and old person" do
+ _local_friend, remote_contact = DataGenerator.create(new_user, %i[mutual_friend remote_mutual_friend])
+ expect(account_migration.new_person.owner.profile).to receive(:subscribers).and_call_original
+ expect(account_migration.subscribers).to match_array([remote_contact.person, old_person])
+ end
+
+ context "with local old user" do
+ include_context "with local old user"
+
+ it "doesn't include old person" do
+ expect(account_migration.subscribers).to be_empty
+ end
+ end
+ end
+ end
+
+ describe "perform!" do
+ # TODO: add references update tests
+ # This spec is missing references update tests. We didn't come with a good idea of how to test it
+ # and it is currently covered by integration tests. But it's beter to add these tests at some point
+ # in future when we have more time to think about it.
+
+ let(:embedded_account_deleter) { account_migration.send(:account_deleter) }
+
+ it "raises if already performed" do
+ expect(account_migration).to receive(:performed?).and_return(true)
+ expect {
+ account_migration.perform!
+ }.to raise_error("already performed")
+ end
+
+ it "calls AccountDeleter#tombstone_person_and_profile" do
+ expect(embedded_account_deleter).to receive(:tombstone_person_and_profile)
+ account_migration.perform!
+ end
+
+ context "with local old and remote new users" do
+ include_context "with local old user"
+
+ it "calls AccountDeleter#close_user" do
+ expect(embedded_account_deleter).to receive(:close_user)
+ account_migration.perform!
+ end
+
+ it "resends contacts to the remote pod" do
+ contact = FactoryGirl.create(:contact, person: old_person, sharing: true)
+ expect(Diaspora::Federation::Dispatcher).to receive(:defer_dispatch).with(contact.user, contact)
+ account_migration.perform!
+ end
+ end
+
+ context "with local new and remote old users" do
+ include_context "with remote old user"
+ include_context "with local new user"
+
+ it "dispatches account migration message" do
+ expect(account_migration).to receive(:sender).and_return(old_user)
+ dispatcher = double
+ expect(dispatcher).to receive(:dispatch)
+ expect(Diaspora::Federation::Dispatcher).to receive(:build)
+ .with(old_user, account_migration)
+ .and_return(dispatcher)
+ account_migration.perform!
+ end
+ end
+
+ context "with local old and new users" do
+ include_context "with local old user"
+ include_context "with local new user"
+
+ it "calls AccountDeleter#tombstone_user" do
+ expect(embedded_account_deleter).to receive(:tombstone_user)
+ account_migration.perform!
+ end
+ end
+ end
+end
diff --git a/spec/models/api/openid_connect/id_token_spec.rb b/spec/models/api/openid_connect/id_token_spec.rb
index 7c85c3cb4..154bbd90f 100644
--- a/spec/models/api/openid_connect/id_token_spec.rb
+++ b/spec/models/api/openid_connect/id_token_spec.rb
@@ -7,19 +7,13 @@ describe Api::OpenidConnect::IdToken, type: :model do
let(:decoded_hash) {
JSON::JWT.decode(id_token.to_jwt, Api::OpenidConnect::IdTokenConfig::PRIVATE_KEY)
}
- let(:discovery_controller) {
- Api::OpenidConnect::DiscoveryController.new.tap {|controller|
- controller.request = ActionController::TestRequest.new
- controller.request.host = AppConfig.pod_uri.authority
- controller.response = ActionController::TestResponse.new
- }
- }
- let(:openid_webfinger) {
- JSON.parse(discovery_controller.webfinger[0])
+ let(:webfinger) {
+ DiasporaFederation.callbacks.trigger(:fetch_person_for_webfinger, alice.diaspora_handle).to_json
}
it "issuer value must much the one we provided in OpenID discovery routine" do
- expect(decoded_hash["iss"]).to eq(openid_webfinger["links"][0]["href"])
+ openid_issuer = webfinger[:links].find {|l| l[:rel] == OpenIDConnect::Discovery::Provider::Issuer::REL_VALUE }
+ expect(decoded_hash["iss"]).to eq(openid_issuer[:href])
end
end
end
diff --git a/spec/models/comment_spec.rb b/spec/models/comment_spec.rb
index 4fe1d983b..82d46566c 100644
--- a/spec/models/comment_spec.rb
+++ b/spec/models/comment_spec.rb
@@ -7,6 +7,8 @@ describe Comment, type: :model do
let(:status_bob) { bob.post(:status_message, text: "hello", to: bob.aspects.first.id) }
let(:comment_alice) { alice.comment!(status_bob, "why so formal?") }
+ it_behaves_like "it is mentions container"
+
describe "#destroy" do
it "should delete a participation" do
comment_alice
@@ -21,6 +23,36 @@ describe Comment, type: :model do
end
end
+ describe "#subscribers" do
+ let(:status_bob) { FactoryGirl.create(:status_message, public: true, author: bob.person) }
+ let(:comment_alice) {
+ FactoryGirl.create(
+ :comment,
+ text: text_mentioning(remote_raphael, local_luke),
+ post: status_bob,
+ author: alice.person
+ )
+ }
+
+ context "on the parent post pod" do
+ it "includes mentioned people to subscribers list" do
+ expect(comment_alice.subscribers).to include(remote_raphael)
+ end
+
+ it "doesn't include local mentioned people if they aren't participant or contact" do
+ expect(comment_alice.subscribers).not_to include(local_luke)
+ end
+ end
+
+ context "on a non parent post pod" do
+ let(:status_bob) { FactoryGirl.create(:status_message) } # make the message remote
+
+ it "doesn't include mentioned people to subscribers list" do
+ expect(comment_alice.subscribers).not_to include(remote_raphael)
+ end
+ end
+ end
+
describe "User#comment" do
it "should be able to comment on one's own status" do
bob.comment!(status_bob, "sup dog")
diff --git a/spec/models/contact_spec.rb b/spec/models/contact_spec.rb
index 1f9318519..aabad41dc 100644
--- a/spec/models/contact_spec.rb
+++ b/spec/models/contact_spec.rb
@@ -20,12 +20,12 @@ describe Contact, type: :model do
it "requires a user" do
contact.valid?
- expect(contact.errors.full_messages).to include "User can't be blank"
+ expect(contact.errors.full_messages).to include "User must exist"
end
it "requires a person" do
contact.valid?
- expect(contact.errors.full_messages).to include "Person can't be blank"
+ expect(contact.errors.full_messages).to include "Person must exist"
end
it "validates uniqueness" do
@@ -161,7 +161,6 @@ describe Contact, type: :model do
describe "#contacts" do
before do
bob.aspects.create(name: "next")
- bob.aspects(true)
@original_aspect = bob.aspects.where(name: "generic").first
@new_aspect = bob.aspects.where(name: "next").first
diff --git a/spec/models/location_spec.rb b/spec/models/location_spec.rb
index fe3eadfe3..0742ffa50 100644
--- a/spec/models/location_spec.rb
+++ b/spec/models/location_spec.rb
@@ -1,12 +1,14 @@
-describe Location, :type => :model do
- describe 'before validation' do
- it 'should create new location when it has coordinates' do
- location = Location.new(coordinates:'1,2')
+describe Location, type: :model do
+ describe "before validation" do
+ let(:status) { FactoryGirl.create(:status_message) }
+
+ it "should create new location when it has coordinates" do
+ location = Location.new(coordinates: "1,2", status_message: status)
expect(location.save).to be true
end
- it 'should not create new location when it does not have coordinates' do
- location = Location.new()
+ it "should not create new location when it does not have coordinates" do
+ location = Location.new(status_message: status)
expect(location.save).to be false
end
end
diff --git a/spec/models/mention_spec.rb b/spec/models/mention_spec.rb
index e0e3a2a46..6fe5ecdb5 100644
--- a/spec/models/mention_spec.rb
+++ b/spec/models/mention_spec.rb
@@ -6,9 +6,9 @@ describe Mention, type: :model do
describe "after destroy" do
it "destroys a notification" do
sm = alice.post(:status_message, text: "hi", to: alice.aspects.first)
- mention = Mention.create!(person: bob.person, post: sm)
+ mention = Mention.create!(person: bob.person, mentions_container: sm)
- Notifications::Mentioned.notify(sm, [bob.id])
+ Notifications::MentionedInPost.notify(sm, [bob.id])
expect {
mention.destroy
diff --git a/spec/models/message_spec.rb b/spec/models/message_spec.rb
index 051b384ce..e2588a502 100644
--- a/spec/models/message_spec.rb
+++ b/spec/models/message_spec.rb
@@ -39,11 +39,6 @@ describe Message, type: :model do
message = Message.create(author: local_luke.person, text: "yo", conversation: remote_conv)
expect(message.subscribers).to match_array([local_luke.person, local_leia.person, remote_raphael])
end
-
- it "returns only remote participants, if the conversation is local, but the author is remote" do
- message = Message.create(author: remote_raphael, text: "yo", conversation: local_conv)
- expect(message.subscribers).to match_array([remote_raphael])
- end
end
describe "#increase_unread" do
diff --git a/spec/models/notifications/mentioned_in_post_spec.rb b/spec/models/notifications/mentioned_in_post_spec.rb
new file mode 100644
index 000000000..90c5b007d
--- /dev/null
+++ b/spec/models/notifications/mentioned_in_post_spec.rb
@@ -0,0 +1,72 @@
+describe Notifications::MentionedInPost, type: :model do
+ let(:sm) {
+ FactoryGirl.create(:status_message, author: alice.person, text: "hi @{bob; #{bob.diaspora_handle}}", public: true)
+ }
+ let(:mentioned_notification) { Notifications::MentionedInPost.new(recipient: bob) }
+
+ describe ".notify" do
+ it "calls create_notification with mention" do
+ expect(Notifications::MentionedInPost).to receive(:create_notification).with(
+ bob, sm.mentions.first, sm.author
+ ).and_return(mentioned_notification)
+
+ Notifications::MentionedInPost.notify(sm, [])
+ end
+
+ it "sends an email to the mentioned person" do
+ allow(Notifications::MentionedInPost).to receive(:create_notification).and_return(mentioned_notification)
+ expect(bob).to receive(:mail).with(Workers::Mail::Mentioned, bob.id, sm.author.id, sm.mentions.first.id)
+
+ Notifications::MentionedInPost.notify(sm, [])
+ end
+
+ it "does nothing if the mentioned person is not local" do
+ sm = FactoryGirl.create(
+ :status_message,
+ author: alice.person,
+ text: "hi @{raphael; #{remote_raphael.diaspora_handle}}",
+ public: true
+ )
+ expect(Notifications::MentionedInPost).not_to receive(:create_notification)
+
+ Notifications::MentionedInPost.notify(sm, [])
+ end
+
+ it "does not notify if the author of the post is ignored" do
+ bob.blocks.create(person: sm.author)
+
+ expect_any_instance_of(Notifications::MentionedInPost).not_to receive(:email_the_user)
+
+ Notifications::MentionedInPost.notify(sm, [])
+
+ expect(Notifications::MentionedInPost.where(target: sm.mentions.first)).not_to exist
+ end
+
+ context "with private post" do
+ let(:private_sm) {
+ FactoryGirl.create(
+ :status_message,
+ author: remote_raphael,
+ text: "hi @{bob; #{bob.diaspora_handle}}",
+ public: false
+ ).tap {|private_sm|
+ private_sm.receive([bob.id, alice.id])
+ }
+ }
+
+ it "calls create_notification if the mentioned person is a recipient of the post" do
+ expect(Notifications::MentionedInPost).to receive(:create_notification).with(
+ bob, private_sm.mentions.first, private_sm.author
+ ).and_return(mentioned_notification)
+
+ Notifications::MentionedInPost.notify(private_sm, [bob.id])
+ end
+
+ it "does not call create_notification if the mentioned person is not a recipient of the post" do
+ expect(Notifications::MentionedInPost).not_to receive(:create_notification)
+
+ Notifications::MentionedInPost.notify(private_sm, [alice.id])
+ end
+ end
+ end
+end
diff --git a/spec/models/notifications/mentioned_spec.rb b/spec/models/notifications/mentioned_spec.rb
index d9f05f30e..2256a35a8 100644
--- a/spec/models/notifications/mentioned_spec.rb
+++ b/spec/models/notifications/mentioned_spec.rb
@@ -1,70 +1,53 @@
-describe Notifications::Mentioned, type: :model do
- let(:sm) {
- FactoryGirl.create(:status_message, author: alice.person, text: "hi @{bob; #{bob.diaspora_handle}}", public: true)
- }
- let(:mentioned_notification) { Notifications::Mentioned.new(recipient: bob) }
+describe Notifications::Mentioned do
+ class TestNotification < Notification
+ include Notifications::Mentioned
- describe ".notify" do
- it "calls create_notification with mention" do
- expect(Notifications::Mentioned).to receive(:create_notification).with(
- bob, sm.mentions.first, sm.author
- ).and_return(mentioned_notification)
-
- Notifications::Mentioned.notify(sm, [])
+ def self.filter_mentions(mentions, *)
+ mentions
end
+ end
- it "sends an email to the mentioned person" do
- allow(Notifications::Mentioned).to receive(:create_notification).and_return(mentioned_notification)
- expect(bob).to receive(:mail).with(Workers::Mail::Mentioned, bob.id, sm.author.id, sm.mentions.first.id)
-
- Notifications::Mentioned.notify(sm, [])
+ describe ".notify" do
+ let(:status_message) {
+ FactoryGirl.create(:status_message, text: text_mentioning(remote_raphael, alice, bob, eve), author: eve.person)
+ }
+
+ it "calls filter_mentions on self" do
+ expect(TestNotification).to receive(:filter_mentions).with(
+ match_array(Mention.where(mentions_container: status_message, person: [alice, bob].map(&:person))),
+ status_message,
+ [alice.id, bob.id]
+ ).and_return([])
+
+ TestNotification.notify(status_message, [alice.id, bob.id])
end
- it "does nothing if the mentioned person is not local" do
- sm = FactoryGirl.create(
- :status_message,
- author: alice.person,
- text: "hi @{raphael; #{remote_raphael.diaspora_handle}}",
- public: true
- )
- expect(Notifications::Mentioned).not_to receive(:create_notification)
+ it "creates notification for each mention" do
+ [alice, bob].each do |recipient|
+ expect(TestNotification).to receive(:create_notification).with(
+ recipient,
+ Mention.where(mentions_container: status_message, person: recipient.person_id).first,
+ status_message.author
+ )
+ end
- Notifications::Mentioned.notify(sm, [])
+ TestNotification.notify(status_message, nil)
end
- it "does not notify if the author of the post is ignored" do
- bob.blocks.create(person: sm.author)
-
- expect_any_instance_of(Notifications::Mentioned).not_to receive(:email_the_user)
-
- Notifications::Mentioned.notify(sm, [])
+ it "creates email notification for mention" do
+ status_message = FactoryGirl.create(:status_message, text: text_mentioning(alice), author: eve.person)
+ expect_any_instance_of(TestNotification).to receive(:email_the_user).with(
+ Mention.where(mentions_container: status_message, person: alice.person_id).first,
+ status_message.author
+ )
- expect(Notifications::Mentioned.where(target: sm.mentions.first)).not_to exist
+ TestNotification.notify(status_message, nil)
end
- context "with private post" do
- let(:private_sm) {
- FactoryGirl.create(
- :status_message,
- author: remote_raphael,
- text: "hi @{bob; #{bob.diaspora_handle}}",
- public: false
- )
- }
-
- it "calls create_notification if the mentioned person is a recipient of the post" do
- expect(Notifications::Mentioned).to receive(:create_notification).with(
- bob, private_sm.mentions.first, private_sm.author
- ).and_return(mentioned_notification)
-
- Notifications::Mentioned.notify(private_sm, [bob.id])
- end
-
- it "does not call create_notification if the mentioned person is not a recipient of the post" do
- expect(Notifications::Mentioned).not_to receive(:create_notification)
-
- Notifications::Mentioned.notify(private_sm, [alice.id])
- end
+ it "doesn't create notification if it was filtered out by filter_mentions" do
+ expect(TestNotification).to receive(:filter_mentions).and_return([])
+ expect(TestNotification).not_to receive(:create_notification)
+ TestNotification.notify(status_message, nil)
end
end
end
diff --git a/spec/models/notifications/private_message_spec.rb b/spec/models/notifications/private_message_spec.rb
index 4ab3b0d79..327312ff6 100644
--- a/spec/models/notifications/private_message_spec.rb
+++ b/spec/models/notifications/private_message_spec.rb
@@ -4,7 +4,7 @@
describe Notifications::PrivateMessage, type: :model do
let(:conversation) {
- conv_guid = FactoryGirl.generate(:guid)
+ conv_guid = Fabricate.sequence(:guid)
Conversation.create(
guid: conv_guid,
diff --git a/spec/models/person_spec.rb b/spec/models/person_spec.rb
index f9e76db51..7cfe69ab9 100644
--- a/spec/models/person_spec.rb
+++ b/spec/models/person_spec.rb
@@ -24,16 +24,6 @@ describe Person, :type => :model do
Person.for_json.first.serialized_public_key
}.to raise_error ActiveModel::MissingAttributeError
end
-
- it 'selects distinct people' do
- aspect = bob.aspects.create(:name => 'hilarious people')
- aspect.contacts << bob.contact_for(eve.person)
- person_ids = Person.for_json.joins(:contacts => :aspect_memberships).
- where(:contacts => {:user_id => bob.id},
- :aspect_memberships => {:aspect_id => bob.aspect_ids}).map{|p| p.id}
-
- expect(person_ids.uniq).to eq(person_ids)
- end
end
describe '.local' do
@@ -94,6 +84,118 @@ describe Person, :type => :model do
expect(Person.who_have_reshared_a_users_posts(alice)).to eq([reshare.author])
end
end
+
+ describe ".find_by_substring" do
+ it "returns \"none\" when the substring is less than 1 non-space character" do
+ expect(Person.find_by_substring("R")).to eq(Person.none)
+ expect(Person.find_by_substring("R ")).to eq(Person.none)
+ expect(Person.find_by_substring("")).to eq(Person.none)
+ expect(Person.find_by_substring(" ")).to eq(Person.none)
+ end
+
+ it "finds a person with a profile name containing the substring" do
+ substring = r_str
+ person = FactoryGirl.create(:person, first_name: "A#{substring}A")
+ expect(Person.find_by_substring(substring)).to include(person)
+ end
+
+ it "finds a person with a diaspora ID starting with the substring" do
+ substring = r_str
+ person = FactoryGirl.create(:person, diaspora_handle: "#{substring}A@pod.tld")
+ expect(Person.find_by_substring(substring)).to include(person)
+ end
+ end
+
+ describe ".allowed_to_be_mentioned_in_a_comment_to" do
+ let(:status_bob) { bob.post(:status_message, text: "hello", to: bob.aspects.first.id) }
+
+ it "returns the author and people who have commented or liked the private post" do
+ kate = FactoryGirl.create(:user_with_aspect, friends: [bob])
+ olga = FactoryGirl.create(:user_with_aspect, friends: [bob])
+ alice.comment!(status_bob, "why so formal?")
+ eve.comment!(status_bob, "comment text")
+ kate.like!(status_bob)
+ olga.participate!(status_bob)
+ expect(
+ Person.allowed_to_be_mentioned_in_a_comment_to(status_bob).ids
+ ).to match_array([alice, bob, eve, kate].map(&:person_id))
+ end
+
+ it "selects distinct people" do
+ alice.comment!(status_bob, "hi")
+ alice.comment!(status_bob, "how are you?")
+ expect(
+ Person.allowed_to_be_mentioned_in_a_comment_to(status_bob).ids
+ ).to match_array([alice, bob].map(&:person_id))
+ end
+
+ it "returns all for public posts" do
+ status_bob.update(public: true) # set parent public
+ expect(Person.allowed_to_be_mentioned_in_a_comment_to(status_bob).ids).to match_array(Person.ids)
+ end
+ end
+
+ describe ".sort_for_mention_suggestion" do
+ let(:status_message) { FactoryGirl.create(:status_message) }
+
+ it "returns people sorted in the order: post author > commenters > likers > contacts" do
+ like = FactoryGirl.create(:like, target: status_message)
+ comment = FactoryGirl.create(:comment, post: status_message)
+ current_user = FactoryGirl.create(:user_with_aspect, friends: [alice])
+ result = Person.select(:id, :guid).sort_for_mention_suggestion(status_message, current_user)
+ expect(result[0]).to eq(status_message.author)
+ expect(result[1]).to eq(comment.author)
+ expect(result[2]).to eq(like.author)
+ expect(result[3]).to eq(alice.person) # a contact of the current user
+ end
+
+ it "sorts people of the same priority by profile name" do
+ current_user = FactoryGirl.create(:user_with_aspect)
+ person1 = FactoryGirl.create(:person, first_name: "x2")
+ person2 = FactoryGirl.create(:person, first_name: "x1")
+ result = Person
+ .select(:id, :guid)
+ .where(id: [person1.id, person2.id])
+ .sort_for_mention_suggestion(status_message, current_user)
+ expect(result[0].id).to eq(person2.id)
+ expect(result[1].id).to eq(person1.id)
+ end
+
+ it "sorts people of the same priority and same names by diaspora ID" do
+ current_user = FactoryGirl.create(:user_with_aspect)
+ person1 = FactoryGirl.create(:person, diaspora_handle: "x2@pod.tld")
+ person1.profile.update(first_name: "John", last_name: "Doe")
+ person2 = FactoryGirl.create(:person, diaspora_handle: "x1@pod.tld")
+ person2.profile.update(first_name: "John", last_name: "Doe")
+ result = Person
+ .select(:id, :guid)
+ .where(id: [person1.id, person2.id])
+ .sort_for_mention_suggestion(status_message, current_user)
+ expect(result[0].id).to eq(person2.id)
+ expect(result[1].id).to eq(person1.id)
+ end
+ end
+
+ describe ".in_aspects" do
+ it "returns person that is in the aspect" do
+ aspect = FactoryGirl.create(:aspect)
+ contact = FactoryGirl.create(:contact, user: aspect.user)
+ aspect.contacts << contact
+ expect(Person.in_aspects([aspect.id])).to include(contact.person)
+ end
+
+ it "returns same person in multiple aspects only once" do
+ user = bob
+ contact = FactoryGirl.create(:contact, user: user)
+ ids = Array.new(2) do
+ aspect = FactoryGirl.create(:aspect, user: user, name: r_str)
+ aspect.contacts << contact
+ aspect.id
+ end
+
+ expect(Person.in_aspects(ids)).to eq([contact.person])
+ end
+ end
end
describe "delegating" do
diff --git a/spec/models/photo_spec.rb b/spec/models/photo_spec.rb
index 1d3ee559d..31d4afff6 100644
--- a/spec/models/photo_spec.rb
+++ b/spec/models/photo_spec.rb
@@ -178,7 +178,7 @@ describe Photo, :type => :model do
file = File.open(@fail_fixture_name)
expect {
@photo.unprocessed_image.store! file
- }.to raise_error CarrierWave::IntegrityError, 'You are not allowed to upload "xml" files, allowed types: jpg, jpeg, png, gif'
+ }.to raise_error CarrierWave::IntegrityError
end
end
@@ -203,12 +203,6 @@ describe Photo, :type => :model do
end
end
- context "commenting" do
- it "accepts comments if there is no parent status message" do
- expect{ @user.comment!(@photo, "big willy style") }.to change(@photo.comments, :count).by(1)
- end
- end
-
describe '#queue_processing_job' do
it 'should queue a job to process the images' do
expect(Workers::ProcessPhoto).to receive(:perform_async).with(@photo.id)
diff --git a/spec/models/pod_spec.rb b/spec/models/pod_spec.rb
index 730f240e3..99e860c0b 100644
--- a/spec/models/pod_spec.rb
+++ b/spec/models/pod_spec.rb
@@ -142,6 +142,7 @@ describe Pod, type: :model do
before do
@pod = FactoryGirl.create(:pod)
@result = double("result")
+ @now = Time.zone.now
allow(@result).to receive(:rt) { 123 }
allow(@result).to receive(:software_version) { "diaspora a.b.c.d" }
@@ -158,7 +159,7 @@ describe Pod, type: :model do
expect(@pod.status).to eq("no_errors")
expect(@pod.offline?).to be_falsy
expect(@pod.response_time).to eq(123)
- expect(@pod.checked_at).to be_within(1.second).of Time.zone.now
+ expect(@pod.checked_at).to be_within(1.second).of @now
end
it "resets the scheduled_check flag" do
@@ -177,7 +178,7 @@ describe Pod, type: :model do
@pod.test_connection!
expect(@pod.offline?).to be_truthy
- expect(@pod.offline_since).to be_within(1.second).of Time.zone.now
+ expect(@pod.offline_since).to be_within(1.second).of @now
end
it "preserves the original offline timestamp" do
@@ -185,13 +186,12 @@ describe Pod, type: :model do
expect(@result).to receive(:error).at_least(:once) { ConnectionTester::NetFailure.new }
@pod.test_connection!
- now = Time.zone.now
- expect(@pod.offline_since).to be_within(1.second).of now
+ expect(@pod.offline_since).to be_within(1.second).of @now
Timecop.travel(Time.zone.today + 30.days) do
@pod.test_connection!
- expect(@pod.offline_since).to be_within(1.second).of now
- expect(Time.zone.now).to be_within(1.day).of(now + 30.days)
+ expect(@pod.offline_since).to be_within(1.second).of @now
+ expect(Time.zone.now).to be_within(1.day).of(@now + 30.days)
end
end
end
@@ -215,19 +215,22 @@ describe Pod, type: :model do
end
it "handles a failed status" do
+ now = Time.zone.now
+
pod.status = :unknown_error
pod.update_offline_since
expect(pod.offline?).to be_truthy
- expect(pod.offline_since).to be_within(1.second).of Time.zone.now
+ expect(pod.offline_since).to be_within(1.second).of now
end
it "preserves the original offline timestamp" do
+ now = Time.zone.now
+
pod.status = :unknown_error
pod.update_offline_since
pod.save
- now = Time.zone.now
expect(pod.offline_since).to be_within(1.second).of now
Timecop.travel(Time.zone.today + 30.days) do
diff --git a/spec/models/poll_participation_spec.rb b/spec/models/poll_participation_spec.rb
index 65730481b..677da69f0 100644
--- a/spec/models/poll_participation_spec.rb
+++ b/spec/models/poll_participation_spec.rb
@@ -1,25 +1,25 @@
describe PollParticipation, type: :model do
+ let(:status) { bob.post(:status_message, text: "hello", to: bob.aspects.first.id) }
+ let(:poll) { Poll.new(question: "Who is in charge?") }
+
before do
- @alices_aspect = alice.aspects.first
- @status = bob.post(:status_message, :text => "hello", :to => bob.aspects.first.id)
- @poll = Poll.new(:question => 'Who is in charge?')
- @poll.poll_answers.build(:answer => "a")
- @poll.poll_answers.build(:answer => "b")
- @status.poll = @poll
+ poll.poll_answers.build(answer: "a").poll = poll
+ poll.poll_answers.build(answer: "b").poll = poll
+ status.poll = poll
end
describe 'validation' do
it 'forbids multiple participations in the same poll' do
expect {
2.times do |run|
- bob.participate_in_poll!(@status, @poll.poll_answers.first)
+ bob.participate_in_poll!(status, poll.poll_answers.first)
end
}.to raise_error ActiveRecord::RecordInvalid
end
it 'allows a one time participation in a poll' do
expect {
- bob.participate_in_poll!(@status, @poll.poll_answers.first)
+ bob.participate_in_poll!(status, poll.poll_answers.first)
}.to_not raise_error
end
end
@@ -38,6 +38,6 @@ describe PollParticipation, type: :model do
let(:remote_object_on_local_parent) {
FactoryGirl.create(:poll_participation, poll_answer: local_parent.poll.poll_answers.first, author: remote_raphael)
}
- let(:relayable) { PollParticipation::Generator.new(alice, @status, @poll.poll_answers.first).build }
+ let(:relayable) { PollParticipation::Generator.new(alice, status, poll.poll_answers.first).build }
end
end
diff --git a/spec/models/poll_spec.rb b/spec/models/poll_spec.rb
index 30fd872bb..f18eb4fab 100644
--- a/spec/models/poll_spec.rb
+++ b/spec/models/poll_spec.rb
@@ -1,24 +1,23 @@
-describe Poll, :type => :model do
- before do
- @poll = Poll.new(:question => "What do you think about apples?")
- end
+describe Poll, type: :model do
+ let(:status) { FactoryGirl.create(:status_message) }
+ let(:poll) { Poll.new(question: "What do you think about apples?", status_message: status) }
- describe 'validation' do
- it 'should not create a poll when it has less than two answers' do
- @poll.poll_answers.build(:answer => '1')
- expect(@poll).not_to be_valid
+ describe "validation" do
+ it "should not create a poll when it has less than two answers" do
+ poll.poll_answers.build(answer: "1").poll = poll
+ expect(poll).not_to be_valid
end
- it 'should create a poll when it has more than two answers' do
- @poll.poll_answers.build(:answer => '1')
- @poll.poll_answers.build(:answer => '2')
- expect(@poll).to be_valid
+ it "should create a poll when it has more than two answers" do
+ poll.poll_answers.build(answer: "1").poll = poll
+ poll.poll_answers.build(answer: "2").poll = poll
+ expect(poll).to be_valid
end
- it 'should not create a poll when question in blank' do
- @poll.question = ' '
- @poll.valid?
- expect(@poll.errors).to have_key(:question)
+ it "should not create a poll when question in blank" do
+ poll.question = " "
+ poll.valid?
+ expect(poll.errors).to have_key(:question)
end
end
end
diff --git a/spec/models/post_spec.rb b/spec/models/post_spec.rb
index fd7b44274..fdfc1f4b4 100644
--- a/spec/models/post_spec.rb
+++ b/spec/models/post_spec.rb
@@ -65,12 +65,12 @@ describe Post, :type => :model do
it 'calls includes_for_a_stream' do
expect(Post).to receive(:includes_for_a_stream)
- Post.for_a_stream(double, double)
+ Post.for_a_stream(Time.zone.now, "created_at")
end
it 'calls excluding_blocks if a user is present' do
expect(Post).to receive(:excluding_blocks).with(alice).and_return(Post)
- Post.for_a_stream(double, double, alice)
+ Post.for_a_stream(Time.zone.now, "created_at", alice)
end
end
@@ -168,12 +168,56 @@ describe Post, :type => :model do
it "returns them in reverse creation order" do
posts = Post.for_visible_shareable_sql(Time.now + 1, "created_at")
expect(posts.first.text).to eq("second")
- expect(posts.at(1).text).to eq("first")
+ expect(posts.second.text).to eq("first")
expect(posts.last.text).to eq("alice - 5")
end
end
end
end
+
+ describe ".subscribed_by" do
+ let(:user) { FactoryGirl.create(:user) }
+
+ context "when the user has a participation on a post" do
+ let(:post) { FactoryGirl.create(:status_message_with_participations, participants: [user]) }
+
+ it "includes the post to the result set" do
+ expect(Post.subscribed_by(user)).to eq([post])
+ end
+ end
+
+ context "when the user doens't have a participation on a post" do
+ before do
+ FactoryGirl.create(:status_message)
+ end
+
+ it "returns empty result set" do
+ expect(Post.subscribed_by(user)).to be_empty
+ end
+ end
+ end
+
+ describe ".reshared_by" do
+ let(:person) { FactoryGirl.create(:person) }
+
+ context "when the person has a reshare for a post" do
+ let(:post) { FactoryGirl.create(:reshare, author: person).root }
+
+ it "includes the post to the result set" do
+ expect(Post.reshared_by(person)).to eq([post])
+ end
+ end
+
+ context "when the person has no reshare for a post" do
+ before do
+ FactoryGirl.create(:status_message)
+ end
+
+ it "returns empty result set" do
+ expect(Post.reshared_by(person)).to be_empty
+ end
+ end
+ end
end
describe 'validations' do
diff --git a/spec/models/profile_spec.rb b/spec/models/profile_spec.rb
index 85c630bfe..678dc677c 100644
--- a/spec/models/profile_spec.rb
+++ b/spec/models/profile_spec.rb
@@ -185,6 +185,18 @@ describe Profile, :type => :model do
end
end
+ describe "public?" do
+ it "is public if public_details is true" do
+ profile = FactoryGirl.build(:profile, public_details: true)
+ expect(profile.public?).to be_truthy
+ end
+
+ it "is not public if public_details is false" do
+ profile = FactoryGirl.build(:profile, public_details: false)
+ expect(profile.public?).to be_falsey
+ end
+ end
+
describe 'date=' do
let(:profile) { FactoryGirl.build(:profile) }
@@ -257,30 +269,6 @@ describe Profile, :type => :model do
it_should_behave_like 'it is taggable'
end
- describe '#formatted_birthday' do
- before do
- @profile = FactoryGirl.build(:profile)
- @profile_hash = { 'year' => '2000', 'month' => '01', 'day' => '01' }
- @profile.date = @profile_hash
- end
-
- it 'returns a formatted date' do
- expect(@profile.formatted_birthday).to eq("January 1, 2000")
- end
-
- it 'removes nil year birthdays' do
- @profile_hash.delete('year')
- @profile.date = @profile_hash
- expect(@profile.formatted_birthday).to eq('January 1')
- end
-
- it 'retuns nil if no birthday is set' do
- @profile.date = {}
- expect(@profile.formatted_birthday).to eq(nil)
- end
-
- end
-
describe "#tombstone!" do
before do
@profile = bob.person.profile
@@ -299,6 +287,12 @@ describe Profile, :type => :model do
expect(@profile.taggings).to receive(:delete_all)
@profile.tombstone!
end
+
+ it "doesn't recreate taggings if tag string was requested" do
+ @profile.tag_string
+ @profile.tombstone!
+ expect(@profile.taggings).to be_empty
+ end
end
describe "#clearable_fields" do
diff --git a/spec/models/role_spec.rb b/spec/models/role_spec.rb
index 97b4424d1..dad31a04d 100644
--- a/spec/models/role_spec.rb
+++ b/spec/models/role_spec.rb
@@ -6,7 +6,12 @@ describe Role do
let!(:moderator_role) { moderator.roles.create(name: "moderator") }
describe "validations" do
- it { should validate_presence_of(:person) }
+ it "validates the presence of the person" do
+ role = Role.new(name: "admin")
+ role.valid?
+ expect(role.errors.full_messages).to include "Person must exist"
+ end
+
it { should validate_uniqueness_of(:name).scoped_to(:person_id) }
it { should validate_inclusion_of(:name).in_array(%w(admin spotlight moderator)) }
end
diff --git a/spec/models/status_message_spec.rb b/spec/models/status_message_spec.rb
index 843305813..d7632958e 100644
--- a/spec/models/status_message_spec.rb
+++ b/spec/models/status_message_spec.rb
@@ -9,16 +9,21 @@ describe StatusMessage, type: :model do
let!(:aspect) { user.aspects.first }
let(:status) { build(:status_message) }
+ it_behaves_like "a shareable" do
+ let(:object) { status }
+ end
+
describe "scopes" do
describe ".where_person_is_mentioned" do
it "returns status messages where the given person is mentioned" do
@bob = bob.person
@test_string = "@{Daniel; #{@bob.diaspora_handle}} can mention people like Raph"
+ post1 = FactoryGirl.create(:status_message, text: @test_string, public: true)
+ post2 = FactoryGirl.create(:status_message, text: @test_string, public: true)
FactoryGirl.create(:status_message, text: @test_string)
- FactoryGirl.create(:status_message, text: @test_string)
- FactoryGirl.create(:status_message)
+ FactoryGirl.create(:status_message, public: true)
- expect(StatusMessage.where_person_is_mentioned(bob).count).to eq(2)
+ expect(StatusMessage.where_person_is_mentioned(@bob).ids).to match_array([post1.id, post2.id])
end
end
@@ -81,14 +86,6 @@ describe StatusMessage, type: :model do
end
end
- describe ".after_create" do
- it "calls create_mentions" do
- status = FactoryGirl.build(:status_message, text: "text @{Test; #{alice.diaspora_handle}}")
- expect(status).to receive(:create_mentions).and_call_original
- status.save
- end
- end
-
context "emptiness" do
it "needs either a message or at least one photo" do
post = user.build_post(:status_message, text: nil)
@@ -131,57 +128,20 @@ describe StatusMessage, type: :model do
expect(status_message).not_to be_valid
end
- describe "mentions" do
- let(:people) { [alice, bob, eve].map(&:person) }
- let(:test_string) {
- "@{Raphael; #{people[0].diaspora_handle}} can mention people like Raphael @{Ilya; #{people[1].diaspora_handle}}
- can mention people like Raphaellike Raphael @{Daniel; #{people[2].diaspora_handle}} can mention people like Raph"
- }
- let(:status_message) { create(:status_message, text: test_string) }
-
- describe "#create_mentions" do
- it "creates a mention for everyone mentioned in the message" do
- status_message
- expect(Diaspora::Mentionable).to receive(:people_from_string).and_return(people)
- status_message.mentions.delete_all
- status_message.create_mentions
- expect(status_message.mentions(true).map(&:person).to_set).to eq(people.to_set)
- end
+ it_behaves_like "it is mentions container"
- it "does not barf if it gets called twice" do
- status_message.create_mentions
+ describe "#people_allowed_to_be_mentioned" do
+ it "returns only aspects members for private posts" do
+ sm = FactoryGirl.build(:status_message_in_aspect)
+ sm.author.owner.share_with(alice.person, sm.author.owner.aspects.first)
+ sm.author.owner.share_with(eve.person, sm.author.owner.aspects.first)
+ sm.save!
- expect {
- status_message.create_mentions
- }.to_not raise_error
- end
+ expect(sm.people_allowed_to_be_mentioned).to match_array([alice.person_id, eve.person_id])
end
- describe "#mentioned_people" do
- it "does not call create_mentions if there are no mentions in the db" do
- status_message.mentions.delete_all
- expect(status_message).not_to receive(:create_mentions)
- status_message.mentioned_people
- end
-
- it "returns the mentioned people" do
- expect(status_message.mentioned_people.to_set).to eq(people.to_set)
- end
-
- it "does not call create_mentions if there are mentions in the db" do
- expect(status_message).not_to receive(:create_mentions)
- status_message.mentioned_people
- end
- end
-
- describe "#mentions?" do
- it "returns true if the person was mentioned" do
- expect(status_message.mentions?(people[0])).to be true
- end
-
- it "returns false if the person was not mentioned" do
- expect(status_message.mentions?(FactoryGirl.build(:person))).to be false
- end
+ it "returns :all for public posts" do
+ expect(FactoryGirl.create(:status_message, public: true).people_allowed_to_be_mentioned).to eq(:all)
end
end
@@ -233,7 +193,7 @@ describe StatusMessage, type: :model do
it "should queue a GatherOembedData if it includes a link" do
status_message
- expect(Workers::GatherOEmbedData).to receive(:perform_async).with(instance_of(Fixnum), instance_of(String))
+ expect(Workers::GatherOEmbedData).to receive(:perform_async).with(kind_of(Integer), instance_of(String))
status_message.save
end
@@ -254,7 +214,7 @@ describe StatusMessage, type: :model do
it "should queue a GatherOpenGraphData if it includes a link" do
status_message
- expect(Workers::GatherOpenGraphData).to receive(:perform_async).with(instance_of(Fixnum), instance_of(String))
+ expect(Workers::GatherOpenGraphData).to receive(:perform_async).with(kind_of(Integer), instance_of(String))
status_message.save
end
diff --git a/spec/models/user/connecting_spec.rb b/spec/models/user/connecting_spec.rb
index 455ce2143..2d6d53f9d 100644
--- a/spec/models/user/connecting_spec.rb
+++ b/spec/models/user/connecting_spec.rb
@@ -21,7 +21,7 @@ describe User::Connecting, type: :model do
expect {
eve.disconnected_by(alice.person)
- }.to change(eve.contacts(true), :count).by(-1)
+ }.to change(eve.contacts, :count).by(-1)
end
it "does not remove contact if disconnect twice" do
@@ -31,7 +31,7 @@ describe User::Connecting, type: :model do
expect {
bob.disconnected_by(alice.person)
bob.disconnected_by(alice.person)
- }.not_to change(bob.contacts(true), :count)
+ }.not_to change(bob.contacts, :count)
contact.reload
expect(contact).not_to be_sharing
@@ -50,7 +50,7 @@ describe User::Connecting, type: :model do
it "removes a contacts receiving flag" do
expect(bob.contacts.find_by(person_id: alice.person.id)).to be_receiving
bob.disconnect(bob.contact_for(alice.person))
- expect(bob.contacts(true).find_by(person_id: alice.person.id)).not_to be_receiving
+ expect(bob.contacts.reload.find_by(person_id: alice.person.id)).not_to be_receiving
end
it "removes contact if not sharing" do
@@ -58,7 +58,7 @@ describe User::Connecting, type: :model do
expect {
alice.disconnect(contact)
- }.to change(alice.contacts(true), :count).by(-1)
+ }.to change(alice.contacts, :count).by(-1)
end
it "does not remove contact if disconnect twice" do
@@ -68,7 +68,7 @@ describe User::Connecting, type: :model do
expect {
alice.disconnect(contact)
alice.disconnect(contact)
- }.not_to change(bob.contacts(true), :count)
+ }.not_to change(bob.contacts, :count)
contact.reload
expect(contact).not_to be_receiving
@@ -87,6 +87,7 @@ describe User::Connecting, type: :model do
contact = local_leia.contact_for(remote_raphael)
retraction = double
+ expect(contact).to receive(:receiving=).with(false)
expect(Retraction).to receive(:for).with(contact).and_return(retraction)
expect(retraction).to receive(:defer_dispatch).with(local_leia)
@@ -99,7 +100,7 @@ describe User::Connecting, type: :model do
expect {
alice.disconnect(contact)
- }.to change(contact.aspects(true), :count).from(2).to(0)
+ }.to change(contact.aspects, :count).from(2).to(0)
end
end
end
diff --git a/spec/models/user/posting_spec.rb b/spec/models/user/posting_spec.rb
index 83226b16a..dd24509ed 100644
--- a/spec/models/user/posting_spec.rb
+++ b/spec/models/user/posting_spec.rb
@@ -10,18 +10,17 @@ describe User, :type => :model do
describe '#add_to_streams' do
before do
- @params = {:text => "hey", :to => [@aspect.id, @aspect1.id]}
- @post = alice.build_post(:status_message, @params)
+ @post = alice.build_post(:status_message, text: "hey")
@post.save
- @aspect_ids = @params[:to]
+ @aspect_ids = [@aspect.id, @aspect1.id]
@aspects = alice.aspects_from_ids(@aspect_ids)
end
it 'saves post into visible post ids' do
expect {
alice.add_to_streams(@post, @aspects)
- }.to change{alice.visible_shareables(Post, :by_members_of => @aspects).length}.by(1)
- expect(alice.visible_shareables(Post, :by_members_of => @aspects)).to include @post
+ }.to change { alice.visible_shareables(Post, by_members_of: @aspect_ids).length }.by(1)
+ expect(alice.visible_shareables(Post, by_members_of: @aspect_ids)).to include @post
end
it 'saves post into each aspect in aspect_ids' do
diff --git a/spec/models/user/querying_spec.rb b/spec/models/user/querying_spec.rb
index 471f2e32e..18ea07dfd 100644
--- a/spec/models/user/querying_spec.rb
+++ b/spec/models/user/querying_spec.rb
@@ -72,7 +72,7 @@ describe User::Querying, :type => :model do
end
it "does not pull back hidden posts" do
- @status.share_visibilities(Post).where(user_id: alice.id).first.update_attributes(hidden: true)
+ @status.share_visibilities.where(user_id: alice.id).first.update_attributes(hidden: true)
expect(alice.visible_shareable_ids(Post).include?(@status.id)).to be false
end
end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index f12f0390c..c74969c0e 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -778,7 +778,7 @@ describe User, :type => :model do
context "posts" do
it "sends a retraction" do
- expect(Retraction).to receive(:for).with(post, bob).and_return(retraction)
+ expect(Retraction).to receive(:for).with(post).and_return(retraction)
expect(retraction).to receive(:defer_dispatch).with(bob)
expect(retraction).to receive(:perform)
@@ -981,63 +981,84 @@ describe User, :type => :model do
describe "queue_export" do
it "queues up a job to perform the export" do
- user = FactoryGirl.create :user
+ user = FactoryGirl.create(:user)
+ user.update export: Tempfile.new([user.username, ".json.gz"]), exported_at: Time.zone.now
expect(Workers::ExportUser).to receive(:perform_async).with(user.id)
user.queue_export
expect(user.exporting).to be_truthy
+ expect(user.export).not_to be_present
+ expect(user.exported_at).to be_nil
end
end
describe "perform_export!" do
+ let(:user) { FactoryGirl.create(:user, exporting: true) }
+
it "saves a json export to the user" do
- user = FactoryGirl.create :user, exporting: true
user.perform_export!
expect(user.export).to be_present
expect(user.exported_at).to be_present
expect(user.exporting).to be_falsey
- expect(user.export.filename).to match /.json/
+ expect(user.export.filename).to match(/.json/)
expect(ActiveSupport::Gzip.decompress(user.export.file.read)).to include user.username
end
it "compresses the result" do
- user = FactoryGirl.create :user, exporting: true
expect(ActiveSupport::Gzip).to receive :compress
user.perform_export!
end
+
+ it "resets exporting to false when failing" do
+ expect_any_instance_of(Diaspora::Exporter).to receive(:execute).and_raise("Unexpected error!")
+ user.perform_export!
+ expect(user.exporting).to be_falsey
+ expect(user.export).not_to be_present
+ end
end
describe "queue_export_photos" do
it "queues up a job to perform the export photos" do
- user = FactoryGirl.create :user
+ user = FactoryGirl.create(:user)
+ user.update exported_photos_file: Tempfile.new([user.username, ".zip"]), exported_photos_at: Time.zone.now
expect(Workers::ExportPhotos).to receive(:perform_async).with(user.id)
user.queue_export_photos
expect(user.exporting_photos).to be_truthy
+ expect(user.exported_photos_file).not_to be_present
+ expect(user.exported_photos_at).to be_nil
end
end
describe "perform_export_photos!" do
+ let(:user) { FactoryGirl.create(:user_with_aspect, exporting: true) }
+
before do
- @user = alice
- filename = 'button.png'
- image = File.join(File.dirname(__FILE__), '..', 'fixtures', filename)
- @saved_image = @user.build_post(:photo, :user_file => File.open(image), :to => alice.aspects.first.id)
+ image = File.join(File.dirname(__FILE__), "..", "fixtures", "button.png")
+ @saved_image = user.build_post(:photo, user_file: File.open(image), to: user.aspects.first.id)
@saved_image.save!
end
it "saves a zip export to the user" do
- @user.perform_export_photos!
- expect(@user.exported_photos_file).to be_present
- expect(@user.exported_photos_at).to be_present
- expect(@user.exporting_photos).to be_falsey
- expect(@user.exported_photos_file.filename).to match /.zip/
- expect(Zip::File.open(@user.exported_photos_file.path).entries.count).to eq(1)
+ user.perform_export_photos!
+ expect(user.exported_photos_file).to be_present
+ expect(user.exported_photos_at).to be_present
+ expect(user.exporting_photos).to be_falsey
+ expect(user.exported_photos_file.filename).to match(/.zip/)
+ expect(Zip::File.open(user.exported_photos_file.path).entries.count).to eq(1)
end
it "does not add empty entries when photo not found" do
- File.unlink @user.photos.first.unprocessed_image.path
- @user.perform_export_photos!
- expect(@user.exported_photos_file.filename).to match /.zip/
- expect(Zip::File.open(@user.exported_photos_file.path).entries.count).to eq(0)
+ File.unlink user.photos.first.unprocessed_image.path
+ user.perform_export_photos!
+ expect(user.exporting_photos).to be_falsey
+ expect(user.exported_photos_file.filename).to match(/.zip/)
+ expect(Zip::File.open(user.exported_photos_file.path).entries.count).to eq(0)
+ end
+
+ it "resets exporting_photos to false when failing" do
+ expect_any_instance_of(PhotoExporter).to receive(:perform).and_raise("Unexpected error!")
+ user.perform_export_photos!
+ expect(user.exporting_photos).to be_falsey
+ expect(user.exported_photos_file).not_to be_present
end
end
@@ -1078,7 +1099,7 @@ describe User, :type => :model do
end
it "#flags user for removal" do
- remove_at = Time.now+5.days
+ remove_at = Time.now.change(usec: 0).utc + 5.days
@user.flag_for_removal(remove_at)
expect(@user.remove_after).to eq(remove_at)
end
diff --git a/spec/presenters/avatar_presenter_spec.rb b/spec/presenters/avatar_presenter_spec.rb
index 0a7daea6a..f51b4ef83 100644
--- a/spec/presenters/avatar_presenter_spec.rb
+++ b/spec/presenters/avatar_presenter_spec.rb
@@ -10,11 +10,10 @@ describe AvatarPresenter do
it "returns the default images if no images set" do
@profile = FactoryGirl.create(:profile, person: alice.person)
@presenter = AvatarPresenter.new(@profile)
- expect(@presenter.base_hash).to eq(
- small: "/assets/user/default.png",
- medium: "/assets/user/default.png",
- large: "/assets/user/default.png"
- )
+ expect(@presenter.base_hash.keys).to eq(%i[small medium large])
+ expect(@presenter.base_hash[:small]).to match(%r{/assets/user/default-[0-9a-f]{64}\.png})
+ expect(@presenter.base_hash[:medium]).to match(%r{/assets/user/default-[0-9a-f]{64}\.png})
+ expect(@presenter.base_hash[:large]).to match(%r{/assets/user/default-[0-9a-f]{64}\.png})
end
end
end
diff --git a/spec/presenters/o_embed_presenter_spec.rb b/spec/presenters/o_embed_presenter_spec.rb
index 9a14a5e7a..55c19a80e 100644
--- a/spec/presenters/o_embed_presenter_spec.rb
+++ b/spec/presenters/o_embed_presenter_spec.rb
@@ -17,7 +17,7 @@ describe OEmbedPresenter do
describe '#iframe_html' do
it 'passes the height options to post_iframe_url' do
- expect(@oembed).to receive(:post_iframe_url).with(instance_of(Fixnum), instance_of(Hash))
+ expect(@oembed).to receive(:post_iframe_url).with(kind_of(Integer), instance_of(Hash))
@oembed.iframe_html
end
end
@@ -31,4 +31,4 @@ describe OEmbedPresenter do
expect(OEmbedPresenter.id_from_url('http://localhost:400/p/1')).to eq("1")
end
end
-end \ No newline at end of file
+end
diff --git a/spec/presenters/post_ineraction_presenter_spec.rb b/spec/presenters/post_interaction_presenter_spec.rb
index c7306a37a..c7306a37a 100644
--- a/spec/presenters/post_ineraction_presenter_spec.rb
+++ b/spec/presenters/post_interaction_presenter_spec.rb
diff --git a/spec/presenters/post_presenter_spec.rb b/spec/presenters/post_presenter_spec.rb
index 0c2a5c993..4110cedeb 100644
--- a/spec/presenters/post_presenter_spec.rb
+++ b/spec/presenters/post_presenter_spec.rb
@@ -1,44 +1,93 @@
describe PostPresenter do
- before do
- @sm = FactoryGirl.create(:status_message, public: true)
- @sm_with_poll = FactoryGirl.create(:status_message_with_poll, public: true)
- @presenter = PostPresenter.new(@sm, bob)
- @unauthenticated_presenter = PostPresenter.new(@sm)
- end
+ let(:status_message) { FactoryGirl.create(:status_message, public: true) }
+ let(:status_message_with_poll) { FactoryGirl.create(:status_message_with_poll, public: true) }
+ let(:presenter) { PostPresenter.new(status_message, bob) }
+ let(:unauthenticated_presenter) { PostPresenter.new(status_message) }
it "takes a post and an optional user" do
- expect(@presenter).not_to be_nil
+ expect(presenter).not_to be_nil
end
describe "#as_json" do
it "works with a user" do
- expect(@presenter.as_json).to be_a Hash
+ expect(presenter.as_json).to be_a Hash
end
it "works without a user" do
- expect(@unauthenticated_presenter.as_json).to be_a Hash
+ expect(unauthenticated_presenter.as_json).to be_a Hash
+ end
+ end
+
+ context "post with interactions" do
+ before do
+ bob.like!(status_message)
+ bob.reshare!(status_message)
+ end
+
+ describe "#with_interactions" do
+ it "works with a user" do
+ post_hash = presenter.with_interactions
+ expect(post_hash).to be_a Hash
+ expect(post_hash[:interactions]).to eq PostInteractionPresenter.new(status_message, bob).as_json
+ end
+
+ it "works without a user" do
+ post_hash = unauthenticated_presenter.with_interactions
+ expect(post_hash).to be_a Hash
+ expect(post_hash[:interactions]).to eq PostInteractionPresenter.new(status_message, nil).as_json
+ end
+ end
+
+ describe "#with_initial_interactions" do
+ it "works with a user" do
+ post_hash = presenter.with_initial_interactions
+ expect(post_hash).to be_a Hash
+ expect(post_hash[:interactions][:likes]).to eq(
+ LikeService.new(bob).find_for_post(status_message.id).as_api_response(:backbone)
+ )
+ expect(post_hash[:interactions][:reshares]).to eq(
+ ReshareService.new(bob).find_for_post(status_message.id).as_api_response(:backbone)
+ )
+ end
+
+ it "works without a user" do
+ post_hash = unauthenticated_presenter.with_initial_interactions
+ expect(post_hash).to be_a Hash
+ expect(post_hash[:interactions][:likes]).to eq(
+ LikeService.new.find_for_post(status_message.id).as_api_response(:backbone)
+ )
+ expect(post_hash[:interactions][:reshares]).to eq(
+ ReshareService.new.find_for_post(status_message.id).as_api_response(:backbone)
+ )
+ end
end
end
describe "#user_like" do
+ before do
+ bob.like!(status_message)
+ end
+
it "includes the users like" do
- bob.like!(@sm)
- expect(@presenter.send(:user_like)).to be_present
+ expect(presenter.send(:user_like)).to be_present
end
it "is nil if the user is not authenticated" do
- expect(@unauthenticated_presenter.send(:user_like)).to be_nil
+ expect(unauthenticated_presenter.send(:user_like)).to be_nil
end
end
describe "#user_reshare" do
+ before do
+ bob.reshare!(status_message)
+ end
+
it "includes the users reshare" do
- bob.reshare!(@sm)
- expect(@presenter.send(:user_reshare)).to be_present
+ expect(presenter.send(:user_reshare)).to be_present
end
it "is nil if the user is not authenticated" do
- expect(@unauthenticated_presenter.send(:user_reshare)).to be_nil
+ expect(unauthenticated_presenter.send(:user_reshare)).to be_nil
end
end
@@ -67,23 +116,23 @@ describe PostPresenter do
it "delegates to message.title" do
message = double(present?: true)
expect(message).to receive(:title)
- @presenter.post = double(message: message)
- @presenter.send(:title)
+ presenter.post = double(message: message)
+ presenter.send(:title)
end
end
context "with posts without text" do
it "displays a messaage with the post class" do
- @sm = double(message: double(present?: false), author: bob.person, author_name: bob.person.name)
- @presenter.post = @sm
- expect(@presenter.send(:title)).to eq("A post from #{@sm.author.name}")
+ sm = double(message: double(present?: false), author: bob.person, author_name: bob.person.name)
+ presenter.post = sm
+ expect(presenter.send(:title)).to eq("A post from #{sm.author.name}")
end
end
end
describe "#poll" do
it "works without a user" do
- presenter = PostPresenter.new(@sm_with_poll)
+ presenter = PostPresenter.new(status_message_with_poll)
expect(presenter.as_json).to be_a(Hash)
end
end
@@ -126,23 +175,23 @@ describe PostPresenter do
it "does not raise if the root of a reshare does not exist anymore" do
reshare = FactoryGirl.create(:reshare)
- reshare.root = nil
+ reshare.update(root: nil)
- expect(PostPresenter.new(reshare).send(:description)).to eq(nil)
+ expect(PostPresenter.new(Post.find(reshare.id)).send(:description)).to eq(nil)
end
end
describe "#build_open_graph_cache" do
it "returns a dummy og cache if the og cache is missing" do
- expect(@presenter.build_open_graph_cache.image).to be_nil
+ expect(presenter.build_open_graph_cache.image).to be_nil
end
context "with an open graph cache" do
it "delegates to as_api_response" do
og_cache = double("open_graph_cache")
expect(og_cache).to receive(:as_api_response).with(:backbone)
- @presenter.post = double(open_graph_cache: og_cache)
- @presenter.send(:build_open_graph_cache)
+ presenter.post = double(open_graph_cache: og_cache)
+ presenter.send(:build_open_graph_cache)
end
it "returns the open graph cache data" do
diff --git a/spec/presenters/statistics_presenter_spec.rb b/spec/presenters/statistics_presenter_spec.rb
deleted file mode 100644
index b0d1143e8..000000000
--- a/spec/presenters/statistics_presenter_spec.rb
+++ /dev/null
@@ -1,110 +0,0 @@
-describe StatisticsPresenter do
- before do
- @presenter = StatisticsPresenter.new
- end
-
- describe "#as_json" do
- it "works" do
- expect(@presenter.as_json).to be_present
- expect(@presenter.as_json).to be_a Hash
- end
- end
-
- describe "#statistics contents" do
- before do
- AppConfig.privacy.statistics.user_counts = false
- AppConfig.privacy.statistics.post_counts = false
- AppConfig.privacy.statistics.comment_counts = false
- end
-
- it "provides generic pod data in json" do
- expect(@presenter.as_json).to eq(
- "name" => AppConfig.settings.pod_name,
- "network" => "Diaspora",
- "version" => AppConfig.version_string,
- "registrations_open" => AppConfig.settings.enable_registrations?,
- "services" => AppConfig.configured_services.map(&:to_s)
- )
- end
-
- context "when services are enabled" do
- before do
- AppConfig.services = {
- "facebook" => {
- "enable" => true,
- "authorized" => true
- },
- "twitter" => {"enable" => true},
- "wordpress" => {"enable" => false},
- "tumblr" => {
- "enable" => true,
- "authorized" => false
- }
- }
- end
-
- it "provides services in json" do
- expect(@presenter.as_json).to eq(
- "name" => AppConfig.settings.pod_name,
- "network" => "Diaspora",
- "version" => AppConfig.version_string,
- "registrations_open" => AppConfig.settings.enable_registrations?,
- "services" => %w(twitter facebook)
- )
- end
- end
-
- context "when some services are set to username authorized" do
- before do
- AppConfig.services = {
- "facebook" => {
- "enable" => true,
- "authorized" => "bob"
- },
- "twitter" => {"enable" => true},
- "wordpress" => {
- "enable" => true,
- "authorized" => "alice"
- },
- "tumblr" => {
- "enable" => true,
- "authorized" => false
- }
- }
- end
-
- it "provides services in json" do
- expect(@presenter.as_json).to eq(
- "name" => AppConfig.settings.pod_name,
- "network" => "Diaspora",
- "version" => AppConfig.version_string,
- "registrations_open" => AppConfig.settings.enable_registrations?,
- "services" => ["twitter"]
- )
- end
- end
-
- context "when counts are enabled" do
- before do
- AppConfig.privacy.statistics.user_counts = true
- AppConfig.privacy.statistics.post_counts = true
- AppConfig.privacy.statistics.comment_counts = true
- end
-
- it "provides generic pod data and counts in json" do
- expect(@presenter.as_json).to eq(
- "name" => AppConfig.settings.pod_name,
- "network" => "Diaspora",
- "version" => AppConfig.version_string,
- "registrations_open" => AppConfig.settings.enable_registrations?,
- "total_users" => User.active.count,
- "active_users_halfyear" => User.halfyear_actives.count,
- "active_users_monthly" => User.monthly_actives.count,
- "local_posts" => @presenter.local_posts,
- "local_comments" => @presenter.local_comments,
- "services" => AppConfig.configured_services.map(&:to_s)
- )
- end
- end
- end
-end
diff --git a/spec/serializers/comment_serializer_spec.rb b/spec/serializers/comment_serializer_spec.rb
deleted file mode 100644
index 42ec79b77..000000000
--- a/spec/serializers/comment_serializer_spec.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-describe Export::CommentSerializer do
- let(:comment) { create(:comment) }
- subject(:json_output) { Export::CommentSerializer.new(comment).to_json }
-
- it { is_expected.to include %("guid":"#{comment.guid}") }
- it { is_expected.to include %("post_guid":"#{comment.post.guid}") }
- it { is_expected.to include %("text":"#{comment.text}") }
-end
diff --git a/spec/serializers/export/aspect_serializer_spec.rb b/spec/serializers/export/aspect_serializer_spec.rb
new file mode 100644
index 000000000..bc3399757
--- /dev/null
+++ b/spec/serializers/export/aspect_serializer_spec.rb
@@ -0,0 +1,12 @@
+describe Export::AspectSerializer do
+ let(:aspect) { FactoryGirl.create(:aspect) }
+ let(:serializer) { Export::AspectSerializer.new(aspect) }
+
+ it "has aspect attributes" do
+ expect(serializer.attributes).to eq(
+ name: aspect.name,
+ contacts_visible: aspect.contacts_visible,
+ chat_enabled: aspect.chat_enabled
+ )
+ end
+end
diff --git a/spec/serializers/export/contact_serializer_spec.rb b/spec/serializers/export/contact_serializer_spec.rb
new file mode 100644
index 000000000..c2578e647
--- /dev/null
+++ b/spec/serializers/export/contact_serializer_spec.rb
@@ -0,0 +1,25 @@
+describe Export::ContactSerializer do
+ let(:contact) { FactoryGirl.create(:contact) }
+ let(:serializer) { Export::ContactSerializer.new(contact) }
+ let(:aspect) { FactoryGirl.create(:aspect) }
+
+ it "has contact attributes" do
+ expect(serializer.attributes).to eq(
+ sharing: contact.sharing,
+ following: contact.sharing,
+ receiving: contact.receiving,
+ followed: contact.receiving,
+ person_guid: contact.person_guid,
+ person_name: contact.person_name,
+ account_id: contact.person_diaspora_handle,
+ public_key: contact.person.serialized_public_key
+ )
+ end
+
+ it "serializes aspects membership" do
+ contact.aspects << aspect
+ expect(Export::ContactSerializer).to serialize_association(:contact_groups_membership)
+ .with_objects(contact.aspects.map(&:name))
+ expect(serializer.associations[:contact_groups_membership]).to eq([aspect.name])
+ end
+end
diff --git a/spec/serializers/export/others_data_serializer_spec.rb b/spec/serializers/export/others_data_serializer_spec.rb
new file mode 100644
index 000000000..81d9be478
--- /dev/null
+++ b/spec/serializers/export/others_data_serializer_spec.rb
@@ -0,0 +1,43 @@
+describe Export::OthersDataSerializer do
+ let(:user) { FactoryGirl.create(:user) }
+ let(:serializer) { Export::OthersDataSerializer.new(user) }
+ let(:others_posts) {
+ [
+ *user.person.likes.map(&:target),
+ *user.person.comments.map(&:parent),
+ *user.person.posts.reshares.map(&:root),
+ *user.person.poll_participations.map(&:status_message)
+ ]
+ }
+
+ it "uses FederationEntitySerializer for array serializing relayables" do
+ sm = DataGenerator.new(user).status_message_with_activity
+
+ expect(Export::OthersDataSerializer).to serialize_association(:relayables)
+ .with_each_serializer(FederationEntitySerializer)
+ .with_objects([*sm.likes, *sm.comments, *sm.poll_participations])
+ serializer.associations
+ end
+
+ context "with user's activity" do
+ before do
+ DataGenerator.new(user).activity
+ end
+
+ it "uses FederationEntitySerializer for array serializing posts" do
+ expect(Export::OthersDataSerializer).to serialize_association(:posts)
+ .with_each_serializer(FederationEntitySerializer)
+ .with_objects(others_posts)
+ serializer.associations
+ end
+
+ it "uses PersonMetadataSerializer for array serializing non_contact_authors" do
+ non_contact_authors = others_posts.map(&:author)
+
+ expect(Export::OthersDataSerializer).to serialize_association(:non_contact_authors)
+ .with_each_serializer(Export::PersonMetadataSerializer)
+ .with_objects(non_contact_authors)
+ serializer.associations
+ end
+ end
+end
diff --git a/spec/serializers/export/own_post_serializer_spec.rb b/spec/serializers/export/own_post_serializer_spec.rb
new file mode 100644
index 000000000..91228ccf8
--- /dev/null
+++ b/spec/serializers/export/own_post_serializer_spec.rb
@@ -0,0 +1,48 @@
+describe Export::OwnPostSerializer do
+ let(:author) { FactoryGirl.create(:user_with_aspect).person }
+
+ before do
+ author.owner.share_with(FactoryGirl.create(:person), author.owner.aspects.first)
+ end
+
+ it_behaves_like "a federation entity serializer" do
+ let(:object) { create(:status_message_with_photo, author: author) }
+ end
+
+ let(:json) { Export::OwnPostSerializer.new(post, root: false).to_json }
+
+ context "with private post" do
+ let(:post) { create(:status_message_in_aspect, author: author) }
+
+ it "includes remote people subscriptions" do
+ expect(JSON.parse(json)["subscribed_users_ids"]).not_to be_empty
+ expect(json).to include_json(subscribed_users_ids: post.subscribers.map(&:diaspora_handle))
+ end
+
+ it "doesn't include remote pods subscriptions" do
+ expect(JSON.parse(json)).not_to have_key("subscribed_pods_uris")
+ end
+ end
+
+ context "with public post" do
+ let(:post) {
+ FactoryGirl.create(
+ :status_message_with_participations,
+ author: author,
+ participants: Array.new(2) { FactoryGirl.create(:person) },
+ public: true
+ )
+ }
+
+ it "includes pods subscriptions" do
+ expect(JSON.parse(json)["subscribed_pods_uris"]).not_to be_empty
+ expect(json).to include_json(
+ subscribed_pods_uris: post.subscribed_pods_uris.push(AppConfig.pod_uri.to_s)
+ )
+ end
+
+ it "doesn't include remote people subscriptions" do
+ expect(JSON.parse(json)).not_to have_key("subscribed_users_ids")
+ end
+ end
+end
diff --git a/spec/serializers/export/own_relayables_serializer_spec.rb b/spec/serializers/export/own_relayables_serializer_spec.rb
new file mode 100644
index 000000000..9906cdf9b
--- /dev/null
+++ b/spec/serializers/export/own_relayables_serializer_spec.rb
@@ -0,0 +1,9 @@
+describe Export::OwnRelayablesSerializer do
+ let(:comment) { FactoryGirl.create(:comment) }
+ let!(:signature) { FactoryGirl.create(:comment_signature, comment: comment) }
+ let(:instance) { Export::OwnRelayablesSerializer.new(comment, root: false) }
+
+ it "doesn't include author signature to the entity data" do
+ expect(JSON.parse(instance.to_json)["entity_data"]).not_to have_key("author_signature")
+ end
+end
diff --git a/spec/serializers/export/person_metadata_serializer_spec.rb b/spec/serializers/export/person_metadata_serializer_spec.rb
new file mode 100644
index 000000000..d284c303e
--- /dev/null
+++ b/spec/serializers/export/person_metadata_serializer_spec.rb
@@ -0,0 +1,12 @@
+describe Export::PersonMetadataSerializer do
+ let(:person) { FactoryGirl.create(:person) }
+ let(:serializer) { Export::PersonMetadataSerializer.new(person) }
+
+ it "has person metadata attributes" do
+ expect(serializer.attributes).to eq(
+ guid: person.guid,
+ account_id: person.diaspora_handle,
+ public_key: person.serialized_public_key
+ )
+ end
+end
diff --git a/spec/serializers/export/user_serializer_spec.rb b/spec/serializers/export/user_serializer_spec.rb
new file mode 100644
index 000000000..e5022e5fd
--- /dev/null
+++ b/spec/serializers/export/user_serializer_spec.rb
@@ -0,0 +1,79 @@
+describe Export::UserSerializer do
+ let(:user) { FactoryGirl.create(:user) }
+ let(:serializer) { Export::UserSerializer.new(user, root: false) }
+
+ it "has basic user's attributes" do
+ expect(serializer.attributes).to eq(
+ username: user.username,
+ email: user.email,
+ language: user.language,
+ private_key: user.serialized_private_key,
+ disable_mail: user.disable_mail,
+ show_community_spotlight_in_stream: user.show_community_spotlight_in_stream,
+ auto_follow_back: user.auto_follow_back,
+ auto_follow_back_aspect: user.auto_follow_back_aspect,
+ strip_exif: user.strip_exif
+ )
+ end
+
+ it "uses FederationEntitySerializer to serialize user profile" do
+ expect(Export::UserSerializer).to serialize_association(:profile)
+ .with_serializer(FederationEntitySerializer)
+ .with_object(user.profile)
+ serializer.associations
+ end
+
+ it "uses AspectSerializer for array serializing contact_groups" do
+ DataGenerator.create(user, %i[first_aspect work_aspect])
+ expect(Export::UserSerializer).to serialize_association(:contact_groups)
+ .with_each_serializer(Export::AspectSerializer)
+ .with_objects([user.aspects.first, user.aspects.second])
+ serializer.associations
+ end
+
+ it "uses ContactSerializer for array serializing contacts" do
+ DataGenerator.create(user, %i[mutual_friend mutual_friend])
+ expect(Export::UserSerializer).to serialize_association(:contacts)
+ .with_each_serializer(Export::ContactSerializer)
+ .with_objects([user.contacts.first, user.contacts.second])
+ serializer.associations
+ end
+
+ it "uses OwnPostSerializer for array serializing posts" do
+ DataGenerator.create(user, %i[public_status_message private_status_message])
+ expect(Export::UserSerializer).to serialize_association(:posts)
+ .with_each_serializer(Export::OwnPostSerializer)
+ .with_objects([user.posts.first, user.posts.second])
+ serializer.associations
+ end
+
+ it "serializes followed tags" do
+ DataGenerator.create(user, %i[tag_following tag_following])
+ expect(Export::UserSerializer).to serialize_association(:followed_tags)
+ .with_objects([user.followed_tags.first.name, user.followed_tags.second.name])
+ serializer.associations
+ end
+
+ it "uses OwnRelayablesSerializer for array serializing relayables" do
+ DataGenerator.create(user, :activity)
+
+ objects = %i[comments likes poll_participations].map do |association|
+ user.person.send(association).first
+ end
+
+ expect(Export::UserSerializer).to serialize_association(:relayables)
+ .with_each_serializer(Export::OwnRelayablesSerializer)
+ .with_objects(objects)
+ serializer.associations
+ end
+
+ it "serializes post subscriptions" do
+ DataGenerator.create(user, %i[participation participation])
+ subscriptions = user.person.participations.map do |participation|
+ participation.target.guid
+ end
+ expect(Export::UserSerializer).to serialize_association(:post_subscriptions)
+ .with_objects(subscriptions)
+ serializer.associations
+ end
+end
diff --git a/spec/serializers/federation_entity_serializer_spec.rb b/spec/serializers/federation_entity_serializer_spec.rb
new file mode 100644
index 000000000..7dcbd3bdf
--- /dev/null
+++ b/spec/serializers/federation_entity_serializer_spec.rb
@@ -0,0 +1,17 @@
+describe FederationEntitySerializer do
+ class TestEntity < DiasporaFederation::Entity
+ property :test, :string
+ end
+
+ let(:object) { double }
+
+ before do
+ # Mock a builder for a TestEntity that we define for this test
+ allow(Diaspora::Federation::Mappings).to receive(:builder_for).with(object.class).and_return(:test_entity)
+ allow(Diaspora::Federation::Entities).to receive(:test_entity).with(object) {
+ TestEntity.new(test: "asdf")
+ }
+ end
+
+ it_behaves_like "a federation entity serializer"
+end
diff --git a/spec/serializers/notification_serializer_spec.rb b/spec/serializers/notification_serializer_spec.rb
index 8f9a20a3c..156dc5ee5 100644
--- a/spec/serializers/notification_serializer_spec.rb
+++ b/spec/serializers/notification_serializer_spec.rb
@@ -3,7 +3,7 @@ describe NotificationSerializer do
before do
allow(notifications_controller).to receive(:current_user).and_return(notification.recipient)
- notifications_controller.request = ActionController::TestRequest.new(host: AppConfig.pod_uri)
+ notifications_controller.request = ActionDispatch::TestRequest.new(host: AppConfig.pod_uri)
end
let(:notification) { FactoryGirl.create(:notification) }
diff --git a/spec/serializers/post_serializer_spec.rb b/spec/serializers/post_serializer_spec.rb
deleted file mode 100644
index c96d42458..000000000
--- a/spec/serializers/post_serializer_spec.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-describe Export::PostSerializer do
- let(:post) { create(:status_message_with_photo) }
- subject(:json_output) { Export::PostSerializer.new(post).to_json }
-
- it { is_expected.to include %("guid":"#{post.guid}") }
- it { is_expected.to include %("text":"#{post.text}") }
- it { is_expected.to include %("public":#{post.public}) }
- it { is_expected.to include %("diaspora_handle":"#{post.diaspora_handle}") }
- it { is_expected.to include %("type":"#{post.type}") }
- it { is_expected.to include %("likes_count":#{post.likes_count}) }
- it { is_expected.to include %("comments_count":#{post.comments_count}) }
- it { is_expected.to include %("reshares_count":#{post.reshares_count}) }
- it { is_expected.to include %("created_at":"#{post.created_at.to_s[0, 4]}) }
- it { is_expected.to include %("created_at":"#{post.created_at.strftime('%FT%T.%LZ')}) }
-end
diff --git a/spec/serializers/serializer_post_processing_spec.rb b/spec/serializers/serializer_post_processing_spec.rb
new file mode 100644
index 000000000..8cb140fd6
--- /dev/null
+++ b/spec/serializers/serializer_post_processing_spec.rb
@@ -0,0 +1,33 @@
+describe SerializerPostProcessing do
+ describe "#modify_serializable_object" do
+ it "allows to modify serializable object of ActiveModel::Serializer ancestor" do
+ class TestSerializer < ActiveModel::Serializer
+ include SerializerPostProcessing
+
+ def modify_serializable_object(*)
+ {
+ custom_key: "custom_value"
+ }
+ end
+ end
+
+ serializer = TestSerializer.new({}, root: false)
+ expect(serializer).to receive(:modify_serializable_object).and_call_original
+ expect(serializer.to_json).to eq("{\"custom_key\":\"custom_value\"}")
+ end
+ end
+
+ describe "#except" do
+ it "allows to except a key from attributes" do
+ class TestSerializer2 < ActiveModel::Serializer
+ include SerializerPostProcessing
+
+ attributes :key_to_exclude
+ end
+
+ serializer = TestSerializer2.new({}, root: false)
+ serializer.except = [:key_to_exclude]
+ expect(serializer.to_json).to eq("{}")
+ end
+ end
+end
diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb
new file mode 100644
index 000000000..8ef4bec5d
--- /dev/null
+++ b/spec/services/notification_service_spec.rb
@@ -0,0 +1,74 @@
+describe NotificationService do
+ describe "notification interrelation" do
+ context "with mention in comment" do
+ let(:status_message) {
+ FactoryGirl.create(:status_message, public: true, author: alice.person).tap {|status_message|
+ eve.comment!(status_message, "whatever")
+ }
+ }
+
+ let(:comment) {
+ FactoryGirl.create(
+ :comment,
+ author: bob.person,
+ text: text_mentioning(alice, eve),
+ post: status_message
+ )
+ }
+
+ it "sends only mention notification" do
+ [alice, eve].each do |user|
+ expect(Workers::Mail::MentionedInComment).to receive(:perform_async).with(
+ user.id,
+ bob.person.id,
+ *comment.mentions.where(person: user.person).ids
+ )
+ end
+
+ expect {
+ NotificationService.new.notify(comment, [])
+ }.to change { Notification.where(recipient_id: alice).count }.by(1)
+ .and change { Notification.where(recipient_id: eve).count }.by(1)
+
+ [alice, eve].each do |user|
+ expect(
+ Notifications::MentionedInComment.where(target: comment.mentions, recipient_id: user.id)
+ ).to exist
+
+ expect(
+ Notifications::CommentOnPost.where(target: comment.parent, recipient_id: user.id)
+ ).not_to exist
+
+ expect(
+ Notifications::AlsoCommented.where(target: comment.parent, recipient_id: user.id)
+ ).not_to exist
+ end
+ end
+
+ context "with \"mentioned in comment\" email turned off" do
+ before do
+ alice.user_preferences.create(email_type: "mentioned_in_comment")
+ eve.user_preferences.create(email_type: "mentioned_in_comment")
+ end
+
+ it "calls appropriate mail worker instead" do
+ expect(Workers::Mail::MentionedInComment).not_to receive(:perform_async)
+
+ expect(Workers::Mail::CommentOnPost).to receive(:perform_async).with(
+ alice.id,
+ bob.person.id,
+ *comment.mentions.where(person: alice.person).ids
+ )
+
+ expect(Workers::Mail::AlsoCommented).to receive(:perform_async).with(
+ eve.id,
+ bob.person.id,
+ *comment.mentions.where(person: eve.person).ids
+ )
+
+ NotificationService.new.notify(comment, [])
+ end
+ end
+ end
+ end
+end
diff --git a/spec/services/post_service_spec.rb b/spec/services/post_service_spec.rb
index 3d6b96a48..5dd889b72 100644
--- a/spec/services/post_service_spec.rb
+++ b/spec/services/post_service_spec.rb
@@ -111,6 +111,8 @@ describe PostService do
end
describe "#mark_user_notifications" do
+ let(:status_text) { text_mentioning(alice) }
+
it "marks a corresponding notifications as read" do
FactoryGirl.create(:notification, recipient: alice, target: post, unread: true)
FactoryGirl.create(:notification, recipient: alice, target: post, unread: true)
@@ -121,7 +123,6 @@ describe PostService do
end
it "marks a corresponding mention notification as read" do
- status_text = "this is a text mentioning @{Mention User ; #{alice.diaspora_handle}} ... have fun testing!"
mention_post = bob.post(:status_message, text: status_text, public: true)
expect {
@@ -129,6 +130,16 @@ describe PostService do
}.to change(Notification.where(unread: true), :count).by(-1)
end
+ it "marks a corresponding mention in comment notification as read" do
+ notification = FactoryGirl.create(:notification_mentioned_in_comment)
+ status_message = notification.target.mentions_container.parent
+ user = notification.recipient
+
+ expect {
+ PostService.new(user).mark_user_notifications(status_message.id)
+ }.to change(Notification.where(unread: true), :count).by(-1)
+ end
+
it "does not change the update_at date/time for post notifications" do
notification = Timecop.travel(1.minute.ago) do
FactoryGirl.create(:notification, recipient: alice, target: post, unread: true)
@@ -140,7 +151,6 @@ describe PostService do
end
it "does not change the update_at date/time for mention notifications" do
- status_text = "this is a text mentioning @{Mention User ; #{alice.diaspora_handle}} ... have fun testing!"
mention_post = Timecop.travel(1.minute.ago) do
bob.post(:status_message, text: status_text, public: true)
end
@@ -183,4 +193,222 @@ describe PostService do
expect(StatusMessage.find_by_id(post.id)).not_to be_nil
end
end
+
+ describe "#mentionable_in_comment" do
+ describe "semi-integration test" do
+ let(:post_author_attributes) { {first_name: "Ro#{r_str}"} }
+ let(:post_author) { FactoryGirl.create(:person, post_author_attributes) }
+ let(:current_user) { FactoryGirl.create(:user_with_aspect) }
+ let(:post_service) { PostService.new(current_user) }
+
+ shared_context "with commenters and likers" do
+ # randomize ids of the created people so that the test doesn't pass just because of
+ # the id sequence matched against the expected ordering
+ let(:ids) { (1..4).map {|i| Person.maximum(:id) + i }.shuffle }
+
+ before do
+ # in case when post_author has't been instantiated before this context, specify id
+ # in order to avoid id conflict with the people generated here
+ post_author_attributes.merge!(id: ids.max + 1)
+ end
+
+ let!(:commenter1) {
+ FactoryGirl.create(:person, id: ids.shift, first_name: "Ro1#{r_str}").tap {|person|
+ FactoryGirl.create(:comment, author: person, post: post)
+ }
+ }
+
+ let!(:commenter2) {
+ FactoryGirl.create(:person, id: ids.shift, first_name: "Ro2#{r_str}").tap {|person|
+ FactoryGirl.create(:comment, author: person, post: post)
+ }
+ }
+
+ let!(:liker1) {
+ FactoryGirl.create(:person, id: ids.shift, first_name: "Ro1#{r_str}").tap {|person|
+ FactoryGirl.create(:like, author: person, target: post)
+ }
+ }
+
+ let!(:liker2) {
+ FactoryGirl.create(:person, id: ids.shift, first_name: "Ro2#{r_str}").tap {|person|
+ FactoryGirl.create(:like, author: person, target: post)
+ }
+ }
+ end
+
+ shared_context "with a current user's friend" do
+ let!(:current_users_friend) {
+ FactoryGirl.create(:person).tap {|friend|
+ current_user.contacts.create!(
+ person: friend,
+ aspects: [current_user.aspects.first],
+ sharing: true,
+ receiving: true
+ )
+ }
+ }
+ end
+
+ context "with private post" do
+ let(:post) { FactoryGirl.create(:status_message, text: "ohai", author: post_author) }
+
+ context "when the post doesn't have a visibility for the current user" do
+ it "doesn't find a post and raises an exception" do
+ expect {
+ post_service.mentionable_in_comment(post.id, "Ro")
+ }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+ end
+
+ context "when the post has a visibility for the current user" do
+ before do
+ ShareVisibility.batch_import([current_user.id], post)
+ end
+
+ context "with commenters and likers" do
+ include_context "with commenters and likers"
+
+ it "returns mention suggestions in the correct order" do
+ expected_suggestions = [
+ post_author, commenter1, commenter2, liker1, liker2
+ ]
+ expect(post_service.mentionable_in_comment(post.id, "Ro")).to eq(expected_suggestions)
+ end
+ end
+
+ context "with a current user's friend" do
+ include_context "with a current user's friend"
+
+ it "doesn't include a contact" do
+ expect(post_service.mentionable_in_comment(post.id, current_users_friend.first_name)).to be_empty
+ end
+ end
+
+ it "doesn't include a non contact" do
+ expect(post_service.mentionable_in_comment(post.id, eve.person.first_name)).to be_empty
+ end
+ end
+ end
+
+ context "with public post" do
+ let(:post) { FactoryGirl.create(:status_message, text: "ohai", public: true, author: post_author) }
+
+ context "with commenters and likers and with a current user's friend" do
+ include_context "with commenters and likers"
+ include_context "with a current user's friend"
+
+ it "returns mention suggestions in the correct order" do
+ result = post_service.mentionable_in_comment(post.id, "Ro").to_a
+ expect(result.size).to be > 7
+ # participants: post author, comments, likers
+ expect(result[0..4]).to eq([post_author, commenter1, commenter2, liker1, liker2])
+ # contacts
+ expect(result[5]).to eq(current_users_friend)
+ # non-contacts
+ result[6..-1].each {|person|
+ expect(person.contacts.where(user_id: current_user.id)).to be_empty
+ expect(person.profile.first_name).to include("Ro")
+ }
+ end
+
+ it "doesn't include people with non-matching names" do
+ commenter = FactoryGirl.create(:person, first_name: "RRR#{r_str}")
+ FactoryGirl.create(:comment, author: commenter)
+ liker = FactoryGirl.create(:person, first_name: "RRR#{r_str}")
+ FactoryGirl.create(:like, author: liker)
+ friend = FactoryGirl.create(:person, first_name: "RRR#{r_str}")
+ current_user.contacts.create!(
+ person: friend,
+ aspects: [current_user.aspects.first],
+ sharing: true,
+ receiving: true
+ )
+
+ result = post_service.mentionable_in_comment(post.id, "Ro")
+ expect(result).not_to include(commenter)
+ expect(result).not_to include(liker)
+ expect(result).not_to include(friend)
+ end
+ end
+
+ shared_examples "current user can't mention himself" do
+ before do
+ current_user.profile.update(first_name: "Ro#{r_str}")
+ end
+
+ it "doesn't include current user" do
+ expect(post_service.mentionable_in_comment(post.id, "Ro")).not_to include(current_user.person)
+ end
+ end
+
+ context "when current user is a post author" do
+ let(:post_author) { current_user.person }
+
+ include_examples "current user can't mention himself"
+ end
+
+ context "current user is a participant" do
+ before do
+ current_user.like!(post)
+ current_user.comment!(post, "hello")
+ end
+
+ include_examples "current user can't mention himself"
+ end
+
+ context "current user is a stranger matching a search pattern" do
+ include_examples "current user can't mention himself"
+ end
+
+ it "doesn't fail when the post author doesn't match the requested pattern" do
+ expect(post_service.mentionable_in_comment(post.id, "#{r_str}#{r_str}#{r_str}")).to be_empty
+ end
+
+ it "renders a commenter with multiple comments only once" do
+ person = FactoryGirl.create(:person, first_name: "Ro2#{r_str}")
+ 2.times { FactoryGirl.create(:comment, author: person, post: post) }
+ expect(post_service.mentionable_in_comment(post.id, person.first_name).length).to eq(1)
+ end
+ end
+ end
+
+ describe "unit test" do
+ let(:post_service) { PostService.new(alice) }
+
+ before do
+ expect(post_service).to receive(:find!).and_return(post)
+ end
+
+ it "calls Person.allowed_to_be_mentioned_in_a_comment_to" do
+ expect(Person).to receive(:allowed_to_be_mentioned_in_a_comment_to).with(post).and_call_original
+ post_service.mentionable_in_comment(post.id, "whatever")
+ end
+
+ it "calls Person.find_by_substring" do
+ expect(Person).to receive(:find_by_substring).with("whatever").and_call_original
+ post_service.mentionable_in_comment(post.id, "whatever")
+ end
+
+ it "calls Person.sort_for_mention_suggestion" do
+ expect(Person).to receive(:sort_for_mention_suggestion).with(post, alice).and_call_original
+ post_service.mentionable_in_comment(post.id, "whatever")
+ end
+
+ it "calls Person.limit" do
+ 16.times {
+ FactoryGirl.create(:comment, author: FactoryGirl.create(:person, first_name: "Ro#{r_str}"), post: post)
+ }
+ expect(post_service.mentionable_in_comment(post.id, "Ro").length).to eq(15)
+ end
+
+ it "contains a constraint on a current user" do
+ expect(Person).to receive(:allowed_to_be_mentioned_in_a_comment_to) { Person.all }
+ expect(Person).to receive(:find_by_substring) { Person.all }
+ expect(Person).to receive(:sort_for_mention_suggestion) { Person.all }
+ expect(post_service.mentionable_in_comment(post.id, alice.person.first_name))
+ .not_to include(alice.person)
+ end
+ end
+ end
end
diff --git a/spec/services/status_message_creation_service_spec.rb b/spec/services/status_message_creation_service_spec.rb
index 80631f266..47838d172 100644
--- a/spec/services/status_message_creation_service_spec.rb
+++ b/spec/services/status_message_creation_service_spec.rb
@@ -151,44 +151,6 @@ describe StatusMessageCreationService do
end
end
- context "with mentions" do
- let(:mentioned_user) { FactoryGirl.create(:user) }
- let(:text) {
- "Hey @{#{bob.name}; #{bob.diaspora_handle}} and @{#{mentioned_user.name}; #{mentioned_user.diaspora_handle}}!"
- }
-
- it "calls Diaspora::Mentionable#filter_for_aspects for private posts" do
- expect(Diaspora::Mentionable).to receive(:filter_for_aspects).with(text, alice, aspect.id.to_s)
- .and_call_original
- StatusMessageCreationService.new(alice).create(params)
- end
-
- it "keeps mentions for users in one of the aspects" do
- status_message = StatusMessageCreationService.new(alice).create(params)
- expect(status_message.text).to include bob.name
- expect(status_message.text).to include bob.diaspora_handle
- end
-
- it "removes mentions for users in other aspects" do
- status_message = StatusMessageCreationService.new(alice).create(params)
- expect(status_message.text).to include mentioned_user.name
- expect(status_message.text).not_to include mentioned_user.diaspora_handle
- end
-
- it "doesn't call Diaspora::Mentionable#filter_for_aspects for public posts" do
- expect(Diaspora::Mentionable).not_to receive(:filter_for_aspects)
- StatusMessageCreationService.new(alice).create(params.merge(public: true))
- end
-
- it "keeps all mentions in public posts" do
- status_message = StatusMessageCreationService.new(alice).create(params.merge(public: true))
- expect(status_message.text).to include bob.name
- expect(status_message.text).to include bob.diaspora_handle
- expect(status_message.text).to include mentioned_user.name
- expect(status_message.text).to include mentioned_user.diaspora_handle
- end
- end
-
context "dispatch" do
it "dispatches the StatusMessage" do
expect(alice).to receive(:dispatch_post).with(instance_of(StatusMessage), hash_including(service_types: []))
@@ -201,6 +163,16 @@ describe StatusMessageCreationService do
hash_including(service_types: array_including(%w(Services::Facebook Services::Twitter))))
StatusMessageCreationService.new(alice).create(params.merge(services: %w(twitter facebook)))
end
+
+ context "with mention" do
+ let(:text) { text_mentioning(eve) }
+
+ # this is only required until changes from #6818 are deployed on every pod
+ it "filters out mentions from text attribute" do
+ status_message = StatusMessageCreationService.new(alice).create(params)
+ expect(status_message.text).not_to include(eve.diaspora_handle)
+ end
+ end
end
end
end
diff --git a/spec/shared_behaviors/account_deletion.rb b/spec/shared_behaviors/account_deletion.rb
index 48500e0d0..2f7b8f8d9 100644
--- a/spec/shared_behaviors/account_deletion.rb
+++ b/spec/shared_behaviors/account_deletion.rb
@@ -2,32 +2,75 @@
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
-shared_examples_for 'it removes the person associations' do
- it "removes all of the person's posts" do
- expect(Post.where(:author_id => @person.id).count).to eq(0)
- end
+shared_examples_for "deletes all of the user data" do
+ it "deletes all of the user data" do
+ expect(user).not_to be_a_clear_account
- it 'deletes all person contacts' do
- expect(Contact.where(:person_id => @person.id)).to be_empty
- end
+ expect {
+ account_removal_method
+ }.to change(nil, "user preferences empty?") { UserPreference.where(user_id: user.id).empty? }
+ .to(be_truthy)
+ .and(change(nil, "notifications empty?") { Notification.where(recipient_id: user.id).empty? }.to(be_truthy))
+ .and(change(nil, "blocks empty?") { Block.where(user_id: user.id).empty? }.to(be_truthy))
+ .and(change(nil, "services empty?") { Service.where(user_id: user.id).empty? }.to(be_truthy))
+ .and(change(nil, "share visibilities empty?") { ShareVisibility.where(user_id: user.id).empty? }.to(be_truthy))
+ .and(change(nil, "aspects empty?") { user.aspects.empty? }.to(be_truthy))
+ .and(change(nil, "contacts empty?") { user.contacts.empty? }.to(be_truthy))
+ .and(change(nil, "tag followings empty?") { user.tag_followings.empty? }.to(be_truthy))
- it 'deletes all mentions' do
- expect(@person.mentions).to be_empty
+ expect(user.reload).to be_a_clear_account
end
+end
- it "removes all of the person's photos" do
- expect(Photo.where(:author_id => @person.id)).to be_empty
+shared_examples_for "it removes the person associations" do
+ it "removes all of the person associations" do
+ expect {
+ account_removal_method
+ }.to change(nil, "posts empty?") { Post.where(author_id: person.id).empty? }.to(be_truthy)
+ .and(change(nil, "contacts empty?") { Contact.where(person_id: person.id).empty? }.to(be_truthy))
+ .and(change(nil, "mentions empty?") { person.mentions.empty? }.to(be_truthy))
+ .and(change(nil, "photos empty?") { Photo.where(author_id: person.id).empty? }.to(be_truthy))
+ .and(change(nil, "participations empty?") { Participation.where(author_id: person.id).empty? }.to(be_truthy))
+ .and(change(nil, "roles empty?") { Role.where(person_id: person.id).empty? }.to(be_truthy))
+ .and(change(person, :closed_account).to(be_truthy))
+ .and(change(nil, "first name is blank?") { person.profile.first_name.blank? }.to(be_truthy))
+ .and(change(nil, "last name is blank?") { person.profile.last_name.blank? }.to(be_truthy))
+ .and(change(nil, "conversation visibilities empty?") {
+ ConversationVisibility.where(person_id: person.id).empty?
+ }.to(be_truthy))
end
+end
- it 'sets the person object as closed and the profile is cleared' do
- expect(@person.reload.closed_account).to be true
+shared_examples_for "it keeps the person conversations" do
+ RSpec::Matchers.define_negated_matcher :remain, :change
- expect(@person.profile.reload.first_name).to be_blank
- expect(@person.profile.reload.last_name).to be_blank
+ it "remains the person conversations" do
+ expect {
+ account_removal_method
+ }.to remain(nil, "conversations empty?") { Conversation.where(author: person).empty? }
+ .from(be_falsey)
+ .and(remain(nil, "conversation visibilities of other participants empty?") {
+ ConversationVisibility.where(conversation: Conversation.where(author: person)).empty?
+ }.from(be_falsey))
end
+end
+
+shared_examples_for "it removes the person conversations" do
+ it "removes the person conversations" do
+ expect {
+ account_removal_method
+ }.to change(nil, "conversations empty?") { Conversation.where(author: person).empty? }
+ .to(be_truthy)
+ .and(change(nil, "conversation visibilities of other participants empty?") {
+ ConversationVisibility.where(conversation: Conversation.where(author: person)).empty?
+ }.to(be_truthy))
+ end
+end
- it 'deletes only the converersation visibility for the deleted user' do
- expect(ConversationVisibility.where(:person_id => alice.person.id)).not_to be_empty
- expect(ConversationVisibility.where(:person_id => @person.id)).to be_empty
+# In fact this example group if for testing effect of AccountDeleter.tombstone_person_and_profile
+shared_examples_for "it makes account closed and clears profile" do
+ it "" do
+ expect(subject).to be_a_closed_account
+ expect(subject.profile).to be_a_clear_profile
end
end
diff --git a/spec/shared_behaviors/account_migration.rb b/spec/shared_behaviors/account_migration.rb
new file mode 100644
index 000000000..5da2f3b62
--- /dev/null
+++ b/spec/shared_behaviors/account_migration.rb
@@ -0,0 +1,187 @@
+shared_context "with local old user" do
+ let(:old_user) { FactoryGirl.create(:user) }
+ let(:old_person) { old_user.person }
+end
+
+shared_context "with local new user" do
+ let(:new_user) { FactoryGirl.create(:user) }
+ let(:new_person) { new_user.person }
+end
+
+shared_context "with remote old user" do
+ let(:old_user) { remote_user_on_pod_c }
+ let(:old_person) { old_user.person }
+end
+
+shared_context "with remote new user" do
+ let(:new_user) { remote_user_on_pod_b }
+ let(:new_person) { new_user.person }
+end
+
+shared_examples_for "it updates person references" do
+ it "updates contact reference" do
+ contact = FactoryGirl.create(:contact, person: old_person)
+ run_migration
+ expect(contact.reload.person).to eq(new_person)
+ end
+
+ it "updates status message reference" do
+ post = FactoryGirl.create(:status_message, author: old_person)
+ run_migration
+ expect(post.reload.author).to eq(new_person)
+ end
+
+ it "updates reshare reference" do
+ reshare = FactoryGirl.create(:reshare, author: old_person)
+ run_migration
+ expect(reshare.reload.author).to eq(new_person)
+ end
+
+ it "updates photo reference" do
+ photo = FactoryGirl.create(:photo, author: old_person)
+ run_migration
+ expect(photo.reload.author).to eq(new_person)
+ end
+
+ it "updates comment reference" do
+ comment = FactoryGirl.create(:comment, author: old_person)
+ run_migration
+ expect(comment.reload.author).to eq(new_person)
+ end
+
+ it "updates like reference" do
+ like = FactoryGirl.create(:like, author: old_person)
+ run_migration
+ expect(like.reload.author).to eq(new_person)
+ end
+
+ it "updates participations reference" do
+ participation = FactoryGirl.create(:participation, author: old_person)
+ run_migration
+ expect(participation.reload.author).to eq(new_person)
+ end
+
+ it "updates poll participations reference" do
+ poll_participation = FactoryGirl.create(:poll_participation, author: old_person)
+ run_migration
+ expect(poll_participation.reload.author).to eq(new_person)
+ end
+
+ it "updates conversation visibilities reference" do
+ conversation = FactoryGirl.build(:conversation)
+ FactoryGirl.create(:contact, user: old_user, person: conversation.author) if old_person.local?
+ conversation.participants << old_person
+ conversation.save!
+ visibility = ConversationVisibility.find_by(person_id: old_person.id)
+ run_migration
+ expect(visibility.reload.person).to eq(new_person)
+ end
+
+ it "updates message reference" do
+ message = FactoryGirl.create(:message, author: old_person)
+ run_migration
+ expect(message.reload.author).to eq(new_person)
+ end
+
+ it "updates conversation reference" do
+ conversation = FactoryGirl.create(:conversation, author: old_person)
+ run_migration
+ expect(conversation.reload.author).to eq(new_person)
+ end
+
+ it "updates block references" do
+ user = FactoryGirl.create(:user)
+ block = user.blocks.create(person: old_person)
+ run_migration
+ expect(block.reload.person).to eq(new_person)
+ end
+
+ it "updates role reference" do
+ role = FactoryGirl.create(:role, person: old_person)
+ run_migration
+ expect(role.reload.person).to eq(new_person)
+ end
+
+ it "updates notification actors" do
+ notification = FactoryGirl.build(:notification)
+ notification.actors << old_person
+ notification.save!
+ actor = notification.notification_actors.find_by(person_id: old_person.id)
+ run_migration
+ expect(actor.reload.person).to eq(new_person)
+ end
+
+ it "updates mention reference" do
+ mention = FactoryGirl.create(:mention, person: old_person)
+ run_migration
+ expect(mention.reload.person).to eq(new_person)
+ end
+end
+
+shared_examples_for "it updates user references" do
+ it "updates invited users reference" do
+ invited_user = FactoryGirl.create(:user, invited_by: old_user)
+ run_migration
+ expect(invited_user.reload.invited_by).to eq(new_user)
+ end
+
+ it "updates aspect reference" do
+ aspect = FactoryGirl.create(:aspect, user: old_user, name: r_str)
+ run_migration
+ expect(aspect.reload.user).to eq(new_user)
+ end
+
+ it "updates contact reference" do
+ contact = FactoryGirl.create(:contact, user: old_user)
+ run_migration
+ expect(contact.reload.user).to eq(new_user)
+ end
+
+ it "updates services reference" do
+ service = FactoryGirl.create(:service, user: old_user)
+ run_migration
+ expect(service.reload.user).to eq(new_user)
+ end
+
+ it "updates user preference references" do
+ pref = UserPreference.create!(user: old_user, email_type: "also_commented")
+ run_migration
+ expect(pref.reload.user).to eq(new_user)
+ end
+
+ it "updates tag following references" do
+ tag_following = FactoryGirl.create(:tag_following, user: old_user)
+ run_migration
+ expect(tag_following.reload.user).to eq(new_user)
+ end
+
+ it "updates blocks refrences" do
+ block = FactoryGirl.create(:block, user: old_user)
+ run_migration
+ expect(block.reload.user).to eq(new_user)
+ end
+
+ it "updates notification refrences" do
+ notification = FactoryGirl.create(:notification, recipient: old_user)
+ run_migration
+ expect(notification.reload.recipient).to eq(new_user)
+ end
+
+ it "updates report refrences" do
+ report = FactoryGirl.create(:report, user: old_user)
+ run_migration
+ expect(report.reload.user).to eq(new_user)
+ end
+
+ it "updates authorization refrences" do
+ authorization = FactoryGirl.create(:auth_with_read, user: old_user)
+ run_migration
+ expect(authorization.reload.user).to eq(new_user)
+ end
+
+ it "updates share visibility refrences" do
+ share_visibility = FactoryGirl.create(:share_visibility, user: old_user)
+ run_migration
+ expect(share_visibility.reload.user).to eq(new_user)
+ end
+end
diff --git a/spec/shared_behaviors/dispatcher.rb b/spec/shared_behaviors/dispatcher.rb
index 1d87d8c24..b168465d8 100644
--- a/spec/shared_behaviors/dispatcher.rb
+++ b/spec/shared_behaviors/dispatcher.rb
@@ -17,7 +17,7 @@ shared_examples "a dispatcher" do
opts = {service_types: "Services::Twitter", tweet_id: "123"}
expect(Workers::DeletePostFromService).to receive(:perform_async).with(twitter.id, opts)
- retraction = Retraction.for(post, alice)
+ retraction = Retraction.for(post)
Diaspora::Federation::Dispatcher.build(alice, retraction, opts).dispatch
end
@@ -35,7 +35,7 @@ shared_examples "a dispatcher" do
it "does not deliver a Retraction of a Comment to services" do
expect(Workers::DeletePostFromService).not_to receive(:perform_async)
- retraction = Retraction.for(comment, alice)
+ retraction = Retraction.for(comment)
Diaspora::Federation::Dispatcher.build(alice, retraction).dispatch
end
end
diff --git a/spec/shared_behaviors/federation_entity_serializer.rb b/spec/shared_behaviors/federation_entity_serializer.rb
new file mode 100644
index 000000000..ef1505fc4
--- /dev/null
+++ b/spec/shared_behaviors/federation_entity_serializer.rb
@@ -0,0 +1,14 @@
+shared_examples_for "a federation entity serializer" do
+ describe "#to_json" do
+ it "contains JSON serialized entity object" do
+ entity = nil
+ expect(Diaspora::Federation::Entities).to receive(:build)
+ .with(object)
+ .and_wrap_original do |original, object, &block|
+ entity = original.call(object, &block)
+ end
+ json = described_class.new(object, root: false).to_json
+ expect(json).to include_json(entity.to_json)
+ end
+ end
+end
diff --git a/spec/shared_behaviors/mentions_container.rb b/spec/shared_behaviors/mentions_container.rb
new file mode 100644
index 000000000..50e4efdc9
--- /dev/null
+++ b/spec/shared_behaviors/mentions_container.rb
@@ -0,0 +1,61 @@
+shared_examples_for "it is mentions container" do
+ let(:people) { [alice, bob, eve].map(&:person) }
+ let(:test_string) {
+ "@{Raphael; #{people[0].diaspora_handle}} can mention people like @{Ilya; #{people[1].diaspora_handle}}"\
+ "can mention people like @{Daniel; #{people[2].diaspora_handle}}"
+ }
+ let(:target) { FactoryGirl.build(described_class.to_s.underscore.to_sym, text: test_string, author: alice.person) }
+ let(:target_persisted) {
+ target.save!
+ target
+ }
+
+ describe ".before_create" do
+ it "backports mention syntax to old syntax" do
+ text = "mention @{#{people[0].diaspora_handle}} text"
+ expected_text = "mention @{#{people[0].name}; #{people[0].diaspora_handle}} text"
+ obj = FactoryGirl.build(described_class.to_s.underscore.to_sym, text: text, author: alice.person)
+ obj.save
+ expect(obj.text).to eq(expected_text)
+ end
+
+ it "doesn't backport mention syntax if author is not local" do
+ text = "mention @{#{people[0].diaspora_handle}} text"
+ obj = FactoryGirl.build(described_class.to_s.underscore.to_sym, text: text, author: remote_raphael)
+ obj.save
+ expect(obj.text).to eq(text)
+ end
+ end
+
+ describe ".after_create" do
+ it "calls create_mentions" do
+ expect(target).to receive(:create_mentions).and_call_original
+ target.save
+ end
+ end
+
+ describe "#create_mentions" do
+ it "creates a mention for everyone mentioned in the message" do
+ people.each do |person|
+ expect(target.mentions).to receive(:find_or_create_by).with(person_id: person.id)
+ end
+ target.create_mentions
+ end
+
+ it "does not barf if it gets called twice" do
+ expect {
+ target_persisted.create_mentions
+ }.to_not raise_error
+ end
+ end
+
+ describe "#mentioned_people" do
+ it "returns the mentioned people if non-persisted" do
+ expect(target.mentioned_people).to match_array(people)
+ end
+
+ it "returns the mentioned people if persisted" do
+ expect(target_persisted.mentioned_people).to match_array(people)
+ end
+ end
+end
diff --git a/spec/shared_behaviors/shareable.rb b/spec/shared_behaviors/shareable.rb
new file mode 100644
index 000000000..a857ab5a7
--- /dev/null
+++ b/spec/shared_behaviors/shareable.rb
@@ -0,0 +1,18 @@
+shared_examples_for "a shareable" do
+ describe "#subscribed_pods_uris" do
+ let(:pods) { Array.new(3) { FactoryGirl.create(:pod) } }
+ let(:subscribers) {
+ pods.map {|pod|
+ FactoryGirl.create(:person, pod: pod)
+ }
+ }
+ let(:pods_uris) {
+ pods.map {|pod| pod.url_to("") }
+ }
+
+ it "builds pod list basing on subscribers" do
+ expect(object).to receive(:subscribers).and_return(subscribers)
+ expect(object.subscribed_pods_uris).to match_array(pods_uris)
+ end
+ end
+end
diff --git a/spec/shared_behaviors/taggable.rb b/spec/shared_behaviors/taggable.rb
index e7a61fb5f..d6accd6a4 100644
--- a/spec/shared_behaviors/taggable.rb
+++ b/spec/shared_behaviors/taggable.rb
@@ -30,7 +30,7 @@ shared_examples_for "it is taggable" do
it "supports non-ascii characters" do
tag_list.each do |tag|
- expect(@object.tags(true).map(&:name)).to include(tag)
+ expect(@object.tags.reload.map(&:name)).to include(tag)
end
end
diff --git a/spec/spec/data_generator_spec.rb b/spec/spec/data_generator_spec.rb
new file mode 100644
index 000000000..1e2800245
--- /dev/null
+++ b/spec/spec/data_generator_spec.rb
@@ -0,0 +1,58 @@
+RSpec::Matchers.define :have_subscribers do
+ match do |posts|
+ posts.map(&:subscribers).delete_if(&:empty?).any?
+ end
+end
+
+# verifications of data generation (protect us from possible false positives in case of poor data preset)
+describe DataGenerator do
+ let(:user) { FactoryGirl.create(:user) }
+ let(:generator) { DataGenerator.new(user) }
+
+ describe "#generic_user_data" do
+ it "creates different data for user" do
+ generator.generic_user_data
+ expect(user.aspects).not_to be_empty
+ expect(Post.subscribed_by(user)).not_to be_empty
+ expect(Contact.where(user: user).mutual).not_to be_empty
+ end
+ end
+
+ describe "#status_messages_flavours" do
+ let(:user) { FactoryGirl.create(:user_with_aspect) }
+
+ it "creates posts of different types" do
+ expect(generator).to receive(:status_message_with_activity).and_call_original
+ generator.status_messages_flavours
+ expect(user.posts).not_to be_empty
+ expect(user.posts.where(public: true)).to have_subscribers
+ expect(user.posts.where(public: false)).to have_subscribers
+ end
+ end
+
+ describe "#status_message_with_activity" do
+ it "creates a status message where presented all possible types of activity" do
+ status_message = generator.status_message_with_activity
+ expect(status_message.likes).not_to be_empty
+ expect(status_message.comments).not_to be_empty
+ expect(status_message.poll_participations).not_to be_empty
+ end
+ end
+
+ describe "#activity" do
+ it "creates activity of different kinds" do
+ generator.activity
+ expect(user.posts.reshares).not_to be_empty
+ expect(user.person.likes).not_to be_empty
+ expect(user.person.comments).not_to be_empty
+ expect(user.person.poll_participations).not_to be_empty
+ end
+ end
+
+ describe "#status_message_with_subscriber" do
+ it "creates a status message with a subscriber" do
+ subscriber, status_message = DataGenerator.create(user, :status_message_with_subscriber)
+ expect(status_message.subscribers).to eq([subscriber.person])
+ end
+ end
+end
diff --git a/spec/misc_spec.rb b/spec/spec/misc_spec.rb
index 1e9851fa9..494e8a91d 100644
--- a/spec/misc_spec.rb
+++ b/spec/spec/misc_spec.rb
@@ -2,23 +2,23 @@
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
-describe 'making sure the spec runner works' do
- it 'factory creates a user with a person saved' do
+describe "making sure the spec runner works" do
+ it "factory creates a user with a person saved" do
user = FactoryGirl.create(:user)
loaded_user = User.find(user.id)
expect(loaded_user.person.owner_id).to eq(user.id)
end
- describe 'fixtures' do
- it 'loads fixtures' do
+ describe "fixtures" do
+ it "loads fixtures" do
expect(User.count).not_to eq(0)
end
end
describe "#connect_users" do
before do
- @user1 = User.where(:username => 'alice').first
- @user2 = User.where(:username => 'eve').first
+ @user1 = User.where(username: "alice").first
+ @user2 = User.where(username: "eve").first
@aspect1 = @user1.aspects.first
@aspect2 = @user2.aspects.first
@@ -26,7 +26,7 @@ describe 'making sure the spec runner works' do
connect_users(@user1, @aspect1, @user2, @aspect2)
end
- it 'connects the first user to the second' do
+ it "connects the first user to the second" do
contact = @user1.contact_for @user2.person
expect(contact).not_to be_nil
expect(@user1.contacts.reload.include?(contact)).to be true
@@ -34,7 +34,7 @@ describe 'making sure the spec runner works' do
expect(contact.aspects.include?(@aspect1)).to be true
end
- it 'connects the second user to the first' do
+ it "connects the second user to the first" do
contact = @user2.contact_for @user1.person
expect(contact).not_to be_nil
expect(@user2.contacts.reload.include?(contact)).to be true
@@ -42,8 +42,8 @@ describe 'making sure the spec runner works' do
expect(contact.aspects.include?(@aspect2)).to be true
end
- it 'allows posting after running' do
- message = @user1.post(:status_message, :text => "Connection!", :to => @aspect1.id)
+ it "allows posting after running" do
+ message = @user1.post(:status_message, text: "Connection!", to: @aspect1.id)
expect(@user2.reload.visible_shareables(Post)).to include message
end
end
@@ -71,14 +71,18 @@ describe 'making sure the spec runner works' do
describe "#post" do
it "creates a notification with a mention" do
expect {
- alice.post(:status_message, :text => "@{Bob Grimn; #{bob.person.diaspora_handle}} you are silly", :to => alice.aspects.find_by_name('generic'))
+ alice.post(
+ :status_message,
+ text: "@{Bob Grimn; #{bob.person.diaspora_handle}} you are silly",
+ to: alice.aspects.find_by(name: "generic")
+ )
}.to change(Notification, :count).by(1)
end
end
describe "#create_conversation_with_message" do
- it 'creates a conversation and a message' do
- conversation = create_conversation_with_message(alice, bob.person, "Subject", "Hey Bob")
+ it "creates a conversation and a message" do
+ conversation = create_conversation_with_message(alice.person, bob.person, "Subject", "Hey Bob")
expect(conversation.participants).to eq([alice.person, bob.person])
expect(conversation.subject).to eq("Subject")
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 88550f7c0..493ee8b36 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -15,6 +15,7 @@ require "webmock/rspec"
require "factory_girl"
require "sidekiq/testing"
require "shoulda/matchers"
+require "diaspora_federation/schemas"
include HelperMethods
@@ -105,8 +106,6 @@ RSpec.configure do |config|
I18n.locale = :en
stub_request(:post, "https://pubsubhubbub.appspot.com/")
$process_queue = false
- allow(Workers::SendPublic).to receive(:perform_async)
- allow(Workers::SendPrivate).to receive(:perform_async)
end
config.expect_with :rspec do |expect_config|
@@ -133,6 +132,16 @@ RSpec.configure do |config|
end
config.include FactoryGirl::Syntax::Methods
+
+ config.include JSON::SchemaMatchers
+ config.json_schemas[:archive_schema] = "lib/schemas/archive-format.json"
+
+ JSON::Validator.add_schema(
+ JSON::Schema.new(
+ DiasporaFederation::Schemas.federation_entities,
+ Addressable::URI.parse(DiasporaFederation::Schemas::FEDERATION_ENTITIES_URI)
+ )
+ )
end
Shoulda::Matchers.configure do |config|
diff --git a/spec/support/account_matchers.rb b/spec/support/account_matchers.rb
new file mode 100644
index 000000000..758e2b583
--- /dev/null
+++ b/spec/support/account_matchers.rb
@@ -0,0 +1,43 @@
+RSpec::Matchers.define :be_a_discovered_person do
+ match do |person|
+ !Person.by_account_identifier(person.diaspora_handle).nil?
+ end
+end
+
+RSpec::Matchers.define :be_a_closed_account do
+ match(&:closed_account?)
+end
+
+RSpec::Matchers.define :be_a_locked_account do
+ match(&:access_locked?)
+end
+
+RSpec::Matchers.define :be_a_clear_profile do
+ match do |profile|
+ attributes = %i[
+ diaspora_handle first_name last_name image_url image_url_small image_url_medium birthday gender bio
+ location nsfw public_details
+ ].map {|attribute| profile[attribute] }
+
+ profile.taggings.empty? && !profile.searchable && attributes.reject(&:nil?).empty?
+ end
+end
+
+RSpec::Matchers.define :be_a_clear_account do
+ match do |user|
+ attributes = %i[
+ language reset_password_token remember_created_at sign_in_count current_sign_in_at last_sign_in_at
+ current_sign_in_ip last_sign_in_ip invited_by_id authentication_token unconfirmed_email confirm_email_token
+ auto_follow_back auto_follow_back_aspect_id reset_password_sent_at last_seen color_theme
+ ].map {|attribute| user[attribute] }
+
+ user.disable_mail &&
+ user.strip_exif &&
+ !user.getting_started &&
+ !user.show_community_spotlight_in_stream &&
+ !user.post_default_public &&
+ user.email == "deletedaccount_#{user.id}@example.org" &&
+ user.hidden_shareables.empty? &&
+ attributes.reject(&:nil?).empty?
+ end
+end
diff --git a/spec/support/data_generator.rb b/spec/support/data_generator.rb
new file mode 100644
index 000000000..77194201d
--- /dev/null
+++ b/spec/support/data_generator.rb
@@ -0,0 +1,189 @@
+# This is a helper class for tests that is capable of generating different sets of data, which are possibly
+# interrelated.
+class DataGenerator
+ def person
+ @person || user.person
+ end
+
+ def user
+ @user || person.owner
+ end
+
+ def initialize(user_or_person)
+ if user_or_person.is_a? User
+ @user = user_or_person
+ elsif user_or_person.is_a? Person
+ @person = user_or_person
+ else
+ raise ArgumentError
+ end
+ end
+
+ def self.create(user_or_person, type)
+ generator = new(user_or_person)
+ if type.is_a? Symbol
+ generator.send(type)
+ elsif type.is_a? Array
+ type.map {|type|
+ generator.send(type)
+ }
+ end
+ end
+
+ def generic_user_data
+ preferences
+ notifications
+ blocks
+ service
+ private_post_as_receipient
+ tag_following
+ generic_person_data
+ remote_mutual_friend
+ end
+
+ def generic_person_data
+ private_status_message
+ mention
+ photo
+ conversations
+ role
+ participation
+ end
+
+ def preferences
+ %w[mentioned liked reshared].each do |pref|
+ user.user_preferences.create!(email_type: pref)
+ end
+ end
+
+ def notifications
+ FactoryGirl.create(:notification, recipient: user)
+ end
+
+ def conversations
+ a_friend = FactoryGirl.create(:contact, person: person).user.person
+ FactoryGirl.create(:contact, user: user, person: a_friend) unless user.nil?
+ create_conversation_with_message(a_friend, person, "Subject", "Hey #{person.name}")
+ create_conversation_with_message(person, a_friend, "Subject", "Hey #{a_friend.name}")
+ end
+
+ def blocks
+ user.blocks.create!(person: eve.person)
+ eve.blocks.create!(person: person)
+ end
+
+ def service
+ FactoryGirl.create(:service, user: user)
+ end
+
+ def private_post_as_receipient
+ friend = mutual_friend
+ friend.post(
+ :status_message,
+ text: text_mentioning(user),
+ to: friend.aspects.first
+ )
+ end
+
+ def tag_following
+ TagFollowing.create!(tag: random_tag, user: user)
+ end
+
+ def random_tag
+ ActsAsTaggableOn::Tag.create!(name: "partytimeexcellent#{r_str}")
+ end
+
+ def mutual_friend
+ FactoryGirl.create(:user_with_aspect).tap {|friend|
+ connect_users(user, first_aspect, friend, friend.aspects.first)
+ }
+ end
+
+ def remote_mutual_friend
+ FactoryGirl.create(:contact, user: user, sharing: true, receiving: true)
+ end
+
+ def first_aspect
+ user.aspects.first || FactoryGirl.create(:aspect, user: user)
+ end
+
+ def public_status_message
+ FactoryGirl.create(:status_message, author: person, public: true)
+ end
+
+ def private_status_message
+ post = FactoryGirl.create(:status_message, author: person)
+
+ person.contacts.each do |contact|
+ ShareVisibility.create!(user_id: contact.user_id, shareable: post)
+ end
+ end
+
+ %i[photo participation status_message_with_location status_message_with_poll status_message_with_photo
+ status_message status_message_in_aspect reshare like comment poll_participation].each do |factory|
+ define_method factory do
+ FactoryGirl.create(factory, author: person)
+ end
+ end
+
+ alias subscription participation
+
+ %i[mention role].each do |factory|
+ define_method factory do
+ FactoryGirl.create(factory, person: person)
+ end
+ end
+
+ def status_message_with_activity
+ status_message_with_poll.tap {|post|
+ mutual_friend.like!(post)
+ mutual_friend.comment!(post, "1")
+ mutual_friend.participate_in_poll!(post, post.poll.poll_answers.first)
+ }
+ end
+
+ def status_message_with_comment
+ post = status_message_in_aspect
+ [post, mutual_friend.comment!(post, "some text")]
+ end
+
+ def status_message_with_like
+ post = status_message_in_aspect
+ [post, mutual_friend.like!(post)]
+ end
+
+ def status_message_with_poll_participation
+ post = status_message_with_poll
+ [
+ post,
+ mutual_friend.participate_in_poll!(post, post.poll.poll_answers.first)
+ ]
+ end
+
+ def activity
+ reshare
+ like
+ comment
+ poll_participation
+ end
+
+ def work_aspect
+ user.aspects.create(name: "Work", contacts_visible: false)
+ end
+
+ def status_messages_flavours
+ public_status_message
+ status_message_with_location
+ status_message_with_activity
+ status_message_with_photo
+ status_message_with_poll
+ status_message_in_aspect
+ end
+
+ def status_message_with_subscriber
+ [
+ mutual_friend,
+ status_message_in_aspect
+ ]
+ end
+end
diff --git a/spec/support/serializer_matchers.rb b/spec/support/serializer_matchers.rb
new file mode 100644
index 000000000..0d9ec4382
--- /dev/null
+++ b/spec/support/serializer_matchers.rb
@@ -0,0 +1,79 @@
+# This file contains custom RSpec matchers for AMS.
+# NOTE: It was developed for AMS v0.9 and the API might be changed in future, so that should be examined when moving
+# between stable versions of AMS (e.g. 0.9 to 0.10, or 0.9 to a possible 1.0).
+
+# This is a matcher that tests a ActiveModel Serializer derivatives to run a serializer for
+# an association with expected properties and data.
+#
+# This matcher is expected to be used in unit testing of ActiveModel Serializer derivatives.
+#
+# It is mostly a wrapper around RSpec::Mocks::Matchers::Receive matcher with expectations based on
+# ActiveModel::Serializer internal API knowledge.
+# NOTE: this matcher uses knowledge of AMS internals
+RSpec::Matchers.define :serialize_association do |association_name|
+ match do |root_serializer_class|
+ association = fetch_association(root_serializer_class, association_name)
+ execute_receive_matcher_with(association)
+ end
+
+ # Sets expectation for a specific serializer class to be used for has_one association serialization
+ chain :with_serializer, :association_serializer_class
+
+ # Sets expectation for a specific serializer class to be user for has_many association serialization
+ chain :with_each_serializer, :each_serializer_class
+
+ # Sets expectation for actual data to be passed to the serializer of the association
+ chain :with_object, :association_object
+ alias_method :with_objects, :with_object
+
+ private
+
+ # subject is what comes from the expect method argument in usual notation.
+ # So this method is equivalent of calling `expect(subject).to receive(:build_serializer)` but valid within a custom
+ # RSpec matcher's match method.
+ def execute_receive_matcher_with(subject)
+ receive_matcher.matches?(subject)
+ end
+
+ def receive_matcher
+ receive(:build_serializer).and_wrap_original do |original, object, options, &block|
+ with_object_expectation(object)
+
+ original.call(object, options, &block).tap do |serializer|
+ expect(serializer).to be_an_instance_of(serializer_class) unless serializer_class.nil?
+ expect(serializer).to serialize_each_with(each_serializer_class) unless each_serializer_class.nil?
+ end
+ end
+ end
+
+ def with_object_expectation(object)
+ if association_object.is_a?(Array)
+ expect(object).to match_array(association_object)
+ elsif !association_object.nil?
+ expect(object).to eq(association_object)
+ end
+ end
+
+ def fetch_association(serializer_class, association_name)
+ serializer_class._associations[association_name]
+ end
+
+ def serializer_class
+ @serializer_class ||= pick_serializer_class
+ end
+
+ def pick_serializer_class
+ return association_serializer_class unless association_serializer_class.nil?
+ return ActiveModel::ArraySerializer unless each_serializer_class.nil?
+ end
+end
+
+# This serializer tests that ActiveModel::ArraySerializer uses specific serializer for each member object of the array.
+# We could also set a mock expectation on each serializer, but it maybe overly complicated for our present
+# requirements.
+# NOTE: this matcher uses knowledge of AMS internals
+RSpec::Matchers.define :serialize_each_with do |expected|
+ match do |actual|
+ actual.is_a?(ActiveModel::ArraySerializer) && actual.instance_variable_get("@each_serializer") == expected
+ end
+end
diff --git a/spec/support/user_methods.rb b/spec/support/user_methods.rb
index 9b5860809..48fec7aba 100644
--- a/spec/support/user_methods.rb
+++ b/spec/support/user_methods.rb
@@ -2,6 +2,8 @@ class User
alias_method :share_with_original, :share_with
def share_with(*args)
+ disable_send_workers
+
inlined_jobs do
share_with_original(*args)
end
@@ -13,6 +15,8 @@ class User
end
def post(class_name, opts = {})
+ disable_send_workers
+
inlined_jobs do
aspects = self.aspects_from_ids(opts[:to])
@@ -22,11 +26,9 @@ class User
self.aspects.reload
dispatch_opts = {
- url: Rails.application.routes.url_helpers.post_url(
- p,
- host: AppConfig.pod_uri.to_s
- ),
- to: opts[:to]}
+ url: Rails.application.routes.url_helpers.post_url(p, host: AppConfig.pod_uri.to_s),
+ to: opts[:to]
+ }
dispatch_post(p, dispatch_opts)
end
unless opts[:created_at]
@@ -40,4 +42,11 @@ class User
def build_comment(options={})
Comment::Generator.new(self, options.delete(:post), options.delete(:text)).build(options)
end
+
+ def disable_send_workers
+ RSpec.current_example&.example_group_instance&.instance_eval do
+ allow(Workers::SendPrivate).to receive(:perform_async)
+ allow(Workers::SendPublic).to receive(:perform_async)
+ end
+ end
end
diff --git a/spec/workers/mail/csrf_token_fail_spec.rb b/spec/workers/mail/csrf_token_fail_spec.rb
index e57292048..8c94f8663 100644
--- a/spec/workers/mail/csrf_token_fail_spec.rb
+++ b/spec/workers/mail/csrf_token_fail_spec.rb
@@ -3,12 +3,12 @@
# the COPYRIGHT file.
describe Workers::Mail::CsrfTokenFail do
- describe "#perfom" do
+ describe "#perform" do
it "should call .deliver on the notifier object" do
user = alice
mail_double = double
expect(mail_double).to receive(:deliver_now)
- expect(Notifier).to receive(:csrf_token_fail).with(user.id).and_return(mail_double)
+ expect(Notifier).to receive(:send_notification).with("csrf_token_fail", user.id).and_return(mail_double)
Workers::Mail::CsrfTokenFail.new.perform(user.id)
end
diff --git a/spec/workers/mail/liked_spec.rb b/spec/workers/mail/liked_spec.rb
index 8bb31ef0d..7ab94586a 100644
--- a/spec/workers/mail/liked_spec.rb
+++ b/spec/workers/mail/liked_spec.rb
@@ -1,12 +1,13 @@
describe Workers::Mail::Liked do
- describe "#perfom" do
+ describe "#perform" do
it "should call .deliver_now on the notifier object" do
sm = FactoryGirl.build(:status_message, author: bob.person, public: true)
like = FactoryGirl.build(:like, author: alice.person, target: sm)
mail_double = double
expect(mail_double).to receive(:deliver_now)
- expect(Notifier).to receive(:liked).with(bob.id, like.author.id, like.id).and_return(mail_double)
+ expect(Notifier).to receive(:send_notification)
+ .with("liked", bob.id, like.author.id, like.id).and_return(mail_double)
Workers::Mail::Liked.new.perform(bob.id, like.author.id, like.id)
end
@@ -15,7 +16,7 @@ describe Workers::Mail::Liked do
sm = FactoryGirl.build(:status_message, author: bob.person, public: true)
like = FactoryGirl.build(:like, author: alice.person, target: sm)
- expect(Notifier).to receive(:liked).with(bob.id, like.author.id, like.id)
+ expect(Notifier).to receive(:send_notification).with("liked", bob.id, like.author.id, like.id)
.and_raise(ActiveRecord::RecordNotFound.new("Couldn't find Like with 'id'=42"))
Workers::Mail::Liked.new.perform(bob.id, like.author.id, like.id)
@@ -25,7 +26,7 @@ describe Workers::Mail::Liked do
sm = FactoryGirl.build(:status_message, author: bob.person, public: true)
like = FactoryGirl.build(:like, author: alice.person, target: sm)
- expect(Notifier).to receive(:liked).with(bob.id, like.author.id, like.id)
+ expect(Notifier).to receive(:send_notification).with("liked", bob.id, like.author.id, like.id)
.and_raise(ActiveRecord::RecordNotFound.new("Couldn't find Person with 'id'=42"))
expect {
diff --git a/spec/workers/mail/mentioned_spec.rb b/spec/workers/mail/mentioned_spec.rb
index e63a9dfe5..cc06f5d58 100644
--- a/spec/workers/mail/mentioned_spec.rb
+++ b/spec/workers/mail/mentioned_spec.rb
@@ -3,15 +3,16 @@
# the COPYRIGHT file.
describe Workers::Mail::Mentioned do
- describe '#perfom' do
- it 'should call .deliver on the notifier object' do
+ describe "#perform" do
+ it "should call .deliver on the notifier object" do
user = alice
sm = FactoryGirl.build(:status_message)
- m = Mention.new(:person => user.person, :post=> sm)
+ m = Mention.new(person: user.person, mentions_container: sm)
mail_double = double()
expect(mail_double).to receive(:deliver_now)
- expect(Notifier).to receive(:mentioned).with(user.id, sm.author.id, m.id).and_return(mail_double)
+ expect(Notifier).to receive(:send_notification)
+ .with("mentioned", user.id, sm.author.id, m.id).and_return(mail_double)
Workers::Mail::Mentioned.new.perform(user.id, sm.author.id, m.id)
end
diff --git a/spec/workers/mail/private_message_spec.rb b/spec/workers/mail/private_message_spec.rb
index 8722cd211..7b8401986 100644
--- a/spec/workers/mail/private_message_spec.rb
+++ b/spec/workers/mail/private_message_spec.rb
@@ -3,8 +3,8 @@
# the COPYRIGHT file.
describe Workers::Mail::PrivateMessage do
- describe '#perfom_delegate' do
- it 'should call .deliver on the notifier object' do
+ describe "#perform" do
+ it "should call .deliver on the notifier object" do
user1 = alice
user2 = bob
participant_ids = [user1.contacts.first.person.id, user1.person.id]
@@ -17,9 +17,10 @@ describe Workers::Mail::PrivateMessage do
mail_double = double()
expect(mail_double).to receive(:deliver_now)
- expect(Notifier).to receive(:mentioned).with(user2.id, user1.person.id, message.id).and_return(mail_double)
+ expect(Notifier).to receive(:send_notification)
+ .with("private_message", user2.id, user1.person.id, message.id).and_return(mail_double)
- Workers::Mail::Mentioned.new.perform(user2.id, user1.person.id, message.id)
+ Workers::Mail::PrivateMessage.new.perform(user2.id, user1.person.id, message.id)
end
end
end
diff --git a/spec/workers/mail/reshared_spec.rb b/spec/workers/mail/reshared_spec.rb
index fea1eb54d..d1ebd9908 100644
--- a/spec/workers/mail/reshared_spec.rb
+++ b/spec/workers/mail/reshared_spec.rb
@@ -3,14 +3,15 @@
# the COPYRIGHT file.
describe Workers::Mail::Reshared do
- describe '#perfom' do
- it 'should call .deliver on the notifier object' do
+ describe "#perform" do
+ it "should call .deliver on the notifier object" do
sm = FactoryGirl.build(:status_message, :author => bob.person, :public => true)
reshare = FactoryGirl.build(:reshare, :author => alice.person, :root=> sm)
mail_double = double()
expect(mail_double).to receive(:deliver_now)
- expect(Notifier).to receive(:reshared).with(bob.id, reshare.author.id, reshare.id).and_return(mail_double)
+ expect(Notifier).to receive(:send_notification)
+ .with("reshared", bob.id, reshare.author.id, reshare.id).and_return(mail_double)
Workers::Mail::Reshared.new.perform(bob.id, reshare.author.id, reshare.id)
end
diff --git a/spec/workers/send_private_spec.rb b/spec/workers/send_private_spec.rb
index 92765c0a2..e3d9a99bc 100644
--- a/spec/workers/send_private_spec.rb
+++ b/spec/workers/send_private_spec.rb
@@ -23,7 +23,7 @@ describe Workers::SendPrivate do
sender_id, obj_str, targets
).and_return(failing_targets)
expect(Workers::SendPrivate).to receive(:perform_in).with(
- kind_of(Fixnum), sender_id, obj_str, failing_targets, 1
+ kind_of(Integer), sender_id, obj_str, failing_targets, 1
)
Workers::SendPrivate.new.perform(sender_id, obj_str, targets)
diff --git a/spec/workers/send_public_spec.rb b/spec/workers/send_public_spec.rb
index bf34c6501..4f87ddb33 100644
--- a/spec/workers/send_public_spec.rb
+++ b/spec/workers/send_public_spec.rb
@@ -19,7 +19,7 @@ describe Workers::SendPublic do
sender_id, obj_str, urls, xml
).and_return(failing_urls)
expect(Workers::SendPublic).to receive(:perform_in).with(
- kind_of(Fixnum), sender_id, obj_str, failing_urls, xml, 1
+ kind_of(Integer), sender_id, obj_str, failing_urls, xml, 1
)
Workers::SendPublic.new.perform(sender_id, obj_str, urls, xml)