From d5b7a4b116d37e8b87f3ed9ebdc6adf07a088766 Mon Sep 17 00:00:00 2001 From: Sasha Sorokin Date: Fri, 13 Dec 2019 01:50:23 +0700 Subject: Avoid using pluralize on moderation pages (#12589) Pluralize function from Rails framework does not work with other languages than English, moreover it does not even work properly with English [1]. Not that the latest applies to this context, it's just a sign that we best to avoid this function, especially when there are more reliable ways. This commit changes how reports pages generated in order to avoid usage of pluralize function, replacing it with default translation function, called with given counter. On top of that, we have to make strings pluralizable, so have to change locale files. [1]: https://medium.com/@anna7/b3927de2ca8e#6a60 --- app/views/admin/reports/index.html.haml | 2 +- app/views/admin/reports/show.html.haml | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/views/admin/reports/index.html.haml b/app/views/admin/reports/index.html.haml index b09472270..30c7549b0 100644 --- a/app/views/admin/reports/index.html.haml +++ b/app/views/admin/reports/index.html.haml @@ -28,7 +28,7 @@ .report-card__profile = account_link_to target_account, '', size: 36, path: admin_account_path(target_account.id) .report-card__profile__stats - = link_to pluralize(target_account.targeted_moderation_notes.count, t('admin.reports.account.note')), admin_account_path(target_account.id) + = link_to t('admin.reports.account.notes', count: target_account.targeted_moderation_notes.count), admin_account_path(target_account.id) %br/ - if target_account.suspended? %span.red= t('admin.accounts.suspended') diff --git a/app/views/admin/reports/show.html.haml b/app/views/admin/reports/show.html.haml index bbe83c979..aee9a3aef 100644 --- a/app/views/admin/reports/show.html.haml +++ b/app/views/admin/reports/show.html.haml @@ -25,16 +25,16 @@ %tr %th= t('admin.reports.reported_account') %td= admin_account_link_to @report.target_account - %td= table_link_to 'flag', pluralize(@report.target_account.targeted_reports.count, t('admin.reports.account.report')), admin_reports_path(target_account_id: @report.target_account.id) - %td= table_link_to 'file', pluralize(@report.target_account.targeted_moderation_notes.count, t('admin.reports.account.note')), admin_reports_path(target_account_id: @report.target_account.id) + %td= table_link_to 'flag', t('admin.reports.account.reports', count: @report.target_account.targeted_reports.count), admin_reports_path(target_account_id: @report.target_account.id) + %td= table_link_to 'file', t('admin.reports.account.notes', count: @report.target_account.targeted_moderation_notes.count), admin_reports_path(target_account_id: @report.target_account.id) %tr %th= t('admin.reports.reported_by') - if @report.account.instance_actor? %td{ colspan: 3 }= site_hostname - elsif @report.account.local? %td= admin_account_link_to @report.account - %td= table_link_to 'flag', pluralize(@report.account.targeted_reports.count, t('admin.reports.account.report')), admin_reports_path(target_account_id: @report.account.id) - %td= table_link_to 'file', pluralize(@report.account.targeted_moderation_notes.count, t('admin.reports.account.note')), admin_reports_path(target_account_id: @report.account.id) + %td= table_link_to 'flag', t('admin.reports.account.reports', count: @report.account.targeted_reports.count), admin_reports_path(target_account_id: @report.account.id) + %td= table_link_to 'file', t('admin.reports.account.notes', count: @report.account.targeted_moderation_notes.count), admin_reports_path(target_account_id: @report.account.id) - else %td{ colspan: 3 }= @report.account.domain %tr -- cgit From 09a72add0e98c3aebe82c417ecda01bed9596b20 Mon Sep 17 00:00:00 2001 From: "Acid Chicken (硫酸鶏)" Date: Tue, 17 Dec 2019 07:55:02 +0900 Subject: Fix tooltip messages of multiple poll switcher are reversed (#12616) --- app/javascript/mastodon/features/compose/components/poll_form.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/javascript/mastodon/features/compose/components/poll_form.js b/app/javascript/mastodon/features/compose/components/poll_form.js index e9bbb4ba4..01df31d3a 100644 --- a/app/javascript/mastodon/features/compose/components/poll_form.js +++ b/app/javascript/mastodon/features/compose/components/poll_form.js @@ -82,8 +82,8 @@ class Option extends React.PureComponent { onKeyPress={this.handleCheckboxKeypress} role='button' tabIndex='0' - title={intl.formatMessage(isPollMultiple ? messages.switchToMultiple : messages.switchToSingle)} - aria-label={intl.formatMessage(isPollMultiple ? messages.switchToMultiple : messages.switchToSingle)} + title={intl.formatMessage(isPollMultiple ? messages.switchToSingle : messages.switchToMultiple)} + aria-label={intl.formatMessage(isPollMultiple ? messages.switchToSingle : messages.switchToMultiple)} /> Date: Tue, 17 Dec 2019 05:55:16 +0700 Subject: Improve report page structure (#12615) * Move resolved button to the heading This is one of the commits on improving overall reports page structure. It changes where resolved button is located, moving it to the heading, right next to the "Report #n" header, so-called "hot-place" to look at. To accomplish this we have to declare one more content variable, change admin dashboard template to respect it and CSS files for minor styling, so buttons are inlined and centrally aligned according to the heading. * Move actions buttons below the report table I believe that actions to react on report should not be located at the top of the page, instead they should be either after the table or reporter's comment. This is just a logical sign that you should not react to the report without reading all the details first. --- app/javascript/styles/mastodon/admin.scss | 31 ++++++++++++++++++++++++++----- app/views/admin/reports/show.html.haml | 24 +++++++++++++----------- app/views/layouts/admin.html.haml | 7 ++++++- 3 files changed, 45 insertions(+), 17 deletions(-) (limited to 'app') diff --git a/app/javascript/styles/mastodon/admin.scss b/app/javascript/styles/mastodon/admin.scss index dde1d69ba..203365f5e 100644 --- a/app/javascript/styles/mastodon/admin.scss +++ b/app/javascript/styles/mastodon/admin.scss @@ -181,18 +181,39 @@ $content-width: 840px; padding-top: 30px; } - h2 { - color: $secondary-text-color; - font-size: 24px; - line-height: 28px; - font-weight: 400; + &-heading { + display: flex; + padding-bottom: 40px; border-bottom: 1px solid lighten($ui-base-color, 8%); margin-bottom: 40px; + flex-wrap: wrap; + align-items: center; + + justify-content: space-between; + + &-actions { + display: inline-flex; + + & > * { + margin-left: 5px; + } + } + @media screen and (max-width: $no-columns-breakpoint) { border-bottom: 0; padding-bottom: 0; + } + } + + h2 { + color: $secondary-text-color; + font-size: 24px; + line-height: 28px; + font-weight: 400; + + @media screen and (max-width: $no-columns-breakpoint) { font-weight: 700; } } diff --git a/app/views/admin/reports/show.html.haml b/app/views/admin/reports/show.html.haml index aee9a3aef..7f3ec35a4 100644 --- a/app/views/admin/reports/show.html.haml +++ b/app/views/admin/reports/show.html.haml @@ -4,21 +4,12 @@ - content_for :page_title do = t('admin.reports.report', id: @report.id) -%div{ style: 'overflow: hidden; margin-bottom: 20px' } +- content_for :page_heading_actions do - if @report.unresolved? - %div{ style: 'float: right' } - - if @report.target_account.local? - = link_to t('admin.accounts.warn'), new_admin_account_action_path(@report.target_account_id, type: 'none', report_id: @report.id), class: 'button' - = link_to t('admin.accounts.disable'), new_admin_account_action_path(@report.target_account_id, type: 'disable', report_id: @report.id), class: 'button button--destructive' - = link_to t('admin.accounts.silence'), new_admin_account_action_path(@report.target_account_id, type: 'silence', report_id: @report.id), class: 'button button--destructive' - = link_to t('admin.accounts.perform_full_suspension'), new_admin_account_action_path(@report.target_account_id, type: 'suspend', report_id: @report.id), class: 'button button--destructive' - %div{ style: 'float: left' } - = link_to t('admin.reports.mark_as_resolved'), resolve_admin_report_path(@report), method: :post, class: 'button' + = link_to t('admin.reports.mark_as_resolved'), resolve_admin_report_path(@report), method: :post, class: 'button' - else = link_to t('admin.reports.mark_as_unresolved'), reopen_admin_report_path(@report), method: :post, class: 'button' -%hr.spacer - .table-wrapper %table.table.inline-table %tbody @@ -77,6 +68,17 @@ %hr.spacer +%div{ style: 'overflow: hidden; margin-bottom: 20px; clear: both' } + - if @report.unresolved? + %div{ style: 'float: right' } + - if @report.target_account.local? + = link_to t('admin.accounts.warn'), new_admin_account_action_path(@report.target_account_id, type: 'none', report_id: @report.id), class: 'button' + = link_to t('admin.accounts.disable'), new_admin_account_action_path(@report.target_account_id, type: 'disable', report_id: @report.id), class: 'button button--destructive' + = link_to t('admin.accounts.silence'), new_admin_account_action_path(@report.target_account_id, type: 'silence', report_id: @report.id), class: 'button button--destructive' + = link_to t('admin.accounts.perform_full_suspension'), new_admin_account_action_path(@report.target_account_id, type: 'suspend', report_id: @report.id), class: 'button button--destructive' + +%hr.spacer + .speech-bubble .speech-bubble__bubble= simple_format(@report.comment.presence || t('admin.reports.comment.none')) .speech-bubble__owner diff --git a/app/views/layouts/admin.html.haml b/app/views/layouts/admin.html.haml index 57bda45e2..059bf8579 100644 --- a/app/views/layouts/admin.html.haml +++ b/app/views/layouts/admin.html.haml @@ -21,7 +21,12 @@ .content-wrapper .content - %h2= yield :page_title + .content-heading + %h2= yield :page_title + + - if :page_heading_actions + .content-heading-actions + = yield :page_heading_actions = render 'application/flashes' -- cgit From 8094955461419661b88a0361a5d7caed4b19c29a Mon Sep 17 00:00:00 2001 From: Thomas Citharel Date: Mon, 16 Dec 2019 23:55:28 +0100 Subject: Add Event activity-type support (#12637) This adds support for Event AP type in Mastodon. Events are converted into toots by taking their title (AS name) and their URL (AP ID). Event picture is also brought in if available. Testable by fetching event content from https://test.mobilizon.org Signed-off-by: Thomas Citharel --- app/lib/activitypub/activity.rb | 2 +- .../activitypub/fetch_remote_status_service_spec.rb | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/lib/activitypub/activity.rb b/app/lib/activitypub/activity.rb index 0ca6b92a4..49b1dc9cd 100644 --- a/app/lib/activitypub/activity.rb +++ b/app/lib/activitypub/activity.rb @@ -5,7 +5,7 @@ class ActivityPub::Activity include Redisable SUPPORTED_TYPES = %w(Note Question).freeze - CONVERTED_TYPES = %w(Image Audio Video Article Page).freeze + CONVERTED_TYPES = %w(Image Audio Video Article Page Event).freeze def initialize(json, account, **options) @json = json diff --git a/spec/services/activitypub/fetch_remote_status_service_spec.rb b/spec/services/activitypub/fetch_remote_status_service_spec.rb index 78dd59e3b..1ecc46952 100644 --- a/spec/services/activitypub/fetch_remote_status_service_spec.rb +++ b/spec/services/activitypub/fetch_remote_status_service_spec.rb @@ -104,6 +104,26 @@ RSpec.describe ActivityPub::FetchRemoteStatusService, type: :service do end end + context 'with Event object' do + let(:object) do + { + '@context': 'https://www.w3.org/ns/activitystreams', + id: "https://#{valid_domain}/@foo/1234", + type: 'Event', + name: "Let's change the world", + attributedTo: ActivityPub::TagManager.instance.uri_for(sender) + } + end + + it 'creates status' do + status = sender.statuses.first + + expect(status).to_not be_nil + expect(status.url).to eq "https://#{valid_domain}/@foo/1234" + expect(strip_tags(status.text)).to eq "Let's change the world https://#{valid_domain}/@foo/1234" + end + end + context 'with wrong id' do let(:note) do { -- cgit From 668f6980774e124a1cc4c80b280172de04ca7973 Mon Sep 17 00:00:00 2001 From: Alice Gaudon Date: Mon, 16 Dec 2019 23:55:50 +0100 Subject: Admin setting to disable default follows (#12566) --- app/javascript/packs/admin.js | 22 ++++++++++++++++++++-- app/models/form/admin_settings.rb | 2 ++ app/services/bootstrap_timeline_service.rb | 2 +- app/views/admin/settings/edit.html.haml | 7 ++++++- config/locales/en.yml | 2 ++ config/settings.yml | 1 + 6 files changed, 32 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/javascript/packs/admin.js b/app/javascript/packs/admin.js index 42c747d2e..b318cadc6 100644 --- a/app/javascript/packs/admin.js +++ b/app/javascript/packs/admin.js @@ -45,7 +45,25 @@ const onDomainBlockSeverityChange = (target) => { delegate(document, '#domain_block_severity', 'change', ({ target }) => onDomainBlockSeverityChange(target)); +const onEnableBootstrapTimelineAccountsChange = (target) => { + const bootstrapTimelineAccountsField = document.querySelector('#form_admin_settings_bootstrap_timeline_accounts'); + + if (bootstrapTimelineAccountsField) { + bootstrapTimelineAccountsField.disabled = !target.checked; + if (target.checked) { + bootstrapTimelineAccountsField.parentElement.classList.remove('disabled'); + } else { + bootstrapTimelineAccountsField.parentElement.classList.add('disabled'); + } + } +}; + +delegate(document, '#form_admin_settings_enable_bootstrap_timeline_accounts', 'change', ({ target }) => onEnableBootstrapTimelineAccountsChange(target)); + ready(() => { - const input = document.getElementById('domain_block_severity'); - if (input) onDomainBlockSeverityChange(input); + const domainBlockSeverityInput = document.getElementById('domain_block_severity'); + if (domainBlockSeverityInput) onDomainBlockSeverityChange(domainBlockSeverityInput); + + const enableBootstrapTimelineAccounts = document.getElementById('form_admin_settings_enable_bootstrap_timeline_accounts'); + if (enableBootstrapTimelineAccounts) onEnableBootstrapTimelineAccountsChange(enableBootstrapTimelineAccounts); }); diff --git a/app/models/form/admin_settings.rb b/app/models/form/admin_settings.rb index 70e9c21f1..390836f28 100644 --- a/app/models/form/admin_settings.rb +++ b/app/models/form/admin_settings.rb @@ -16,6 +16,7 @@ class Form::AdminSettings open_deletion timeline_preview show_staff_badge + enable_bootstrap_timeline_accounts bootstrap_timeline_accounts theme min_invite_role @@ -40,6 +41,7 @@ class Form::AdminSettings open_deletion timeline_preview show_staff_badge + enable_bootstrap_timeline_accounts activity_api_enabled peers_api_enabled show_known_fediverse_at_about_page diff --git a/app/services/bootstrap_timeline_service.rb b/app/services/bootstrap_timeline_service.rb index c489601c1..8412aa7e7 100644 --- a/app/services/bootstrap_timeline_service.rb +++ b/app/services/bootstrap_timeline_service.rb @@ -5,7 +5,7 @@ class BootstrapTimelineService < BaseService @source_account = source_account autofollow_inviter! - autofollow_bootstrap_timeline_accounts! + autofollow_bootstrap_timeline_accounts! if Setting.enable_bootstrap_timeline_accounts end private diff --git a/app/views/admin/settings/edit.html.haml b/app/views/admin/settings/edit.html.haml index 6282bb39c..d7b493051 100644 --- a/app/views/admin/settings/edit.html.haml +++ b/app/views/admin/settings/edit.html.haml @@ -1,3 +1,6 @@ +- content_for :header_tags do + = javascript_pack_tag 'admin', integrity: true, async: true, crossorigin: 'anonymous' + - content_for :page_title do = t('admin.settings.title') @@ -38,7 +41,9 @@ %hr.spacer/ .fields-group - = f.input :bootstrap_timeline_accounts, wrapper: :with_block_label, label: t('admin.settings.bootstrap_timeline_accounts.title'), hint: t('admin.settings.bootstrap_timeline_accounts.desc_html') + = f.input :enable_bootstrap_timeline_accounts, as: :boolean, wrapper: :with_label, label: t('admin.settings.enable_bootstrap_timeline_accounts.title') + .fields-group + = f.input :bootstrap_timeline_accounts, wrapper: :with_block_label, label: t('admin.settings.bootstrap_timeline_accounts.title'), hint: t('admin.settings.bootstrap_timeline_accounts.desc_html'), disabled: !Setting.enable_bootstrap_timeline_accounts %hr.spacer/ diff --git a/config/locales/en.yml b/config/locales/en.yml index ea94928e7..5edd6e0d3 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -456,6 +456,8 @@ en: users: To logged-in local users domain_blocks_rationale: title: Show rationale + enable_bootstrap_timeline_accounts: + title: Enable default follows for new users hero: desc_html: Displayed on the frontpage. At least 600x100px recommended. When not set, falls back to server thumbnail title: Hero image diff --git a/config/settings.yml b/config/settings.yml index f66e3922e..002473643 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -61,6 +61,7 @@ defaults: &defaults - mod - moderator disallowed_hashtags: # space separated string or list of hashtags without the hash + enable_bootstrap_timeline_accounts: true bootstrap_timeline_accounts: '' activity_api_enabled: true peers_api_enabled: true -- cgit From 3830c0b74168070cdd410d311ba85a3b323bca9f Mon Sep 17 00:00:00 2001 From: scd31 <57571338+scd31@users.noreply.github.com> Date: Tue, 17 Dec 2019 12:30:58 +0000 Subject: Increase max backup size (#12602) * Increased max backup size * partially reverted schema.rb --- app/models/backup.rb | 2 +- db/migrate/20191212003415_increase_backup_size.rb | 9 ++++++++ db/schema.rb | 28 ++--------------------- 3 files changed, 12 insertions(+), 27 deletions(-) create mode 100644 db/migrate/20191212003415_increase_backup_size.rb (limited to 'app') diff --git a/app/models/backup.rb b/app/models/backup.rb index c2651313b..8eeb1748a 100644 --- a/app/models/backup.rb +++ b/app/models/backup.rb @@ -7,7 +7,7 @@ # user_id :bigint(8) # dump_file_name :string # dump_content_type :string -# dump_file_size :integer +# dump_file_size :bigint # dump_updated_at :datetime # processed :boolean default(FALSE), not null # created_at :datetime not null diff --git a/db/migrate/20191212003415_increase_backup_size.rb b/db/migrate/20191212003415_increase_backup_size.rb new file mode 100644 index 000000000..782c67db1 --- /dev/null +++ b/db/migrate/20191212003415_increase_backup_size.rb @@ -0,0 +1,9 @@ +class IncreaseBackupSize < ActiveRecord::Migration[5.2] + def up + change_column :backups, :dump_file_size, :bigint + end + + def down + change_column :backups, :dump_file_size, :integer + end +end diff --git a/db/schema.rb b/db/schema.rb index 84c76e4ce..5a6b2530c 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2019_10_31_163205) do +ActiveRecord::Schema.define(version: 2019_12_12_003415) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -200,7 +200,7 @@ ActiveRecord::Schema.define(version: 2019_10_31_163205) do t.bigint "user_id" t.string "dump_file_name" t.string "dump_content_type" - t.integer "dump_file_size" + t.bigint "dump_file_size" t.datetime "dump_updated_at" t.boolean "processed", default: false, null: false t.datetime "created_at", null: false @@ -703,30 +703,6 @@ ActiveRecord::Schema.define(version: 2019_10_31_163205) do t.index ["tag_id", "status_id"], name: "index_statuses_tags_on_tag_id_and_status_id", unique: true end - create_table "stream_entries", force: :cascade do |t| - t.bigint "activity_id" - t.string "activity_type" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.boolean "hidden", default: false, null: false - t.bigint "account_id" - t.index ["account_id", "activity_type", "id"], name: "index_stream_entries_on_account_id_and_activity_type_and_id" - t.index ["activity_id", "activity_type"], name: "index_stream_entries_on_activity_id_and_activity_type" - end - - create_table "subscriptions", force: :cascade do |t| - t.string "callback_url", default: "", null: false - t.string "secret" - t.datetime "expires_at" - t.boolean "confirmed", default: false, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.datetime "last_successful_delivery_at" - t.string "domain" - t.bigint "account_id", null: false - t.index ["account_id", "callback_url"], name: "index_subscriptions_on_account_id_and_callback_url", unique: true - end - create_table "tags", force: :cascade do |t| t.string "name", default: "", null: false t.datetime "created_at", null: false -- cgit From da2143b3089ec16fca449b97acbfb65acfe92197 Mon Sep 17 00:00:00 2001 From: ThibG Date: Tue, 17 Dec 2019 13:31:56 +0100 Subject: Fixes featured hashtag setting page erroring out instead of rejecting invalid tags (#12436) * Revert "Fix ignoring whole status because of one invalid hashtag (#11621)" This reverts commit dff46b260b2f7d765d254c84a4b89105c7de5e97. * Fix statuses being rejected because of invalid hashtag names * Add spec for invalid hashtag names in statuses * Add test for featured tags controller --- app/lib/activitypub/activity/create.rb | 2 +- app/models/tag.rb | 2 +- .../settings/featured_tags_controller_spec.rb | 43 ++++++++++++++++++++++ spec/lib/activitypub/activity/create_spec.rb | 22 +++++++++++ 4 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 spec/controllers/settings/featured_tags_controller_spec.rb (limited to 'app') diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index 8a12a2b08..756d5cb1c 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -157,7 +157,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity return if tag['name'].blank? Tag.find_or_create_by_names(tag['name']) do |hashtag| - @tags << hashtag unless @tags.include?(hashtag) + @tags << hashtag unless @tags.include?(hashtag) || !hashtag.valid? end rescue ActiveRecord::RecordInvalid nil diff --git a/app/models/tag.rb b/app/models/tag.rb index d3a7e1e6d..bce76fc16 100644 --- a/app/models/tag.rb +++ b/app/models/tag.rb @@ -117,7 +117,7 @@ class Tag < ApplicationRecord class << self def find_or_create_by_names(name_or_names) Array(name_or_names).map(&method(:normalize)).uniq { |str| str.mb_chars.downcase.to_s }.map do |normalized_name| - tag = matching_name(normalized_name).first || create!(name: normalized_name) + tag = matching_name(normalized_name).first || create(name: normalized_name) yield tag if block_given? diff --git a/spec/controllers/settings/featured_tags_controller_spec.rb b/spec/controllers/settings/featured_tags_controller_spec.rb new file mode 100644 index 000000000..33b87f9f6 --- /dev/null +++ b/spec/controllers/settings/featured_tags_controller_spec.rb @@ -0,0 +1,43 @@ +require 'rails_helper' + +describe Settings::FeaturedTagsController do + render_views + + shared_examples 'authenticate user' do + it 'redirects to sign_in page' do + is_expected.to redirect_to new_user_session_path + end + end + + describe 'POST #create' do + context 'when user is not sign in' do + subject { post :create } + + it_behaves_like 'authenticate user' + end + + context 'when user is sign in' do + subject { post :create, params: { featured_tag: params } } + + let(:user) { Fabricate(:user, password: '12345678') } + + before { sign_in user, scope: :user } + + context 'when parameter is valid' do + let(:params) { { name: 'test' } } + + it 'creates featured tag' do + expect { subject }.to change { user.account.featured_tags.count }.by(1) + end + end + + context 'when parameter is invalid' do + let(:params) { { name: 'test, #foo !bleh' } } + + it 'renders new' do + expect(subject).to render_template :index + end + end + end + end +end diff --git a/spec/lib/activitypub/activity/create_spec.rb b/spec/lib/activitypub/activity/create_spec.rb index b709954a3..c4efb5cc9 100644 --- a/spec/lib/activitypub/activity/create_spec.rb +++ b/spec/lib/activitypub/activity/create_spec.rb @@ -378,6 +378,28 @@ RSpec.describe ActivityPub::Activity::Create do end end + context 'with hashtags invalid name' do + let(:object_json) do + { + id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join, + type: 'Note', + content: 'Lorem ipsum', + tag: [ + { + type: 'Hashtag', + href: 'http://example.com/blah', + name: 'foo, #eh !', + }, + ], + } + end + + it 'creates status' do + status = sender.statuses.first + expect(status).to_not be_nil + end + end + context 'with emojis' do let(:object_json) do { -- cgit From 2ee5a9d9c319f187d4e94f6974654e1701e427eb Mon Sep 17 00:00:00 2001 From: ThibG Date: Tue, 17 Dec 2019 13:32:57 +0100 Subject: Clean up OStatus-related codepaths (#12173) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Remove “protocol” argument and return value, as only ActivityPub is supported * Remove FetchRemoteAccountService, only use ActivityPub::FetchRemoteAccountService * Fix tests --- app/lib/activitypub/activity/create.rb | 2 +- app/services/fetch_remote_account_service.rb | 17 -------- app/services/fetch_remote_status_service.rb | 9 ++-- app/services/fetch_resource_service.rb | 2 +- app/services/resolve_url_service.rb | 10 ++--- spec/services/fetch_remote_account_service_spec.rb | 50 ---------------------- spec/services/fetch_remote_status_service_spec.rb | 7 ++- spec/services/fetch_resource_service_spec.rb | 8 ++-- 8 files changed, 15 insertions(+), 90 deletions(-) delete mode 100644 app/services/fetch_remote_account_service.rb delete mode 100644 spec/services/fetch_remote_account_service_spec.rb (limited to 'app') diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index 756d5cb1c..c55cfe08e 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -167,7 +167,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity return if tag['href'].blank? account = account_from_uri(tag['href']) - account = ::FetchRemoteAccountService.new.call(tag['href']) if account.nil? + account = ActivityPub::FetchRemoteAccountService.new.call(tag['href']) if account.nil? return if account.nil? diff --git a/app/services/fetch_remote_account_service.rb b/app/services/fetch_remote_account_service.rb deleted file mode 100644 index 3cd06e30f..000000000 --- a/app/services/fetch_remote_account_service.rb +++ /dev/null @@ -1,17 +0,0 @@ -# frozen_string_literal: true - -class FetchRemoteAccountService < BaseService - def call(url, prefetched_body = nil, protocol = :ostatus) - if prefetched_body.nil? - resource_url, resource_options, protocol = FetchResourceService.new.call(url) - else - resource_url = url - resource_options = { prefetched_body: prefetched_body } - end - - case protocol - when :activitypub - ActivityPub::FetchRemoteAccountService.new.call(resource_url, **resource_options) - end - end -end diff --git a/app/services/fetch_remote_status_service.rb b/app/services/fetch_remote_status_service.rb index 208dc7809..21d277aff 100644 --- a/app/services/fetch_remote_status_service.rb +++ b/app/services/fetch_remote_status_service.rb @@ -1,17 +1,14 @@ # frozen_string_literal: true class FetchRemoteStatusService < BaseService - def call(url, prefetched_body = nil, protocol = :ostatus) + def call(url, prefetched_body = nil) if prefetched_body.nil? - resource_url, resource_options, protocol = FetchResourceService.new.call(url) + resource_url, resource_options = FetchResourceService.new.call(url) else resource_url = url resource_options = { prefetched_body: prefetched_body } end - case protocol - when :activitypub - ActivityPub::FetchRemoteStatusService.new.call(resource_url, **resource_options) - end + ActivityPub::FetchRemoteStatusService.new.call(resource_url, **resource_options) end end diff --git a/app/services/fetch_resource_service.rb b/app/services/fetch_resource_service.rb index 3676d899d..34382d279 100644 --- a/app/services/fetch_resource_service.rb +++ b/app/services/fetch_resource_service.rb @@ -33,7 +33,7 @@ class FetchResourceService < BaseService body = response.body_with_limit json = body_to_json(body) - [json['id'], { prefetched_body: body, id: true }, :activitypub] if supported_context?(json) && (equals_or_includes_any?(json['type'], ActivityPub::FetchRemoteAccountService::SUPPORTED_TYPES) || expected_type?(json)) + [json['id'], { prefetched_body: body, id: true }] if supported_context?(json) && (equals_or_includes_any?(json['type'], ActivityPub::FetchRemoteAccountService::SUPPORTED_TYPES) || expected_type?(json)) elsif !terminal link_header = response['Link'] && parse_link_header(response) diff --git a/app/services/resolve_url_service.rb b/app/services/resolve_url_service.rb index 4e971a4b8..79b1bad0c 100644 --- a/app/services/resolve_url_service.rb +++ b/app/services/resolve_url_service.rb @@ -19,9 +19,9 @@ class ResolveURLService < BaseService def process_url if equals_or_includes_any?(type, ActivityPub::FetchRemoteAccountService::SUPPORTED_TYPES) - FetchRemoteAccountService.new.call(resource_url, body, protocol) + ActivityPub::FetchRemoteAccountService.new.call(resource_url, prefetched_body: body) elsif equals_or_includes_any?(type, ActivityPub::Activity::Create::SUPPORTED_TYPES + ActivityPub::Activity::Create::CONVERTED_TYPES) - status = FetchRemoteStatusService.new.call(resource_url, body, protocol) + status = FetchRemoteStatusService.new.call(resource_url, body) authorize_with @on_behalf_of, status, :show? unless status.nil? status elsif fetched_resource.nil? && @on_behalf_of.present? @@ -45,12 +45,8 @@ class ResolveURLService < BaseService fetched_resource.second[:prefetched_body] end - def protocol - fetched_resource.third - end - def type - return json_data['type'] if protocol == :activitypub + json_data['type'] end def json_data diff --git a/spec/services/fetch_remote_account_service_spec.rb b/spec/services/fetch_remote_account_service_spec.rb deleted file mode 100644 index ee7325be2..000000000 --- a/spec/services/fetch_remote_account_service_spec.rb +++ /dev/null @@ -1,50 +0,0 @@ -require 'rails_helper' - -RSpec.describe FetchRemoteAccountService, type: :service do - let(:url) { 'https://example.com/alice' } - let(:prefetched_body) { nil } - let(:protocol) { :ostatus } - - subject { FetchRemoteAccountService.new.call(url, prefetched_body, protocol) } - - let(:actor) do - { - '@context': 'https://www.w3.org/ns/activitystreams', - id: 'https://example.com/alice', - type: 'Person', - preferredUsername: 'alice', - name: 'Alice', - summary: 'Foo bar', - inbox: 'http://example.com/alice/inbox', - } - end - - let(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice' }] } } - let(:xml) { File.read(Rails.root.join('spec', 'fixtures', 'xml', 'mastodon.atom')) } - - shared_examples 'return Account' do - it { is_expected.to be_an Account } - end - - context 'protocol is :activitypub' do - let(:prefetched_body) { Oj.dump(actor) } - let(:protocol) { :activitypub } - - before do - stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) - end - - include_examples 'return Account' - end - - context 'when prefetched_body is nil' do - context 'protocol is :activitypub' do - before do - stub_request(:get, url).to_return(status: 200, body: Oj.dump(actor), headers: { 'Content-Type' => 'application/activity+json' }) - stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) - end - - include_examples 'return Account' - end - end -end diff --git a/spec/services/fetch_remote_status_service_spec.rb b/spec/services/fetch_remote_status_service_spec.rb index f9db024b9..1c4b4fee2 100644 --- a/spec/services/fetch_remote_status_service_spec.rb +++ b/spec/services/fetch_remote_status_service_spec.rb @@ -16,9 +16,8 @@ RSpec.describe FetchRemoteStatusService, type: :service do end context 'protocol is :activitypub' do - subject { described_class.new.call(note[:id], prefetched_body, protocol) } + subject { described_class.new.call(note[:id], prefetched_body) } let(:prefetched_body) { Oj.dump(note) } - let(:protocol) { :activitypub } before do account.update(uri: ActivityPub::TagManager.instance.uri_for(account)) @@ -59,7 +58,7 @@ RSpec.describe FetchRemoteStatusService, type: :service do XML - expect(subject.call('https://fake.domain/foo', status_body, :ostatus)).to be_nil + expect(subject.call('https://fake.domain/foo', status_body)).to be_nil end it 'does not create status with wrong id when id uses http format' do @@ -81,7 +80,7 @@ RSpec.describe FetchRemoteStatusService, type: :service do XML - expect(subject.call('https://real.domain/statuses/456', status_body, :ostatus)).to be_nil + expect(subject.call('https://real.domain/statuses/456', status_body)).to be_nil end end end diff --git a/spec/services/fetch_resource_service_spec.rb b/spec/services/fetch_resource_service_spec.rb index f836147d3..3af6a0689 100644 --- a/spec/services/fetch_resource_service_spec.rb +++ b/spec/services/fetch_resource_service_spec.rb @@ -71,14 +71,14 @@ RSpec.describe FetchResourceService, type: :service do let(:content_type) { 'application/activity+json; charset=utf-8' } let(:body) { json } - it { is_expected.to eq [1, { prefetched_body: body, id: true }, :activitypub] } + it { is_expected.to eq [1, { prefetched_body: body, id: true }] } end context 'when content type is ld+json with profile' do let(:content_type) { 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' } let(:body) { json } - it { is_expected.to eq [1, { prefetched_body: body, id: true }, :activitypub] } + it { is_expected.to eq [1, { prefetched_body: body, id: true }] } end before do @@ -89,14 +89,14 @@ RSpec.describe FetchResourceService, type: :service do context 'when link header is present' do let(:headers) { { 'Link' => '; rel="alternate"; type="application/activity+json"', } } - it { is_expected.to eq [1, { prefetched_body: json, id: true }, :activitypub] } + it { is_expected.to eq [1, { prefetched_body: json, id: true }] } end context 'when content type is text/html' do let(:content_type) { 'text/html' } let(:body) { '' } - it { is_expected.to eq [1, { prefetched_body: json, id: true }, :activitypub] } + it { is_expected.to eq [1, { prefetched_body: json, id: true }] } end end end -- cgit From a391eaf4d81d5b7a2e5d7e2106f3e119867e1a9b Mon Sep 17 00:00:00 2001 From: Takeshi Umeda Date: Thu, 19 Dec 2019 00:54:03 +0900 Subject: Fix an error when ActivityPub::FetchRemoteStatusService url is called with nil (#12652) --- app/services/fetch_remote_status_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/services/fetch_remote_status_service.rb b/app/services/fetch_remote_status_service.rb index 21d277aff..eafde4d4a 100644 --- a/app/services/fetch_remote_status_service.rb +++ b/app/services/fetch_remote_status_service.rb @@ -9,6 +9,6 @@ class FetchRemoteStatusService < BaseService resource_options = { prefetched_body: prefetched_body } end - ActivityPub::FetchRemoteStatusService.new.call(resource_url, **resource_options) + ActivityPub::FetchRemoteStatusService.new.call(resource_url, **resource_options) unless resource_url.nil? end end -- cgit From 68070e82ccadfef4f101653cf8456f15148c58b7 Mon Sep 17 00:00:00 2001 From: Takeshi Umeda Date: Thu, 19 Dec 2019 00:55:21 +0900 Subject: Add signature to exported status (#12649) --- app/services/backup_service.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/services/backup_service.rb b/app/services/backup_service.rb index fe26d7aa0..fba2d19a0 100644 --- a/app/services/backup_service.rb +++ b/app/services/backup_service.rb @@ -3,6 +3,8 @@ require 'rubygems/package' class BackupService < BaseService + include Payloadable + attr_reader :account, :backup, :collection def call(backup) @@ -20,7 +22,7 @@ class BackupService < BaseService account.statuses.with_includes.reorder(nil).find_in_batches do |statuses| statuses.each do |status| - item = serialize(status, ActivityPub::ActivitySerializer) + item = serialize_payload(status, ActivityPub::ActivitySerializer, signer: @account) item.delete(:'@context') unless item[:type] == 'Announce' || item[:object][:attachment].blank? -- cgit From b364175e1b345e7f36955ba85b483ec2bdd8622d Mon Sep 17 00:00:00 2001 From: ThibG Date: Wed, 18 Dec 2019 16:56:06 +0100 Subject: Fix link crawler not specifying accepted content-type (#12646) The link crawler expects HTML documents, so set the `Accept` header accordingly. Fixes #12618 --- app/services/fetch_link_card_service.rb | 2 +- app/services/fetch_oembed_service.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/services/fetch_link_card_service.rb b/app/services/fetch_link_card_service.rb index 5d4a7c303..91141c1f5 100644 --- a/app/services/fetch_link_card_service.rb +++ b/app/services/fetch_link_card_service.rb @@ -45,7 +45,7 @@ class FetchLinkCardService < BaseService def html return @html if defined?(@html) - Request.new(:get, @url).perform do |res| + Request.new(:get, @url).add_headers('Accept' => 'text/html').perform do |res| if res.code == 200 && res.mime_type == 'text/html' @html = res.body_with_limit @html_charset = res.charset diff --git a/app/services/fetch_oembed_service.rb b/app/services/fetch_oembed_service.rb index 76d971bc5..67e33875c 100644 --- a/app/services/fetch_oembed_service.rb +++ b/app/services/fetch_oembed_service.rb @@ -93,7 +93,7 @@ class FetchOEmbedService def html return @html if defined?(@html) - @html = @options[:html] || Request.new(:get, @url).perform do |res| + @html = @options[:html] || Request.new(:get, @url).add_headers('Accept' => 'text/html').perform do |res| res.code != 200 || res.mime_type != 'text/html' ? nil : res.body_with_limit end end -- cgit From c0ed53b810351b61db543701c4938d41723a6e4e Mon Sep 17 00:00:00 2001 From: ThibG Date: Wed, 18 Dec 2019 16:56:59 +0100 Subject: Fix custom emoji category creation silently erroring out on duplicate category (#12647) Instead, just re-use the existing category if any. Fixes #12608 --- app/models/form/custom_emoji_batch.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/models/form/custom_emoji_batch.rb b/app/models/form/custom_emoji_batch.rb index 076e8c9e3..6b7ea5355 100644 --- a/app/models/form/custom_emoji_batch.rb +++ b/app/models/form/custom_emoji_batch.rb @@ -40,7 +40,7 @@ class Form::CustomEmojiBatch if category_id.present? CustomEmojiCategory.find(category_id) elsif category_name.present? - CustomEmojiCategory.create!(name: category_name) + CustomEmojiCategory.find_or_create_by!(name: category_name) end end -- cgit From a90258dbe9f6632350a81f0e4e14f6cc354e0e76 Mon Sep 17 00:00:00 2001 From: Marcin Mikołajczak Date: Wed, 18 Dec 2019 23:39:08 +0100 Subject: fix multiple space (#12655) --- app/javascript/mastodon/extra_polyfills.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/javascript/mastodon/extra_polyfills.js b/app/javascript/mastodon/extra_polyfills.js index 3acc55abd..13c4f6da9 100644 --- a/app/javascript/mastodon/extra_polyfills.js +++ b/app/javascript/mastodon/extra_polyfills.js @@ -1,5 +1,5 @@ import 'intersection-observer'; import 'requestidlecallback'; -import objectFitImages from 'object-fit-images'; +import objectFitImages from 'object-fit-images'; objectFitImages(); -- cgit From dc0750abc331749a92ffa96fed9fe048acdea3b1 Mon Sep 17 00:00:00 2001 From: ThibG Date: Thu, 19 Dec 2019 12:47:19 +0100 Subject: Fix manual scrolling issue on Firefox/Windows (#12648) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #12607 `will-change: transform` apparently makes manual scrolling impossible on Firefox/Windows. While this should probably be considered a Firefox bug, `will-change: transform` seem like a very aggressive performance hint that may possibly make the browser consume more resources than needed, especially in multiple-column mode. This was originally added to improve scrolling performances on mobile, but I think this isn't necessary anymore, because of the two following reasons: - `contain: paint` (which is implied by `contain: strict`, which we apply whenever the browser supports grids) should have similar effects - in single-column mode, the scrolling container is the root element, which I believe is optimized in at least Chromium Keep in mind that I have not been able to make in-depth benchmarks, and especially not been able to try on mobile, so performances should probably be investigated further… --- app/javascript/styles/mastodon/components.scss | 1 - 1 file changed, 1 deletion(-) (limited to 'app') diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index 13f9dfae7..4c7ce9ba7 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -2512,7 +2512,6 @@ a.account__display-name { overflow-x: hidden; flex: 1 1 auto; -webkit-overflow-scrolling: touch; - will-change: transform; // improves perf in mobile Chrome &.optionally-scrollable { overflow-y: auto; -- cgit From 902c6bed5aab12c2e97af3452f122247777226af Mon Sep 17 00:00:00 2001 From: Sasha Sorokin Date: Thu, 19 Dec 2019 18:47:55 +0700 Subject: Use different strings on exports page (#12569) Currently the page re-uses strings from other contexts which doesn't fit very well - strings incorrectly lowercase-d and pluralized, when they don't need to be, because it's a table. This commit changes page to re-use accounts.posts_tab_heading for toots, and admin.accounts for "Following" and "Follows". This all should look more aesthetically pleasing. --- app/views/settings/exports/show.html.haml | 6 +++--- config/locales/en.yml | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/views/settings/exports/show.html.haml b/app/views/settings/exports/show.html.haml index 76ff76bd9..0bb80e937 100644 --- a/app/views/settings/exports/show.html.haml +++ b/app/views/settings/exports/show.html.haml @@ -9,11 +9,11 @@ %td= number_to_human_size @export.total_storage %td %tr - %th= t('accounts.posts', count: @export.total_statuses) + %th= t('accounts.posts_tab_heading') %td= number_with_delimiter @export.total_statuses %td %tr - %th= t('exports.follows') + %th= t('admin.accounts.follows') %td= number_with_delimiter @export.total_follows %td= table_link_to 'download', t('exports.csv'), settings_exports_follows_path(format: :csv) %tr @@ -21,7 +21,7 @@ %td= number_with_delimiter @export.total_lists %td= table_link_to 'download', t('exports.csv'), settings_exports_lists_path(format: :csv) %tr - %th= t('accounts.followers', count: @export.total_followers) + %th= t('admin.accounts.followers') %td= number_with_delimiter @export.total_followers %td %tr diff --git a/config/locales/en.yml b/config/locales/en.yml index a54cc813e..c7179d304 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -719,7 +719,6 @@ en: blocks: You block csv: CSV domain_blocks: Domain blocks - follows: You follow lists: Lists mutes: You mute storage: Media storage -- cgit