From 67215692fc1764cb4311e4bbd1211d0cf38438bd Mon Sep 17 00:00:00 2001 From: ThibG Date: Tue, 12 Feb 2019 22:24:14 +0100 Subject: [PATCH 01/27] Save IP address used for sign-up, not only sign-in (#10026) Fixes #9995 --- app/controllers/auth/registrations_controller.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/controllers/auth/registrations_controller.rb b/app/controllers/auth/registrations_controller.rb index f2a832542fe..ad7b1859f68 100644 --- a/app/controllers/auth/registrations_controller.rb +++ b/app/controllers/auth/registrations_controller.rb @@ -28,6 +28,7 @@ class Auth::RegistrationsController < Devise::RegistrationsController resource.invite_code = params[:invite_code] if resource.invite_code.blank? resource.agreement = true + resource.current_sign_in_ip = request.remote_ip if resource.current_sign_in_ip.nil? resource.build_account if resource.account.nil? end From fbe527ccfc85f9547fd807b3d1e2a7fcf3fc81ae Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Wed, 13 Feb 2019 02:45:01 +0100 Subject: [PATCH 02/27] Bump sidekiq-unique-jobs from 6.0.8 to 6.0.9 (#10019) Bumps [sidekiq-unique-jobs](https://github.com/mhenrixon/sidekiq-unique-jobs) from 6.0.8 to 6.0.9. - [Release notes](https://github.com/mhenrixon/sidekiq-unique-jobs/releases) - [Changelog](https://github.com/mhenrixon/sidekiq-unique-jobs/blob/master/CHANGELOG.md) - [Commits](https://github.com/mhenrixon/sidekiq-unique-jobs/compare/v6.0.8...v6.0.9) Signed-off-by: dependabot[bot] --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index c47f4e9307f..9d4252f1639 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -563,7 +563,7 @@ GEM rufus-scheduler (~> 3.2) sidekiq (>= 3) tilt (>= 1.4.0) - sidekiq-unique-jobs (6.0.8) + sidekiq-unique-jobs (6.0.9) concurrent-ruby (~> 1.0, >= 1.0.5) sidekiq (>= 4.0, < 6.0) thor (~> 0) From 3a2e44b62c408f2665f4faf6245f6a41e3a2c541 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Wed, 13 Feb 2019 02:54:27 +0100 Subject: [PATCH 03/27] Bump pkg-config from 1.3.2 to 1.3.3 (#10023) Bumps [pkg-config](https://github.com/ruby-gnome2/pkg-config) from 1.3.2 to 1.3.3. - [Release notes](https://github.com/ruby-gnome2/pkg-config/releases) - [Changelog](https://github.com/ruby-gnome2/pkg-config/blob/master/NEWS) - [Commits](https://github.com/ruby-gnome2/pkg-config/compare/1.3.2...1.3.3) Signed-off-by: dependabot[bot] --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 9d4252f1639..30c7d31d957 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -400,7 +400,7 @@ GEM pg (1.1.4) pghero (2.2.0) activerecord - pkg-config (1.3.2) + pkg-config (1.3.3) powerpack (0.1.2) premailer (1.11.1) addressable From 5977e6af322fd597c7e9a28d4686870a7e0ed539 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Wed, 13 Feb 2019 02:54:48 +0100 Subject: [PATCH 04/27] Bump faker from 1.9.1 to 1.9.2 (#10020) Bumps [faker](https://github.com/stympy/faker) from 1.9.1 to 1.9.2. - [Release notes](https://github.com/stympy/faker/releases) - [Changelog](https://github.com/stympy/faker/blob/master/CHANGELOG.md) - [Commits](https://github.com/stympy/faker/compare/v1.9.1...v1.9.2) Signed-off-by: dependabot[bot] --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 30c7d31d957..d60eb1c141e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -205,7 +205,7 @@ GEM tzinfo excon (0.62.0) fabrication (2.20.1) - faker (1.9.1) + faker (1.9.2) i18n (>= 0.7) faraday (0.15.0) multipart-post (>= 1.2, < 3) From 3d374ed18be3efc78e48ccd512f7e44f38d2bc7c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Wed, 13 Feb 2019 02:55:06 +0100 Subject: [PATCH 05/27] Bump bootsnap from 1.3.2 to 1.4.0 (#10022) Bumps [bootsnap](https://github.com/Shopify/bootsnap) from 1.3.2 to 1.4.0. - [Release notes](https://github.com/Shopify/bootsnap/releases) - [Changelog](https://github.com/Shopify/bootsnap/blob/master/CHANGELOG.md) - [Commits](https://github.com/Shopify/bootsnap/compare/v1.3.2...v1.4.0) Signed-off-by: dependabot[bot] --- Gemfile | 2 +- Gemfile.lock | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Gemfile b/Gemfile index d924a546ba1..e01d168b635 100644 --- a/Gemfile +++ b/Gemfile @@ -24,7 +24,7 @@ gem 'streamio-ffmpeg', '~> 3.0' gem 'active_model_serializers', '~> 0.10' gem 'addressable', '~> 2.6' -gem 'bootsnap', '~> 1.3', require: false +gem 'bootsnap', '~> 1.4', require: false gem 'browser' gem 'charlock_holmes', '~> 0.7.6' gem 'iso-639' diff --git a/Gemfile.lock b/Gemfile.lock index d60eb1c141e..05622340b79 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -98,7 +98,7 @@ GEM rack (>= 0.9.0) binding_of_caller (0.8.0) debug_inspector (>= 0.0.1) - bootsnap (1.3.2) + bootsnap (1.4.0) msgpack (~> 1.0) brakeman (4.4.0) browser (2.5.3) @@ -345,7 +345,7 @@ GEM mini_mime (1.0.1) mini_portile2 (2.4.0) minitest (5.11.3) - msgpack (1.2.4) + msgpack (1.2.6) multi_json (1.13.1) multipart-post (2.0.0) necromancer (0.4.0) @@ -660,7 +660,7 @@ DEPENDENCIES aws-sdk-s3 (~> 1.30) better_errors (~> 2.5) binding_of_caller (~> 0.7) - bootsnap (~> 1.3) + bootsnap (~> 1.4) brakeman (~> 4.4) browser bullet (~> 5.9) From c6e7b97baa37c23a4853619ad3ff706f41a15237 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Wed, 13 Feb 2019 05:30:49 +0100 Subject: [PATCH 06/27] Fix color of static page links in high contrast theme (#10028) --- app/javascript/styles/contrast/diff.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/javascript/styles/contrast/diff.scss b/app/javascript/styles/contrast/diff.scss index 7d8993a5080..8429103b8af 100644 --- a/app/javascript/styles/contrast/diff.scss +++ b/app/javascript/styles/contrast/diff.scss @@ -13,6 +13,10 @@ } } +.rich-formatting a, +.rich-formatting p a, +.rich-formatting li a, +.landing-page__short-description p a, .status__content a, .reply-indicator__content a { color: lighten($ui-highlight-color, 12%); From 98d1a1f117452a5e12d73eaf43a10f36e187402e Mon Sep 17 00:00:00 2001 From: ThibG Date: Wed, 13 Feb 2019 18:33:03 +0100 Subject: [PATCH 07/27] Disable box shadows for featured hashtags in light theme (#10034) Fixes #9990 --- app/javascript/styles/mastodon-light/diff.scss | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/javascript/styles/mastodon-light/diff.scss b/app/javascript/styles/mastodon-light/diff.scss index 78bc2dbb6d5..de03cf1a667 100644 --- a/app/javascript/styles/mastodon-light/diff.scss +++ b/app/javascript/styles/mastodon-light/diff.scss @@ -352,6 +352,8 @@ .moved-account-widget, .memoriam-widget, .activity-stream, -.nothing-here { +.nothing-here, +.directory__tag > a, +.directory__tag > div { box-shadow: none; } From 169b9d4428d8e54d7bee365fd76be9a6e2a92da5 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Wed, 13 Feb 2019 18:34:58 +0100 Subject: [PATCH 08/27] Fix hashtags select styling in default and high contrast themes (#10029) --- .../components/column_settings.js | 55 ++++++----- app/javascript/styles/mastodon/_mixins.scss | 31 ++++++ .../styles/mastodon/components.scss | 95 +++++++++++++------ 3 files changed, 128 insertions(+), 53 deletions(-) diff --git a/app/javascript/mastodon/features/hashtag_timeline/components/column_settings.js b/app/javascript/mastodon/features/hashtag_timeline/components/column_settings.js index 9c9f62d8211..cdc138c8bf3 100644 --- a/app/javascript/mastodon/features/hashtag_timeline/components/column_settings.js +++ b/app/javascript/mastodon/features/hashtag_timeline/components/column_settings.js @@ -1,10 +1,15 @@ import React from 'react'; import PropTypes from 'prop-types'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import { injectIntl, FormattedMessage } from 'react-intl'; +import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import Toggle from 'react-toggle'; import AsyncSelect from 'react-select/lib/Async'; +const messages = defineMessages({ + placeholder: { id: 'hashtag.column_settings.select.placeholder', defaultMessage: 'Enter hashtags…' }, + noOptions: { id: 'hashtag.column_settings.select.no_options_message', defaultMessage: 'No suggestions found' }, +}); + export default @injectIntl class ColumnSettings extends React.PureComponent { @@ -25,6 +30,7 @@ class ColumnSettings extends React.PureComponent { tags (mode) { let tags = this.props.settings.getIn(['tags', mode]) || []; + if (tags.toJSON) { return tags.toJSON(); } else { @@ -32,33 +38,36 @@ class ColumnSettings extends React.PureComponent { } }; - onSelect = (mode) => { - return (value) => { - this.props.onChange(['tags', mode], value); - }; - }; + onSelect = mode => value => this.props.onChange(['tags', mode], value); onToggle = () => { if (this.state.open && this.hasTags()) { this.props.onChange('tags', {}); } + this.setState({ open: !this.state.open }); }; + noOptionsMessage = () => this.props.intl.formatMessage(messages.noOptions); + modeSelect (mode) { return ( -
- {this.modeLabel(mode)} +
+ + {this.modeLabel(mode)} + +
); @@ -66,11 +75,15 @@ class ColumnSettings extends React.PureComponent { modeLabel (mode) { switch(mode) { - case 'any': return ; - case 'all': return ; - case 'none': return ; + case 'any': + return ; + case 'all': + return ; + case 'none': + return ; + default: + return ''; } - return ''; }; render () { @@ -78,23 +91,21 @@ class ColumnSettings extends React.PureComponent {
- + +
- {this.state.open && + + {this.state.open && (
{this.modeSelect('any')} {this.modeSelect('all')} {this.modeSelect('none')}
- } + )}
); } diff --git a/app/javascript/styles/mastodon/_mixins.scss b/app/javascript/styles/mastodon/_mixins.scss index d5bafe6b6a2..08806599e8f 100644 --- a/app/javascript/styles/mastodon/_mixins.scss +++ b/app/javascript/styles/mastodon/_mixins.scss @@ -41,3 +41,34 @@ font-size: 16px; } } + +@mixin search-popout() { + background: $simple-background-color; + border-radius: 4px; + padding: 10px 14px; + padding-bottom: 14px; + margin-top: 10px; + color: $light-text-color; + box-shadow: 2px 4px 15px rgba($base-shadow-color, 0.4); + + h4 { + text-transform: uppercase; + color: $light-text-color; + font-size: 13px; + font-weight: 500; + margin-bottom: 10px; + } + + li { + padding: 4px 0; + } + + ul { + margin-bottom: 10px; + } + + em { + font-weight: 500; + color: $inverted-text-color; + } +} diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index 32fd773859e..02bbd345a7b 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -3056,14 +3056,41 @@ a.status-card.compact:hover { display: block; font-weight: 500; margin-bottom: 10px; +} - .column-settings__hashtag-select { +.column-settings__hashtags { + .column-settings__row { + margin-bottom: 15px; + } + + .column-select { &__control { @include search-input(); } + &__placeholder { + color: $dark-text-color; + padding-left: 2px; + font-size: 12px; + } + + &__value-container { + padding-left: 6px; + } + &__multi-value { background: lighten($ui-base-color, 8%); + + &__remove { + cursor: pointer; + + &:hover, + &:active, + &:focus { + background: lighten($ui-base-color, 12%); + color: lighten($darker-text-color, 4%); + } + } } &__multi-value__label, @@ -3071,9 +3098,42 @@ a.status-card.compact:hover { color: $darker-text-color; } - &__indicator-separator, + &__clear-indicator, &__dropdown-indicator { - display: none; + cursor: pointer; + transition: none; + color: $dark-text-color; + + &:hover, + &:active, + &:focus { + color: lighten($dark-text-color, 4%); + } + } + + &__indicator-separator { + background-color: lighten($ui-base-color, 8%); + } + + &__menu { + @include search-popout(); + padding: 0; + background: $ui-secondary-color; + } + + &__menu-list { + padding: 6px; + } + + &__option { + color: $inverted-text-color; + border-radius: 4px; + font-size: 14px; + + &--is-focused, + &--is-selected { + background: darken($ui-secondary-color, 10%); + } } } } @@ -4867,34 +4927,7 @@ a.status-card.compact:hover { } .search-popout { - background: $simple-background-color; - border-radius: 4px; - padding: 10px 14px; - padding-bottom: 14px; - margin-top: 10px; - color: $light-text-color; - box-shadow: 2px 4px 15px rgba($base-shadow-color, 0.4); - - h4 { - text-transform: uppercase; - color: $light-text-color; - font-size: 13px; - font-weight: 500; - margin-bottom: 10px; - } - - li { - padding: 4px 0; - } - - ul { - margin-bottom: 10px; - } - - em { - font-weight: 500; - color: $inverted-text-color; - } + @include search-popout(); } noscript { From 6a5307a5733e7872e7827f32b27111434e0307c4 Mon Sep 17 00:00:00 2001 From: ThibG Date: Wed, 13 Feb 2019 18:36:23 +0100 Subject: [PATCH 09/27] Alternative handling of private self-boosts (#9998) * When self-boosting, embed original toot into Announce serialization * Process unknown self-boosts from Announce object if it is more than an URI * Add some self-boost specs * Only serialize private toots in self-Announces --- app/lib/activitypub/activity.rb | 32 +++++++++++ app/lib/activitypub/activity/announce.rb | 4 +- app/lib/activitypub/activity/create.rb | 15 ------ .../activitypub/activity_serializer.rb | 8 ++- .../lib/activitypub/activity/announce_spec.rb | 53 ++++++++++++++++--- 5 files changed, 86 insertions(+), 26 deletions(-) diff --git a/app/lib/activitypub/activity.rb b/app/lib/activitypub/activity.rb index 919678618a3..7e4e195313a 100644 --- a/app/lib/activitypub/activity.rb +++ b/app/lib/activitypub/activity.rb @@ -4,6 +4,9 @@ class ActivityPub::Activity include JsonLdHelper include Redisable + SUPPORTED_TYPES = %w(Note).freeze + CONVERTED_TYPES = %w(Image Video Article Page).freeze + def initialize(json, account, **options) @json = json @account = account @@ -71,6 +74,18 @@ class ActivityPub::Activity @object_uri ||= value_or_id(@object) end + def unsupported_object_type? + @object.is_a?(String) || !(supported_object_type? || converted_object_type?) + end + + def supported_object_type? + equals_or_includes_any?(@object['type'], SUPPORTED_TYPES) + end + + def converted_object_type? + equals_or_includes_any?(@object['type'], CONVERTED_TYPES) + end + def distribute(status) crawl_links(status) @@ -120,6 +135,23 @@ class ActivityPub::Activity redis.setex("delete_upon_arrival:#{@account.id}:#{uri}", 6.hours.seconds, uri) end + def status_from_object + # If the status is already known, return it + status = status_from_uri(object_uri) + return status unless status.nil? + + # If the boosted toot is embedded and it is a self-boost, handle it like a Create + unless unsupported_object_type? + actor_id = value_or_id(first_of_value(@object['attributedTo'])) || @account.uri + if actor_id == @account.uri + return ActivityPub::Activity.factory({ 'type' => 'Create', 'actor' => actor_id, 'object' => @object }, @account).perform + end + end + + # If the status is not from the actor, try to fetch it + return fetch_remote_original_status if value_or_id(first_of_value(@json['attributedTo'])) == @account.uri + end + def fetch_remote_original_status if object_uri.start_with?('http') return if ActivityPub::TagManager.instance.local_uri?(object_uri) diff --git a/app/lib/activitypub/activity/announce.rb b/app/lib/activitypub/activity/announce.rb index 34d1b7cbd0f..04afeea202c 100644 --- a/app/lib/activitypub/activity/announce.rb +++ b/app/lib/activitypub/activity/announce.rb @@ -2,9 +2,7 @@ class ActivityPub::Activity::Announce < ActivityPub::Activity def perform - original_status = status_from_uri(object_uri) - original_status ||= fetch_remote_original_status - + original_status = status_from_object return if original_status.nil? || delete_arrived_first?(@json['id']) || !announceable?(original_status) status = Status.find_by(account: @account, reblog: original_status) diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index b49657d4b14..9a3db51dd9e 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -1,9 +1,6 @@ # frozen_string_literal: true class ActivityPub::Activity::Create < ActivityPub::Activity - SUPPORTED_TYPES = %w(Note).freeze - CONVERTED_TYPES = %w(Image Video Article Page).freeze - def perform return if unsupported_object_type? || invalid_origin?(@object['id']) return if Tombstone.exists?(uri: @object['id']) @@ -318,22 +315,10 @@ class ActivityPub::Activity::Create < ActivityPub::Activity @object['nameMap'].is_a?(Hash) && !@object['nameMap'].empty? end - def unsupported_object_type? - @object.is_a?(String) || !(supported_object_type? || converted_object_type?) - end - def unsupported_media_type?(mime_type) mime_type.present? && !(MediaAttachment::IMAGE_MIME_TYPES + MediaAttachment::VIDEO_MIME_TYPES).include?(mime_type) end - def supported_object_type? - equals_or_includes_any?(@object['type'], SUPPORTED_TYPES) - end - - def converted_object_type? - equals_or_includes_any?(@object['type'], CONVERTED_TYPES) - end - def skip_download? return @skip_download if defined?(@skip_download) @skip_download ||= DomainBlock.find_by(domain: @account.domain)&.reject_media? diff --git a/app/serializers/activitypub/activity_serializer.rb b/app/serializers/activitypub/activity_serializer.rb index 50c4f6a049a..b51e8c54429 100644 --- a/app/serializers/activitypub/activity_serializer.rb +++ b/app/serializers/activitypub/activity_serializer.rb @@ -3,8 +3,8 @@ class ActivityPub::ActivitySerializer < ActiveModel::Serializer attributes :id, :type, :actor, :published, :to, :cc - has_one :proper, key: :object, serializer: ActivityPub::NoteSerializer, unless: :announce? - attribute :proper_uri, key: :object, if: :announce? + has_one :proper, key: :object, serializer: ActivityPub::NoteSerializer, unless: :owned_announce? + attribute :proper_uri, key: :object, if: :owned_announce? attribute :atom_uri, if: :announce? def id @@ -42,4 +42,8 @@ class ActivityPub::ActivitySerializer < ActiveModel::Serializer def announce? object.reblog? end + + def owned_announce? + announce? && object.account == object.proper.account && object.proper.private_visibility? + end end diff --git a/spec/lib/activitypub/activity/announce_spec.rb b/spec/lib/activitypub/activity/announce_spec.rb index 54dd52a6049..1725c2843bb 100644 --- a/spec/lib/activitypub/activity/announce_spec.rb +++ b/spec/lib/activitypub/activity/announce_spec.rb @@ -1,7 +1,7 @@ require 'rails_helper' RSpec.describe ActivityPub::Activity::Announce do - let(:sender) { Fabricate(:account) } + let(:sender) { Fabricate(:account, followers_url: 'http://example.com/followers') } let(:recipient) { Fabricate(:account) } let(:status) { Fabricate(:status, account: recipient) } @@ -11,19 +11,60 @@ RSpec.describe ActivityPub::Activity::Announce do id: 'foo', type: 'Announce', actor: ActivityPub::TagManager.instance.uri_for(sender), - object: ActivityPub::TagManager.instance.uri_for(status), + object: object_json, }.with_indifferent_access end - describe '#perform' do - subject { described_class.new(json, sender) } + subject { described_class.new(json, sender) } + before do + sender.update(uri: ActivityPub::TagManager.instance.uri_for(sender)) + end + + describe '#perform' do before do subject.perform end - it 'creates a reblog by sender of status' do - expect(sender.reblogged?(status)).to be true + context 'a known status' do + let(:object_json) do + ActivityPub::TagManager.instance.uri_for(status) + end + + it 'creates a reblog by sender of status' do + expect(sender.reblogged?(status)).to be true + end + end + + context 'self-boost of a previously unknown status with missing attributedTo' do + let(:object_json) do + { + id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join, + type: 'Note', + content: 'Lorem ipsum', + to: 'http://example.com/followers', + } + end + + it 'creates a reblog by sender of status' do + expect(sender.reblogged?(sender.statuses.first)).to be true + end + end + + context 'self-boost of a previously unknown status with correct attributedTo' do + let(:object_json) do + { + id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join, + type: 'Note', + content: 'Lorem ipsum', + attributedTo: ActivityPub::TagManager.instance.uri_for(sender), + to: 'http://example.com/followers', + } + end + + it 'creates a reblog by sender of status' do + expect(sender.reblogged?(sender.statuses.first)).to be true + end end end end From 114cdc36aad7247ffa886674ae40021516d53420 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Wed, 13 Feb 2019 18:36:40 +0100 Subject: [PATCH 10/27] Fix style regressions on landing page (#10030) --- app/javascript/styles/mastodon/about.scss | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/app/javascript/styles/mastodon/about.scss b/app/javascript/styles/mastodon/about.scss index b6c92a09e7d..b078d4d24d5 100644 --- a/app/javascript/styles/mastodon/about.scss +++ b/app/javascript/styles/mastodon/about.scss @@ -49,15 +49,9 @@ $small-breakpoint: 960px; } } + strong, em { - display: inline; - margin: 0; - padding: 0; font-weight: 700; - background: transparent; - font-family: inherit; - font-size: inherit; - line-height: inherit; color: lighten($darker-text-color, 10%); } @@ -796,7 +790,7 @@ $small-breakpoint: 960px; width: 100%; display: flex; flex-direction: row-reverse; - flex-wrap: wrap; + flex-wrap: nowrap; justify-content: space-between; align-items: center; } @@ -846,14 +840,7 @@ $small-breakpoint: 960px; } strong { - display: inline; - margin: 0; - padding: 0; - font-weight: 700; - background: transparent; - font-family: inherit; - font-size: inherit; - line-height: inherit; + font-weight: 500; color: lighten($darker-text-color, 10%); } From 011b476d38663656988ae21ca29689aae01cb7c2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Wed, 13 Feb 2019 18:37:27 +0100 Subject: [PATCH 11/27] Bump faker from 1.9.2 to 1.9.3 (#10031) Bumps [faker](https://github.com/stympy/faker) from 1.9.2 to 1.9.3. - [Release notes](https://github.com/stympy/faker/releases) - [Changelog](https://github.com/stympy/faker/blob/master/CHANGELOG.md) - [Commits](https://github.com/stympy/faker/compare/v1.9.2...v1.9.3) Signed-off-by: dependabot[bot] --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 05622340b79..ee536f2ab63 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -205,7 +205,7 @@ GEM tzinfo excon (0.62.0) fabrication (2.20.1) - faker (1.9.2) + faker (1.9.3) i18n (>= 0.7) faraday (0.15.0) multipart-post (>= 1.2, < 3) From dad339da6d19679f0361bfd49d9bcf3a3517af0c Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Wed, 13 Feb 2019 18:42:47 +0100 Subject: [PATCH 12/27] Filter incoming Create activities by relation to local activity (#10005) Reject those from accounts with no local followers, from relays that are not enabled, which do not address local accounts and are not replies to accounts that do have local followers --- app/lib/activitypub/activity/create.rb | 34 +++++++++++++++++-- .../activitypub/process_collection_service.rb | 1 + app/workers/activitypub/processing_worker.rb | 2 +- 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index 9a3db51dd9e..1b31768d964 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -2,8 +2,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity def perform - return if unsupported_object_type? || invalid_origin?(@object['id']) - return if Tombstone.exists?(uri: @object['id']) + return if unsupported_object_type? || invalid_origin?(@object['id']) || Tombstone.exists?(uri: @object['id']) || !related_to_local_activity? RedisLock.acquire(lock_options) do |lock| if lock.acquired? @@ -337,6 +336,37 @@ class ActivityPub::Activity::Create < ActivityPub::Activity !replied_to_status.nil? && replied_to_status.account.local? end + def related_to_local_activity? + fetch? || followed_by_local_accounts? || requested_through_relay? || + responds_to_followed_account? || addresses_local_accounts? + end + + def fetch? + !@options[:delivery] + end + + def followed_by_local_accounts? + @account.passive_relationships.exists? + end + + def requested_through_relay? + @options[:relayed_through_account] && Relay.find_by(inbox_url: @options[:relayed_through_account].inbox_url)&.enabled? + end + + def responds_to_followed_account? + !replied_to_status.nil? && (replied_to_status.account.local? || replied_to_status.account.passive_relationships.exists?) + end + + def addresses_local_accounts? + return true if @options[:delivered_to_account_id] + + local_usernames = (as_array(@object['to']) + as_array(@object['cc'])).uniq.select { |uri| ActivityPub::TagManager.instance.local_uri?(uri) }.map { |uri| ActivityPub::TagManager.instance.uri_to_local_id(uri, :username) } + + return false if local_usernames.empty? + + Account.local.where(username: local_usernames).exists? + end + def forward_for_reply return unless @json['signature'].present? && reply_to_local? ActivityPub::RawDistributionWorker.perform_async(Oj.dump(@json), replied_to_status.account_id, [@account.preferred_inbox_url]) diff --git a/app/services/activitypub/process_collection_service.rb b/app/services/activitypub/process_collection_service.rb index 5c54aad89f1..881df478bf5 100644 --- a/app/services/activitypub/process_collection_service.rb +++ b/app/services/activitypub/process_collection_service.rb @@ -44,6 +44,7 @@ class ActivityPub::ProcessCollectionService < BaseService end def verify_account! + @options[:relayed_through_account] = @account @account = ActivityPub::LinkedDataSignature.new(@json).verify_account! rescue JSON::LD::JsonLdError => e Rails.logger.debug "Could not verify LD-Signature for #{value_or_id(@json['actor'])}: #{e.message}" diff --git a/app/workers/activitypub/processing_worker.rb b/app/workers/activitypub/processing_worker.rb index a8a3ebf0f56..a3abe72cf66 100644 --- a/app/workers/activitypub/processing_worker.rb +++ b/app/workers/activitypub/processing_worker.rb @@ -6,6 +6,6 @@ class ActivityPub::ProcessingWorker sidekiq_options backtrace: true def perform(account_id, body, delivered_to_account_id = nil) - ActivityPub::ProcessCollectionService.new.call(body, Account.find(account_id), override_timestamps: true, delivered_to_account_id: delivered_to_account_id) + ActivityPub::ProcessCollectionService.new.call(body, Account.find(account_id), override_timestamps: true, delivered_to_account_id: delivered_to_account_id, delivery: true) end end From 188f1c7c89d6fc7349302a9680bac9a82515cb90 Mon Sep 17 00:00:00 2001 From: ThibG Date: Wed, 13 Feb 2019 18:52:02 +0100 Subject: [PATCH 13/27] Add list title editing (#9748) * Add list title editing Port changes made by ash for glitch-soc * Code style fixes --- .../list_editor/components/edit_list_form.js | 70 +++++++++++++++++++ .../mastodon/features/list_editor/index.js | 7 +- .../mastodon/reducers/list_editor.js | 11 ++- .../styles/mastodon/components.scss | 2 +- 4 files changed, 83 insertions(+), 7 deletions(-) create mode 100644 app/javascript/mastodon/features/list_editor/components/edit_list_form.js diff --git a/app/javascript/mastodon/features/list_editor/components/edit_list_form.js b/app/javascript/mastodon/features/list_editor/components/edit_list_form.js new file mode 100644 index 00000000000..3dc59c12e76 --- /dev/null +++ b/app/javascript/mastodon/features/list_editor/components/edit_list_form.js @@ -0,0 +1,70 @@ +import React from 'react'; +import { connect } from 'react-redux'; +import PropTypes from 'prop-types'; +import { changeListEditorTitle, submitListEditor } from '../../../actions/lists'; +import IconButton from '../../../components/icon_button'; +import { defineMessages, injectIntl } from 'react-intl'; + +const messages = defineMessages({ + title: { id: 'lists.edit.submit', defaultMessage: 'Change title' }, +}); + +const mapStateToProps = state => ({ + value: state.getIn(['listEditor', 'title']), + disabled: !state.getIn(['listEditor', 'isChanged']), +}); + +const mapDispatchToProps = dispatch => ({ + onChange: value => dispatch(changeListEditorTitle(value)), + onSubmit: () => dispatch(submitListEditor(false)), +}); + +export default @connect(mapStateToProps, mapDispatchToProps) +@injectIntl +class ListForm extends React.PureComponent { + + static propTypes = { + value: PropTypes.string.isRequired, + disabled: PropTypes.bool, + intl: PropTypes.object.isRequired, + onChange: PropTypes.func.isRequired, + onSubmit: PropTypes.func.isRequired, + }; + + handleChange = e => { + this.props.onChange(e.target.value); + } + + handleSubmit = e => { + e.preventDefault(); + this.props.onSubmit(); + } + + handleClick = () => { + this.props.onSubmit(); + } + + render () { + const { value, disabled, intl } = this.props; + + const title = intl.formatMessage(messages.title); + + return ( +
+ + + + + ); + } + +} diff --git a/app/javascript/mastodon/features/list_editor/index.js b/app/javascript/mastodon/features/list_editor/index.js index aab0cdd0c0c..48466604a7d 100644 --- a/app/javascript/mastodon/features/list_editor/index.js +++ b/app/javascript/mastodon/features/list_editor/index.js @@ -7,11 +7,11 @@ import { injectIntl } from 'react-intl'; import { setupListEditor, clearListSuggestions, resetListEditor } from '../../actions/lists'; import Account from './components/account'; import Search from './components/search'; +import EditListForm from './components/edit_list_form'; import Motion from '../ui/util/optional_motion'; import spring from 'react-motion/lib/spring'; const mapStateToProps = state => ({ - title: state.getIn(['listEditor', 'title']), accountIds: state.getIn(['listEditor', 'accounts', 'items']), searchAccountIds: state.getIn(['listEditor', 'suggestions', 'items']), }); @@ -33,7 +33,6 @@ class ListEditor extends ImmutablePureComponent { onInitialize: PropTypes.func.isRequired, onClear: PropTypes.func.isRequired, onReset: PropTypes.func.isRequired, - title: PropTypes.string.isRequired, accountIds: ImmutablePropTypes.list.isRequired, searchAccountIds: ImmutablePropTypes.list.isRequired, }; @@ -49,12 +48,12 @@ class ListEditor extends ImmutablePureComponent { } render () { - const { title, accountIds, searchAccountIds, onClear } = this.props; + const { accountIds, searchAccountIds, onClear } = this.props; const showSearch = searchAccountIds.size > 0; return (
-

{title}

+ diff --git a/app/javascript/mastodon/reducers/list_editor.js b/app/javascript/mastodon/reducers/list_editor.js index 02a0dabb147..91e524dd550 100644 --- a/app/javascript/mastodon/reducers/list_editor.js +++ b/app/javascript/mastodon/reducers/list_editor.js @@ -22,6 +22,7 @@ import { const initialState = ImmutableMap({ listId: null, isSubmitting: false, + isChanged: false, title: '', accounts: ImmutableMap({ @@ -47,10 +48,16 @@ export default function listEditorReducer(state = initialState, action) { map.set('isSubmitting', false); }); case LIST_EDITOR_TITLE_CHANGE: - return state.set('title', action.value); + return state.withMutations(map => { + map.set('title', action.value); + map.set('isChanged', true); + }); case LIST_CREATE_REQUEST: case LIST_UPDATE_REQUEST: - return state.set('isSubmitting', true); + return state.withMutations(map => { + map.set('isSubmitting', true); + map.set('isChanged', false); + }); case LIST_CREATE_FAIL: case LIST_UPDATE_FAIL: return state.set('isSubmitting', false); diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index 02bbd345a7b..8533e4eb5b8 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -5163,7 +5163,7 @@ noscript { .icon-button { flex: 0 0 auto; - margin-left: 5px; + margin: 0 5px; } } From 658b4621a622364d8daf699a7e46c65f3f63486b Mon Sep 17 00:00:00 2001 From: Nolan Lawson Date: Wed, 13 Feb 2019 09:52:36 -0800 Subject: [PATCH 14/27] perf: run node directly when streaming (#10032) --- dist/mastodon-streaming.service | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist/mastodon-streaming.service b/dist/mastodon-streaming.service index 5d7c129dfbb..c324fccf467 100644 --- a/dist/mastodon-streaming.service +++ b/dist/mastodon-streaming.service @@ -9,7 +9,7 @@ WorkingDirectory=/home/mastodon/live Environment="NODE_ENV=production" Environment="PORT=4000" Environment="STREAMING_CLUSTER_NUM=1" -ExecStart=/usr/bin/npm run start +ExecStart=/usr/bin/node ./streaming TimeoutSec=15 Restart=always From 7750416597e4d172b1d4751215aac2a50cf528e3 Mon Sep 17 00:00:00 2001 From: Aditoo17 <42938951+Aditoo17@users.noreply.github.com> Date: Wed, 13 Feb 2019 17:53:01 +0000 Subject: [PATCH 15/27] I18n: Update Czech pluralization and fix some language names (#10015) * I18n: Update Czech pluralization * I18n: Fix some language names * I18n: Fix some language names --- app/helpers/settings_helper.rb | 12 ++++++------ config/locales/cs.yml | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/app/helpers/settings_helper.rb b/app/helpers/settings_helper.rb index 7a3ceca786a..e868b45c019 100644 --- a/app/helpers/settings_helper.rb +++ b/app/helpers/settings_helper.rb @@ -4,7 +4,7 @@ module SettingsHelper HUMAN_LOCALES = { en: 'English', ar: 'العربية', - ast: 'l\'asturianu', + ast: 'Asturianu', bg: 'Български', ca: 'Català', co: 'Corsu', @@ -30,16 +30,16 @@ module SettingsHelper ja: '日本語', ka: 'ქართული', ko: '한국어', - lv: 'Latviešu valoda', + lv: 'Latviešu', ml: 'മലയാളം', - ms: 'بهاس ملايو', + ms: 'Bahasa Melayu', nl: 'Nederlands', no: 'Norsk', oc: 'Occitan', - pl: 'Polszczyzna', + pl: 'Polski', pt: 'Português', 'pt-BR': 'Português do Brasil', - ro: 'Limba română', + ro: 'Română', ru: 'Русский', sk: 'Slovenčina', sl: 'Slovenščina', @@ -49,7 +49,7 @@ module SettingsHelper sv: 'Svenska', ta: 'தமிழ்', te: 'తెలుగు', - th: 'ภาษาไทย', + th: 'ไทย', tr: 'Türkçe', uk: 'Українська', zh: '中文', diff --git a/config/locales/cs.yml b/config/locales/cs.yml index d1f11261cc0..c75d0b643c9 100644 --- a/config/locales/cs.yml +++ b/config/locales/cs.yml @@ -46,7 +46,7 @@ cs: choices_html: 'Volby uživatele %{name}:' follow: Sledovat followers: - few: Sledovatelé + few: Sledující one: Sledující other: Sledujících following: Sledovaných @@ -618,7 +618,7 @@ cs: lock_link: Zamkněte svůj účet purge: Odstranit ze sledujících success: - few: V průběhu blokování sledovatelů ze %{count} domén... + few: V průběhu blokování sledujících ze %{count} domén... one: V průběhu blokování sledujících z jedné domény... other: V průběhu blokování sledujících z %{count} domén... true_privacy_html: Berte prosím na vědomí, že skutečného soukromí se dá dosáhnout pouze za pomoci end-to-end šifrování. @@ -688,7 +688,7 @@ cs: body: Zde najdete stručný souhrn zpráv, které jste zmeškal/a od vaší poslední návštěvy %{since} mention: "%{name} vás zmínil/a v:" new_followers_summary: - few: Navíc jste získal/a %{count} nové sledovatele, zatímco jste byl/a pryč! Skvělé! + few: Navíc jste získal/a %{count} nové sledující, zatímco jste byl/a pryč! Skvělé! one: Navíc jste získal/a jednoho nového sledujícího, zatímco jste byl/a pryč! Hurá! other: Navíc jste získal/a %{count} nových sledujících, zatímco jste byl/a pryč! Úžasné! subject: From 80161f43510ad9316c60c9b50dd5c09c2dae4d54 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Wed, 13 Feb 2019 21:28:18 +0100 Subject: [PATCH 16/27] Change robots.txt to exclude some URLs (#10037) - Exclude static assets - Exclude uploaded files - Exclude alternate versions of the profile page - Exclude media proxy URLs --- public/robots.txt | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/public/robots.txt b/public/robots.txt index 3c9c7c01f30..36afc85eff5 100644 --- a/public/robots.txt +++ b/public/robots.txt @@ -1,5 +1,13 @@ -# See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file -# -# To ban all spiders from the entire site uncomment the next two lines: -# User-agent: * -# Disallow: / +User-Agent: * +Disallow: /users/*/followers +Disallow: /users/*/following +Disallow: /@*/media +Disallow: /@*/with_replies +Disallow: /@*/tagged/* +Disallow: /media_proxy/* +Disallow: /emoji/* +Disallow: /packs/* +Disallow: /sounds/* +Disallow: /system/* +Disallow: /avatars/* +Disallow: /headers/* From 309043b158f5a4187b6f603f346ed17ee6ddb190 Mon Sep 17 00:00:00 2001 From: Ben Lubar Date: Wed, 13 Feb 2019 18:04:43 -0600 Subject: [PATCH 17/27] Improve image description user experience (#10036) * Add image descriptions to searchable post content. * Allow multi-line image descriptions. * Request image descriptions in the same query as posts when creating the search index. (see https://github.com/tootsuite/mastodon/pull/10036#discussion_r256551624) --- app/chewy/statuses_index.rb | 4 ++-- app/javascript/mastodon/features/compose/components/upload.js | 3 +-- app/javascript/styles/mastodon/components.scss | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/app/chewy/statuses_index.rb b/app/chewy/statuses_index.rb index d3104172c48..eafc1818b8f 100644 --- a/app/chewy/statuses_index.rb +++ b/app/chewy/statuses_index.rb @@ -31,7 +31,7 @@ class StatusesIndex < Chewy::Index }, } - define_type ::Status.unscoped.without_reblogs do + define_type ::Status.unscoped.without_reblogs.includes(:media_attachments) do crutch :mentions do |collection| data = ::Mention.where(status_id: collection.map(&:id)).pluck(:status_id, :account_id) data.each.with_object({}) { |(id, name), result| (result[id] ||= []).push(name) } @@ -50,7 +50,7 @@ class StatusesIndex < Chewy::Index root date_detection: false do field :account_id, type: 'long' - field :text, type: 'text', value: ->(status) { [status.spoiler_text, Formatter.instance.plaintext(status)].join("\n\n") } do + field :text, type: 'text', value: ->(status) { [status.spoiler_text, Formatter.instance.plaintext(status)].concat(status.media_attachments.map(&:description)).join("\n\n") } do field :stemmed, type: 'text', analyzer: 'content' end diff --git a/app/javascript/mastodon/features/compose/components/upload.js b/app/javascript/mastodon/features/compose/components/upload.js index 038d7ee28af..629cbc36ac3 100644 --- a/app/javascript/mastodon/features/compose/components/upload.js +++ b/app/javascript/mastodon/features/compose/components/upload.js @@ -108,9 +108,8 @@ class Upload extends ImmutablePureComponent {