From a60f90b0789b791cc1313589beb327b0dce924af Mon Sep 17 00:00:00 2001 From: ThibG Date: Tue, 12 Feb 2019 22:24:14 +0100 Subject: [PATCH 01/24] 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 f2a832542f..ad7b1859f6 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 394cc99d666fbd75d7545eceb0c3336a8aec70ff Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Wed, 13 Feb 2019 02:45:01 +0100 Subject: [PATCH 02/24] 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 c47f4e9307..9d4252f163 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 194afac341e69b604e09a01576305bcb2608a261 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Wed, 13 Feb 2019 02:54:27 +0100 Subject: [PATCH 03/24] 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 9d4252f163..30c7d31d95 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 222b0095bbd3dcb7f08f72fe0eeec5b2fa3a01ee Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Wed, 13 Feb 2019 02:54:48 +0100 Subject: [PATCH 04/24] 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 30c7d31d95..d60eb1c141 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 ee737fbbd3eb8c0f67adf59a125319de4b72989e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Wed, 13 Feb 2019 02:55:06 +0100 Subject: [PATCH 05/24] 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 d924a546ba..e01d168b63 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 d60eb1c141..05622340b7 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 a90bbe9bc165f3abe5e3e27e3ce79c64988765b9 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Wed, 13 Feb 2019 05:30:49 +0100 Subject: [PATCH 06/24] 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 7d8993a508..8429103b8a 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 bf0c9d7dfaf6975a4980bbb54c1a090133c684fc Mon Sep 17 00:00:00 2001 From: ThibG Date: Wed, 13 Feb 2019 18:33:03 +0100 Subject: [PATCH 07/24] 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 78bc2dbb6d..de03cf1a66 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 bc9930f59da7403fa9dd7f553531c7bd056faf2a Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Wed, 13 Feb 2019 18:34:58 +0100 Subject: [PATCH 08/24] 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 9c9f62d821..cdc138c8bf 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 d5bafe6b6a..08806599e8 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 32fd773859..02bbd345a7 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__hashtags { + .column-settings__row { + margin-bottom: 15px; + } - .column-settings__hashtag-select { + .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 99dcb6d910eed4f4f252af3a60500ac692097f1d Mon Sep 17 00:00:00 2001 From: ThibG Date: Wed, 13 Feb 2019 18:36:23 +0100 Subject: [PATCH 09/24] 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 919678618a..7e4e195313 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 34d1b7cbd0..04afeea202 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 b49657d4b1..9a3db51dd9 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 50c4f6a049..b51e8c5442 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 54dd52a604..1725c2843b 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 72190529d0aae9f8a703f214de511c324947f1ba Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Wed, 13 Feb 2019 18:36:40 +0100 Subject: [PATCH 10/24] 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 b6c92a09e7..b078d4d24d 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 a4cfb5c36b9b805276854a7accc4ad8390f3c844 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Wed, 13 Feb 2019 18:37:27 +0100 Subject: [PATCH 11/24] 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 05622340b7..ee536f2ab6 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 ddbf75ea87229b596ef4023a425a802c3c52e4fe Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Wed, 13 Feb 2019 18:42:47 +0100 Subject: [PATCH 12/24] 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 9a3db51dd9..1b31768d96 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 5c54aad89f..881df478bf 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 a8a3ebf0f5..a3abe72cf6 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 793946fadb17ca27f7f83ffeef89a64c4e7e866e Mon Sep 17 00:00:00 2001 From: ThibG Date: Wed, 13 Feb 2019 18:52:02 +0100 Subject: [PATCH 13/24] 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 0000000000..3dc59c12e7 --- /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 aab0cdd0c0..48466604a7 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 02a0dabb14..91e524dd55 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 02bbd345a7..8533e4eb5b 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 4a515905fcdc442a63950481fb85e71ff802478b Mon Sep 17 00:00:00 2001 From: Nolan Lawson Date: Wed, 13 Feb 2019 09:52:36 -0800 Subject: [PATCH 14/24] 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 5d7c129dfb..c324fccf46 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 f24e258692f44ee245ca4f59e16e6a8283a2f71e 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/24] 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 7a3ceca786..e868b45c01 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 d1f11261cc..c75d0b643c 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 0e8ebc2371f19ea501e5018c04b497849c2dab4d Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Wed, 13 Feb 2019 21:28:18 +0100 Subject: [PATCH 16/24] 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 3c9c7c01f3..36afc85eff 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 a679867d38c8a6c37336b9a1147d980e8b1cad90 Mon Sep 17 00:00:00 2001 From: Ben Lubar Date: Wed, 13 Feb 2019 18:04:43 -0600 Subject: [PATCH 17/24] 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 d3104172c4..eafc1818b8 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 038d7ee28a..629cbc36ac 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 {