Merge remote-tracking branch 'tootsuite/master' into glitchsoc/master
This commit is contained in:
		
						commit
						6290cd7969
					
				
					 14 changed files with 105 additions and 57 deletions
				
			
		
							
								
								
									
										1
									
								
								.babelrc
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								.babelrc
									
									
									
									
									
								
							|  | @ -4,7 +4,6 @@ | ||||||
|     [ |     [ | ||||||
|       "env", |       "env", | ||||||
|       { |       { | ||||||
|         "debug": true, |  | ||||||
|         "exclude": ["transform-async-to-generator", "transform-regenerator"], |         "exclude": ["transform-async-to-generator", "transform-regenerator"], | ||||||
|         "loose": true, |         "loose": true, | ||||||
|         "modules": false, |         "modules": false, | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								Gemfile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Gemfile
									
									
									
									
									
								
							|  | @ -73,7 +73,7 @@ gem 'mario-redis-lock', '~> 1.2', require: 'redis_lock' | ||||||
| gem 'rqrcode', '~> 0.10' | gem 'rqrcode', '~> 0.10' | ||||||
| gem 'ruby-oembed', '~> 0.12', require: 'oembed' | gem 'ruby-oembed', '~> 0.12', require: 'oembed' | ||||||
| gem 'ruby-progressbar', '~> 1.4' | gem 'ruby-progressbar', '~> 1.4' | ||||||
| gem 'sanitize', '~> 4.4' | gem 'sanitize', '~> 4.6.4' | ||||||
| gem 'sidekiq', '~> 5.0' | gem 'sidekiq', '~> 5.0' | ||||||
| gem 'sidekiq-scheduler', '~> 2.1' | gem 'sidekiq-scheduler', '~> 2.1' | ||||||
| gem 'sidekiq-unique-jobs', '~> 5.0' | gem 'sidekiq-unique-jobs', '~> 5.0' | ||||||
|  |  | ||||||
							
								
								
									
										12
									
								
								Gemfile.lock
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								Gemfile.lock
									
									
									
									
									
								
							|  | @ -290,7 +290,7 @@ GEM | ||||||
|       activesupport (>= 4, < 5.2) |       activesupport (>= 4, < 5.2) | ||||||
|       railties (>= 4, < 5.2) |       railties (>= 4, < 5.2) | ||||||
|       request_store (~> 1.0) |       request_store (~> 1.0) | ||||||
|     loofah (2.1.1) |     loofah (2.2.1) | ||||||
|       crass (~> 1.0.2) |       crass (~> 1.0.2) | ||||||
|       nokogiri (>= 1.5.9) |       nokogiri (>= 1.5.9) | ||||||
|     mail (2.7.0) |     mail (2.7.0) | ||||||
|  | @ -318,9 +318,9 @@ GEM | ||||||
|       net-ssh (>= 2.6.5) |       net-ssh (>= 2.6.5) | ||||||
|     net-ssh (4.2.0) |     net-ssh (4.2.0) | ||||||
|     nio4r (2.1.0) |     nio4r (2.1.0) | ||||||
|     nokogiri (1.8.1) |     nokogiri (1.8.2) | ||||||
|       mini_portile2 (~> 2.3.0) |       mini_portile2 (~> 2.3.0) | ||||||
|     nokogumbo (1.4.13) |     nokogumbo (1.5.0) | ||||||
|       nokogiri |       nokogiri | ||||||
|     nsa (0.2.4) |     nsa (0.2.4) | ||||||
|       activesupport (>= 4.2, < 6) |       activesupport (>= 4.2, < 6) | ||||||
|  | @ -499,10 +499,10 @@ GEM | ||||||
|     rufus-scheduler (3.4.2) |     rufus-scheduler (3.4.2) | ||||||
|       et-orbi (~> 1.0) |       et-orbi (~> 1.0) | ||||||
|     safe_yaml (1.0.4) |     safe_yaml (1.0.4) | ||||||
|     sanitize (4.5.0) |     sanitize (4.6.4) | ||||||
|       crass (~> 1.0.2) |       crass (~> 1.0.2) | ||||||
|       nokogiri (>= 1.4.4) |       nokogiri (>= 1.4.4) | ||||||
|       nokogumbo (~> 1.4.1) |       nokogumbo (~> 1.4) | ||||||
|     sass (3.5.3) |     sass (3.5.3) | ||||||
|       sass-listen (~> 4.0.0) |       sass-listen (~> 4.0.0) | ||||||
|     sass-listen (4.0.0) |     sass-listen (4.0.0) | ||||||
|  | @ -704,7 +704,7 @@ DEPENDENCIES | ||||||
|   rubocop |   rubocop | ||||||
|   ruby-oembed (~> 0.12) |   ruby-oembed (~> 0.12) | ||||||
|   ruby-progressbar (~> 1.4) |   ruby-progressbar (~> 1.4) | ||||||
|   sanitize (~> 4.4) |   sanitize (~> 4.6.4) | ||||||
|   scss_lint (~> 0.55) |   scss_lint (~> 0.55) | ||||||
|   sidekiq (~> 5.0) |   sidekiq (~> 5.0) | ||||||
|   sidekiq-bulk (~> 0.1.1) |   sidekiq-bulk (~> 0.1.1) | ||||||
|  |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| import api from '../api'; | import api from '../api'; | ||||||
|  | import { CancelToken } from 'axios'; | ||||||
| import { throttle } from 'lodash'; | import { throttle } from 'lodash'; | ||||||
| import { search as emojiSearch } from '../features/emoji/emoji_mart_search_light'; | import { search as emojiSearch } from '../features/emoji/emoji_mart_search_light'; | ||||||
| import { tagHistory } from '../settings'; | import { tagHistory } from '../settings'; | ||||||
|  | @ -11,6 +12,8 @@ import { | ||||||
|   refreshPublicTimeline, |   refreshPublicTimeline, | ||||||
| } from './timelines'; | } from './timelines'; | ||||||
| 
 | 
 | ||||||
|  | let cancelFetchComposeSuggestionsAccounts; | ||||||
|  | 
 | ||||||
| export const COMPOSE_CHANGE          = 'COMPOSE_CHANGE'; | export const COMPOSE_CHANGE          = 'COMPOSE_CHANGE'; | ||||||
| export const COMPOSE_SUBMIT_REQUEST  = 'COMPOSE_SUBMIT_REQUEST'; | export const COMPOSE_SUBMIT_REQUEST  = 'COMPOSE_SUBMIT_REQUEST'; | ||||||
| export const COMPOSE_SUBMIT_SUCCESS  = 'COMPOSE_SUBMIT_SUCCESS'; | export const COMPOSE_SUBMIT_SUCCESS  = 'COMPOSE_SUBMIT_SUCCESS'; | ||||||
|  | @ -257,13 +260,22 @@ export function undoUploadCompose(media_id) { | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| export function clearComposeSuggestions() { | export function clearComposeSuggestions() { | ||||||
|  |   if (cancelFetchComposeSuggestionsAccounts) { | ||||||
|  |     cancelFetchComposeSuggestionsAccounts(); | ||||||
|  |   } | ||||||
|   return { |   return { | ||||||
|     type: COMPOSE_SUGGESTIONS_CLEAR, |     type: COMPOSE_SUGGESTIONS_CLEAR, | ||||||
|   }; |   }; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const fetchComposeSuggestionsAccounts = throttle((dispatch, getState, token) => { | const fetchComposeSuggestionsAccounts = throttle((dispatch, getState, token) => { | ||||||
|  |   if (cancelFetchComposeSuggestionsAccounts) { | ||||||
|  |     cancelFetchComposeSuggestionsAccounts(); | ||||||
|  |   } | ||||||
|   api(getState).get('/api/v1/accounts/search', { |   api(getState).get('/api/v1/accounts/search', { | ||||||
|  |     cancelToken: new CancelToken(cancel => { | ||||||
|  |       cancelFetchComposeSuggestionsAccounts = cancel; | ||||||
|  |     }), | ||||||
|     params: { |     params: { | ||||||
|       q: token.slice(1), |       q: token.slice(1), | ||||||
|       resolve: false, |       resolve: false, | ||||||
|  |  | ||||||
|  | @ -94,9 +94,16 @@ class Request | ||||||
|   class Socket < TCPSocket |   class Socket < TCPSocket | ||||||
|     class << self |     class << self | ||||||
|       def open(host, *args) |       def open(host, *args) | ||||||
|         address = IPSocket.getaddress(host) |         outer_e = nil | ||||||
|         raise Mastodon::HostValidationError if PrivateAddressCheck.private_address? IPAddr.new(address) |         Addrinfo.foreach(host, nil, nil, :SOCK_STREAM) do |address| | ||||||
|         super address, *args |           begin | ||||||
|  |             raise Mastodon::HostValidationError if PrivateAddressCheck.private_address? IPAddr.new(address.ip_address) | ||||||
|  |             return super address.ip_address, *args | ||||||
|  |           rescue => e | ||||||
|  |             outer_e = e | ||||||
|  |           end | ||||||
|  |         end | ||||||
|  |         raise outer_e if outer_e | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|       alias new open |       alias new open | ||||||
|  |  | ||||||
|  | @ -47,7 +47,8 @@ | ||||||
| # | # | ||||||
| 
 | 
 | ||||||
| class Account < ApplicationRecord | class Account < ApplicationRecord | ||||||
|   MENTION_RE = /(?<=^|[^\/[:word:]])@(([a-z0-9_]+)(?:@[a-z0-9\.\-]+[a-z0-9]+)?)/i |   USERNAME_RE = /[a-z0-9_]+([a-z0-9_\.]+[a-z0-9_]+)?/i | ||||||
|  |   MENTION_RE  = /(?<=^|[^\/[:word:]])@((#{USERNAME_RE}?)(?:@[a-z0-9\.\-]+[a-z0-9]+)?)/i | ||||||
| 
 | 
 | ||||||
|   include AccountAvatar |   include AccountAvatar | ||||||
|   include AccountFinderConcern |   include AccountFinderConcern | ||||||
|  | @ -70,7 +71,8 @@ class Account < ApplicationRecord | ||||||
|   validates :username, uniqueness: { scope: :domain, case_sensitive: true }, if: -> { !local? && will_save_change_to_username? } |   validates :username, uniqueness: { scope: :domain, case_sensitive: true }, if: -> { !local? && will_save_change_to_username? } | ||||||
| 
 | 
 | ||||||
|   # Local user validations |   # Local user validations | ||||||
|   validates :username, format: { with: /\A[a-z0-9_]+\z/i }, uniqueness: { scope: :domain, case_sensitive: false }, length: { maximum: 30 }, if: -> { local? && will_save_change_to_username? } |   validates :username, format: { with: /\A#{USERNAME_RE}\z/i }, length: { maximum: 30 }, if: -> { local? && will_save_change_to_username? } | ||||||
|  |   validates_with UniqueUsernameValidator, if: -> { local? && will_save_change_to_username? } | ||||||
|   validates_with UnreservedUsernameValidator, if: -> { local? && will_save_change_to_username? } |   validates_with UnreservedUsernameValidator, if: -> { local? && will_save_change_to_username? } | ||||||
|   validates :display_name, length: { maximum: 30 }, if: -> { local? && will_save_change_to_display_name? } |   validates :display_name, length: { maximum: 30 }, if: -> { local? && will_save_change_to_display_name? } | ||||||
|   validate :note_length_does_not_exceed_length_limit, if: -> { local? && will_save_change_to_note? } |   validate :note_length_does_not_exceed_length_limit, if: -> { local? && will_save_change_to_note? } | ||||||
|  |  | ||||||
|  | @ -16,7 +16,7 @@ class ActivityPub::ProcessAccountService < BaseService | ||||||
| 
 | 
 | ||||||
|     RedisLock.acquire(lock_options) do |lock| |     RedisLock.acquire(lock_options) do |lock| | ||||||
|       if lock.acquired? |       if lock.acquired? | ||||||
|         @account        = Account.find_by(uri: @uri) |         @account        = Account.find_remote(@username, @domain) | ||||||
|         @old_public_key = @account&.public_key |         @old_public_key = @account&.public_key | ||||||
|         @old_protocol   = @account&.protocol |         @old_protocol   = @account&.protocol | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										14
									
								
								app/validators/unique_username_validator.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								app/validators/unique_username_validator.rb
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,14 @@ | ||||||
|  | # frozen_string_literal: true | ||||||
|  | 
 | ||||||
|  | class UniqueUsernameValidator < ActiveModel::Validator | ||||||
|  |   def validate(account) | ||||||
|  |     return if account.username.nil? | ||||||
|  | 
 | ||||||
|  |     normalized_username = account.username.downcase.delete('.') | ||||||
|  | 
 | ||||||
|  |     scope = Account.where(domain: nil, username: normalized_username) | ||||||
|  |     scope = scope.where.not(id: account.id) if account.persisted? | ||||||
|  | 
 | ||||||
|  |     account.errors.add(:username, :taken) if scope.exists? | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -77,9 +77,7 @@ module Mastodon | ||||||
|     ] |     ] | ||||||
| 
 | 
 | ||||||
|     config.i18n.default_locale = ENV['DEFAULT_LOCALE']&.to_sym |     config.i18n.default_locale = ENV['DEFAULT_LOCALE']&.to_sym | ||||||
|     if config.i18n.available_locales.include?(config.i18n.default_locale) |     unless config.i18n.available_locales.include?(config.i18n.default_locale) | ||||||
|       config.i18n.fallbacks = [:en] |  | ||||||
|     else |  | ||||||
|       config.i18n.default_locale = :en |       config.i18n.default_locale = :en | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -55,8 +55,8 @@ Rails.application.configure do | ||||||
|   # config.action_mailer.raise_delivery_errors = false |   # config.action_mailer.raise_delivery_errors = false | ||||||
| 
 | 
 | ||||||
|   # Enable locale fallbacks for I18n (makes lookups for any locale fall back to |   # Enable locale fallbacks for I18n (makes lookups for any locale fall back to | ||||||
|   # the I18n.default_locale when a translation cannot be found). |   # English when a translation cannot be found). | ||||||
|   config.i18n.fallbacks = true |   config.i18n.fallbacks = [:en] | ||||||
| 
 | 
 | ||||||
|   # Send deprecation notices to registered listeners. |   # Send deprecation notices to registered listeners. | ||||||
|   config.active_support.deprecation = :notify |   config.active_support.deprecation = :notify | ||||||
|  |  | ||||||
|  | @ -55,6 +55,8 @@ module Devise | ||||||
|   @@ldap_bind_dn = nil |   @@ldap_bind_dn = nil | ||||||
|   mattr_accessor :ldap_password |   mattr_accessor :ldap_password | ||||||
|   @@ldap_password = nil |   @@ldap_password = nil | ||||||
|  |   mattr_accessor :ldap_tls_no_verify | ||||||
|  |   @@ldap_tls_no_verify = false | ||||||
| 
 | 
 | ||||||
|   class Strategies::PamAuthenticatable |   class Strategies::PamAuthenticatable | ||||||
|     def valid? |     def valid? | ||||||
|  | @ -357,5 +359,6 @@ Devise.setup do |config| | ||||||
|     config.ldap_bind_dn        = ENV.fetch('LDAP_BIND_DN') |     config.ldap_bind_dn        = ENV.fetch('LDAP_BIND_DN') | ||||||
|     config.ldap_password       = ENV.fetch('LDAP_PASSWORD') |     config.ldap_password       = ENV.fetch('LDAP_PASSWORD') | ||||||
|     config.ldap_uid            = ENV.fetch('LDAP_UID', 'cn') |     config.ldap_uid            = ENV.fetch('LDAP_UID', 'cn') | ||||||
|  |     config.ldap_tls_no_verify  = ENV['LDAP_TLS_NO_VERIFY'] == 'true' | ||||||
|   end |   end | ||||||
| end | end | ||||||
|  |  | ||||||
|  | @ -1,10 +1,9 @@ | ||||||
| # frozen_string_literal: true | # frozen_string_literal: true | ||||||
| 
 | 
 | ||||||
| if ENV['LDAP_ENABLED'] == 'true' | require 'net/ldap' | ||||||
|   require 'net/ldap' | require 'devise/strategies/authenticatable' | ||||||
|   require 'devise/strategies/authenticatable' |  | ||||||
| 
 | 
 | ||||||
|   module Devise | module Devise | ||||||
|   module Strategies |   module Strategies | ||||||
|     class LdapAuthenticatable < Authenticatable |     class LdapAuthenticatable < Authenticatable | ||||||
|       def authenticate! |       def authenticate! | ||||||
|  | @ -15,7 +14,7 @@ if ENV['LDAP_ENABLED'] == 'true' | ||||||
|             base: Devise.ldap_base, |             base: Devise.ldap_base, | ||||||
|             encryption: { |             encryption: { | ||||||
|               method: Devise.ldap_method, |               method: Devise.ldap_method, | ||||||
|                 tls_options: OpenSSL::SSL::SSLContext::DEFAULT_PARAMS, |               tls_options: tls_options, | ||||||
|             }, |             }, | ||||||
|             auth: { |             auth: { | ||||||
|               method: :simple, |               method: :simple, | ||||||
|  | @ -41,9 +40,14 @@ if ENV['LDAP_ENABLED'] == 'true' | ||||||
|       def password |       def password | ||||||
|         params[:user][:password] |         params[:user][:password] | ||||||
|       end |       end | ||||||
|       end |  | ||||||
|     end |  | ||||||
|   end |  | ||||||
| 
 | 
 | ||||||
|   Warden::Strategies.add(:ldap_authenticatable, Devise::Strategies::LdapAuthenticatable) |       def tls_options | ||||||
|  |         OpenSSL::SSL::SSLContext::DEFAULT_PARAMS.tap do |options| | ||||||
|  |           options[:verify_mode] = OpenSSL::SSL::VERIFY_NONE if Devise.ldap_tls_no_verify | ||||||
|  |         end | ||||||
|  |       end | ||||||
|  |     end | ||||||
|  |   end | ||||||
| end | end | ||||||
|  | 
 | ||||||
|  | Warden::Strategies.add(:ldap_authenticatable, Devise::Strategies::LdapAuthenticatable) | ||||||
|  |  | ||||||
|  | @ -21,7 +21,7 @@ module Mastodon | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|     def flags |     def flags | ||||||
|       'rc3' |       'rc4' | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|     def to_a |     def to_a | ||||||
|  |  | ||||||
|  | @ -48,6 +48,13 @@ describe Request do | ||||||
|         expect(a_request(:get, 'http://example.com')).to have_been_made.once |         expect(a_request(:get, 'http://example.com')).to have_been_made.once | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|  |       it 'executes a HTTP request when the first address is private' do | ||||||
|  |         allow(Addrinfo).to receive(:foreach).with('example.com', nil, nil, :SOCK_STREAM) | ||||||
|  |                                             .and_yield(Addrinfo.new(["AF_INET", 0, "example.com", "0.0.0.0"], :PF_INET, :SOCK_STREAM)) | ||||||
|  |                                             .and_yield(Addrinfo.new(["AF_INET6", 0, "example.com", "2001:4860:4860::8844"], :PF_INET6, :SOCK_STREAM)) | ||||||
|  |         expect(a_request(:get, 'http://example.com')).to have_been_made.once | ||||||
|  |       end | ||||||
|  | 
 | ||||||
|       it 'sets headers' do |       it 'sets headers' do | ||||||
|         expect(a_request(:get, 'http://example.com').with(headers: subject.headers)).to have_been_made |         expect(a_request(:get, 'http://example.com').with(headers: subject.headers)).to have_been_made | ||||||
|       end |       end | ||||||
|  | @ -61,7 +68,9 @@ describe Request do | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|       it 'raises Mastodon::ValidationError' do |       it 'raises Mastodon::ValidationError' do | ||||||
|         allow(IPSocket).to receive(:getaddress).with('example.com').and_return('0.0.0.0') |         allow(Addrinfo).to receive(:foreach).with('example.com', nil, nil, :SOCK_STREAM) | ||||||
|  |                                             .and_yield(Addrinfo.new(["AF_INET", 0, "example.com", "0.0.0.0"], :PF_INET, :SOCK_STREAM)) | ||||||
|  |                                             .and_yield(Addrinfo.new(["AF_INET6", 0, "example.com", "2001:db8::face"], :PF_INET6, :SOCK_STREAM)) | ||||||
|         expect{ subject.perform }.to raise_error Mastodon::ValidationError |         expect{ subject.perform }.to raise_error Mastodon::ValidationError | ||||||
|       end |       end | ||||||
|     end |     end | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue