From 35b142a7ad19821483f900e81e915a7925fd4eaf Mon Sep 17 00:00:00 2001 From: ThibG Date: Sat, 30 Nov 2019 18:19:47 +0100 Subject: Fix lost focus when modals open/close (#12437) * Fix lost focus after modal closes Regression caused by the use of the wicg-inert polyfill * Fix regression introduced by wicg-inert * Catch errors to please CodeClimate --- app/javascript/mastodon/components/modal_root.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/javascript/mastodon/components/modal_root.js b/app/javascript/mastodon/components/modal_root.js index c55fa0f74..fa4e59192 100644 --- a/app/javascript/mastodon/components/modal_root.js +++ b/app/javascript/mastodon/components/modal_root.js @@ -56,15 +56,21 @@ export default class ModalRoot extends React.PureComponent { } else if (!nextProps.children) { this.setState({ revealed: false }); } - if (!nextProps.children && !!this.props.children) { - this.activeElement.focus(); - this.activeElement = null; - } } componentDidUpdate (prevProps) { if (!this.props.children && !!prevProps.children) { this.getSiblings().forEach(sibling => sibling.removeAttribute('inert')); + + // Because of the wicg-inert polyfill, the activeElement may not be + // immediately selectable, we have to wait for observers to run, as + // described in https://github.com/WICG/inert#performance-and-gotchas + Promise.resolve().then(() => { + this.activeElement.focus(); + this.activeElement = null; + }).catch((error) => { + console.error(error); + }); } if (this.props.children) { requestAnimationFrame(() => { -- cgit From d8f96028c54bb47e6edddbd936bc8f2301dc9fa3 Mon Sep 17 00:00:00 2001 From: ThibG Date: Sat, 30 Nov 2019 19:53:58 +0100 Subject: Add ability to filter reports by target account domain (#12154) * Add ability to filter reports by target account domain * Reword by_target_domain label --- app/controllers/admin/reports_controller.rb | 3 ++- app/helpers/admin/filter_helper.rb | 2 +- app/models/report_filter.rb | 2 ++ app/views/admin/reports/index.html.haml | 14 ++++++++++++++ config/locales/en.yml | 1 + 5 files changed, 20 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/controllers/admin/reports_controller.rb b/app/controllers/admin/reports_controller.rb index f138376b2..09ce1761c 100644 --- a/app/controllers/admin/reports_controller.rb +++ b/app/controllers/admin/reports_controller.rb @@ -55,7 +55,8 @@ module Admin params.permit( :account_id, :resolved, - :target_account_id + :target_account_id, + :by_target_domain ) end diff --git a/app/helpers/admin/filter_helper.rb b/app/helpers/admin/filter_helper.rb index 8af1683e7..fc4f15985 100644 --- a/app/helpers/admin/filter_helper.rb +++ b/app/helpers/admin/filter_helper.rb @@ -2,7 +2,7 @@ module Admin::FilterHelper ACCOUNT_FILTERS = %i(local remote by_domain active pending silenced suspended username display_name email ip staff).freeze - REPORT_FILTERS = %i(resolved account_id target_account_id).freeze + REPORT_FILTERS = %i(resolved account_id target_account_id by_target_domain).freeze INVITE_FILTER = %i(available expired).freeze CUSTOM_EMOJI_FILTERS = %i(local remote by_domain shortcode).freeze TAGS_FILTERS = %i(directory reviewed unreviewed pending_review popular active name).freeze diff --git a/app/models/report_filter.rb b/app/models/report_filter.rb index a392d60c3..abf53cbab 100644 --- a/app/models/report_filter.rb +++ b/app/models/report_filter.rb @@ -19,6 +19,8 @@ class ReportFilter def scope_for(key, value) case key.to_sym + when :by_target_domain + Report.where(target_account: Account.where(domain: value)) when :resolved Report.resolved when :account_id diff --git a/app/views/admin/reports/index.html.haml b/app/views/admin/reports/index.html.haml index bfbd32108..b09472270 100644 --- a/app/views/admin/reports/index.html.haml +++ b/app/views/admin/reports/index.html.haml @@ -8,6 +8,20 @@ %li= filter_link_to t('admin.reports.unresolved'), resolved: nil %li= filter_link_to t('admin.reports.resolved'), resolved: '1' += form_tag admin_reports_url, method: 'GET', class: 'simple_form' do + .fields-group + - Admin::FilterHelper::REPORT_FILTERS.each do |key| + - if params[key].present? + = hidden_field_tag key, params[key] + + - %i(by_target_domain).each do |key| + .input.string.optional + = text_field_tag key, params[key], class: 'string optional', placeholder: I18n.t("admin.reports.#{key}") + + .actions + %button= t('admin.accounts.search') + = link_to t('admin.accounts.reset'), admin_reports_path, class: 'button negative' + - @reports.group_by(&:target_account_id).each do |target_account_id, reports| - target_account = reports.first.target_account .report-card diff --git a/config/locales/en.yml b/config/locales/en.yml index 783b7a4f6..e69b3596f 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -405,6 +405,7 @@ en: are_you_sure: Are you sure? assign_to_self: Assign to me assigned: Assigned moderator + by_target_domain: Domain of reported account comment: none: None created_at: Reported -- cgit From f05b0463dbc83a85dee7490e07bd79859132ee48 Mon Sep 17 00:00:00 2001 From: ThibG Date: Sat, 30 Nov 2019 19:58:00 +0100 Subject: Fallback to Create audience when object has no defined audience (#12249) Fixes #11137 --- app/lib/activitypub/activity/create.rb | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'app') diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index 76bf9b2e5..8a12a2b08 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -25,6 +25,14 @@ class ActivityPub::Activity::Create < ActivityPub::Activity private + def audience_to + @object['to'] || @json['to'] + end + + def audience_cc + @object['cc'] || @json['cc'] + end + def process_status @tags = [] @mentions = [] @@ -75,7 +83,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity end def process_audience - (as_array(@object['to']) + as_array(@object['cc'])).uniq.each do |audience| + (as_array(audience_to) + as_array(audience_cc)).uniq.each do |audience| next if audience == ActivityPub::TagManager::COLLECTIONS[:public] # Unlike with tags, there is no point in resolving accounts we don't already @@ -291,11 +299,11 @@ class ActivityPub::Activity::Create < ActivityPub::Activity end def visibility_from_audience - if equals_or_includes?(@object['to'], ActivityPub::TagManager::COLLECTIONS[:public]) + if equals_or_includes?(audience_to, ActivityPub::TagManager::COLLECTIONS[:public]) :public - elsif equals_or_includes?(@object['cc'], ActivityPub::TagManager::COLLECTIONS[:public]) + elsif equals_or_includes?(audience_cc, ActivityPub::TagManager::COLLECTIONS[:public]) :unlisted - elsif equals_or_includes?(@object['to'], @account.followers_url) + elsif equals_or_includes?(audience_to, @account.followers_url) :private else :direct @@ -304,7 +312,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity def audience_includes?(account) uri = ActivityPub::TagManager.instance.uri_for(account) - equals_or_includes?(@object['to'], uri) || equals_or_includes?(@object['cc'], uri) + equals_or_includes?(audience_to, uri) || equals_or_includes?(audience_cc, uri) end def replied_to_status @@ -415,7 +423,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity 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) } + local_usernames = (as_array(audience_to) + as_array(audience_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? -- cgit From ed73376f1ca7ef5e254a3ec21e1ead85b2d34fd6 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sun, 1 Dec 2019 07:06:20 +0100 Subject: Fix conversations not having an unread indicator in web UI (#12506) --- .../direct_timeline/components/conversation.js | 5 +++-- app/javascript/styles/mastodon/components.scss | 26 ++++++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/javascript/mastodon/features/direct_timeline/components/conversation.js b/app/javascript/mastodon/features/direct_timeline/components/conversation.js index 2cbaa0791..235cb7ad8 100644 --- a/app/javascript/mastodon/features/direct_timeline/components/conversation.js +++ b/app/javascript/mastodon/features/direct_timeline/components/conversation.js @@ -12,6 +12,7 @@ import IconButton from 'mastodon/components/icon_button'; import RelativeTimestamp from 'mastodon/components/relative_timestamp'; import { HotKeys } from 'react-hotkeys'; import { autoPlayGif } from 'mastodon/initial_state'; +import classNames from 'classnames'; const messages = defineMessages({ more: { id: 'status.more', defaultMessage: 'More' }, @@ -158,7 +159,7 @@ class Conversation extends ImmutablePureComponent { return ( -
+
@@ -166,7 +167,7 @@ class Conversation extends ImmutablePureComponent {
- + {unread && }
diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index 98ffe1c20..13f9dfae7 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -6517,6 +6517,16 @@ noscript { flex: 0 0 auto; padding: 10px; padding-top: 12px; + position: relative; + } + + &__unread { + display: inline-block; + background: $highlight-text-color; + border-radius: 50%; + width: 0.625rem; + height: 0.625rem; + margin: -.1ex .15em .1ex; } &__content { @@ -6564,4 +6574,20 @@ noscript { word-break: break-word; } } + + &--unread { + background: lighten($ui-base-color, 2%); + + &:focus { + background: lighten($ui-base-color, 4%); + } + + .conversation__content__info { + font-weight: 700; + } + + .conversation__content__relative-time { + color: $primary-text-color; + } + } } -- cgit From c8d82ef3c3cb6ef3be34787c28d1c6bf8edae441 Mon Sep 17 00:00:00 2001 From: Sasha Sorokin Date: Sun, 1 Dec 2019 13:08:40 +0700 Subject: Split relationships page strings (#12502) Before this moment relationships managing page was using strings from other context - from counters, but in order for translators to be able to translate it relatively to the page, it must use separate strings. I've split the strings for "Following" and "Followers" and put them to "relationships" keyset in localization file. This should solve this issue. Fixes #10863 --- app/views/relationships/show.html.haml | 4 ++-- config/locales/en.yml | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/views/relationships/show.html.haml b/app/views/relationships/show.html.haml index e6fff0ad6..0da1596ce 100644 --- a/app/views/relationships/show.html.haml +++ b/app/views/relationships/show.html.haml @@ -8,8 +8,8 @@ .filter-subset %strong= t 'relationships.relationship' %ul - %li= filter_link_to t('accounts.following', count: current_account.following_count), relationship: nil - %li= filter_link_to t('accounts.followers', count: current_account.followers_count), relationship: 'followed_by' + %li= filter_link_to t('relationships.following'), relationship: nil + %li= filter_link_to t('relationships.followers'), relationship: 'followed_by' %li= filter_link_to t('relationships.mutual'), relationship: 'mutual' .filter-subset diff --git a/config/locales/en.yml b/config/locales/en.yml index e69b3596f..d498f6ce3 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -925,6 +925,8 @@ en: relationships: activity: Account activity dormant: Dormant + followers: Followers + following: Following last_active: Last active most_recent: Most recent moved: Moved -- cgit From d70268f0991ba69568112d4da5768e821d5983dd Mon Sep 17 00:00:00 2001 From: Mathieu Brunot Date: Sun, 1 Dec 2019 07:21:28 +0100 Subject: :sparkles: Convert LDAP username (#12461) * :sparkles: Convert LDAP username #12021 Signed-off-by: mathieu.brunot * :bug: Fix conversion var use Signed-off-by: mathieu.brunot * :bug: Fix LDAP uid conversion test Signed-off-by: mathieu.brunot * :ok_hand: Remove comments with ref to PR Signed-off-by: mathieu.brunot * :ok_hand: Remove unnecessary paranthesis Signed-off-by: mathieu.brunot * :wrench: Move space in conversion string Signed-off-by: mathieu.brunot --- .env.nanobox | 3 +++ .env.production.sample | 3 +++ app/models/concerns/ldap_authenticable.rb | 12 ++++++++++-- config/initializers/devise.rb | 9 +++++++++ 4 files changed, 25 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/.env.nanobox b/.env.nanobox index cfbe487fb..fc6c3c42f 100644 --- a/.env.nanobox +++ b/.env.nanobox @@ -183,6 +183,9 @@ SMTP_FROM_ADDRESS=notifications@${APP_NAME}.nanoapp.io # LDAP_BIND_DN= # LDAP_PASSWORD= # LDAP_UID=cn +# LDAP_UID_CONVERSION_ENABLED=true +# LDAP_UID_CONVERSION_SEARCH=., - +# LDAP_UID_CONVERSION_REPLACE=_ # PAM authentication (optional) # PAM authentication uses for the email generation the "email" pam variable diff --git a/.env.production.sample b/.env.production.sample index f9a8bb7c1..6b078c7b2 100644 --- a/.env.production.sample +++ b/.env.production.sample @@ -179,6 +179,9 @@ STREAMING_CLUSTER_NUM=1 # LDAP_PASSWORD= # LDAP_UID=cn # LDAP_SEARCH_FILTER=%{uid}=%{email} +# LDAP_UID_CONVERSION_ENABLED=true +# LDAP_UID_CONVERSION_SEARCH=., - +# LDAP_UID_CONVERSION_REPLACE=_ # PAM authentication (optional) # PAM authentication uses for the email generation the "email" pam variable diff --git a/app/models/concerns/ldap_authenticable.rb b/app/models/concerns/ldap_authenticable.rb index 117993947..2d2e1edbb 100644 --- a/app/models/concerns/ldap_authenticable.rb +++ b/app/models/concerns/ldap_authenticable.rb @@ -14,10 +14,18 @@ module LdapAuthenticable end def ldap_get_user(attributes = {}) - resource = joins(:account).find_by(accounts: { username: attributes[Devise.ldap_uid.to_sym].first }) + safe_username = attributes[Devise.ldap_uid.to_sym].first + if Devise.ldap_uid_conversion_enabled + keys = Regexp.union(Devise.ldap_uid_conversion_search.chars) + replacement = Devise.ldap_uid_conversion_replace + + safe_username = safe_username.gsub(keys, replacement) + end + + resource = joins(:account).find_by(accounts: { username: safe_username }) if resource.blank? - resource = new(email: attributes[:mail].first, agreement: true, account_attributes: { username: attributes[Devise.ldap_uid.to_sym].first }, admin: false, external: true, confirmed_at: Time.now.utc) + resource = new(email: attributes[:mail].first, agreement: true, account_attributes: { username: safe_username }, admin: false, external: true, confirmed_at: Time.now.utc) resource.save! end diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index fd9a5a8b9..fa9fd8cc4 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -61,6 +61,12 @@ module Devise @@ldap_tls_no_verify = false mattr_accessor :ldap_search_filter @@ldap_search_filter = nil + mattr_accessor :ldap_uid_conversion_enabled + @@ldap_uid_conversion_enabled = false + mattr_accessor :ldap_uid_conversion_search + @@ldap_uid_conversion_search = nil + mattr_accessor :ldap_uid_conversion_replace + @@ldap_uid_conversion_replace = nil class Strategies::PamAuthenticatable def valid? @@ -365,5 +371,8 @@ Devise.setup do |config| config.ldap_uid = ENV.fetch('LDAP_UID', 'cn') config.ldap_tls_no_verify = ENV['LDAP_TLS_NO_VERIFY'] == 'true' config.ldap_search_filter = ENV.fetch('LDAP_SEARCH_FILTER', '%{uid}=%{email}') + config.ldap_uid_conversion_enabled = ENV['LDAP_UID_CONVERSION_ENABLED'] == 'true' + config.ldap_uid_conversion_search = ENV.fetch('LDAP_UID_CONVERSION_SEARCH', '.,- ') + config.ldap_uid_conversion_replace = ENV.fetch('LDAP_UID_CONVERSION_REPLACE', '_') end end -- cgit