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", | ||||
|       { | ||||
|         "debug": true, | ||||
|         "exclude": ["transform-async-to-generator", "transform-regenerator"], | ||||
|         "loose": true, | ||||
|         "modules": false, | ||||
|  |  | |||
							
								
								
									
										2
									
								
								Gemfile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Gemfile
									
									
									
									
									
								
							|  | @ -73,7 +73,7 @@ gem 'mario-redis-lock', '~> 1.2', require: 'redis_lock' | |||
| gem 'rqrcode', '~> 0.10' | ||||
| gem 'ruby-oembed', '~> 0.12', require: 'oembed' | ||||
| gem 'ruby-progressbar', '~> 1.4' | ||||
| gem 'sanitize', '~> 4.4' | ||||
| gem 'sanitize', '~> 4.6.4' | ||||
| gem 'sidekiq', '~> 5.0' | ||||
| gem 'sidekiq-scheduler', '~> 2.1' | ||||
| gem 'sidekiq-unique-jobs', '~> 5.0' | ||||
|  |  | |||
							
								
								
									
										12
									
								
								Gemfile.lock
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								Gemfile.lock
									
									
									
									
									
								
							|  | @ -290,7 +290,7 @@ GEM | |||
|       activesupport (>= 4, < 5.2) | ||||
|       railties (>= 4, < 5.2) | ||||
|       request_store (~> 1.0) | ||||
|     loofah (2.1.1) | ||||
|     loofah (2.2.1) | ||||
|       crass (~> 1.0.2) | ||||
|       nokogiri (>= 1.5.9) | ||||
|     mail (2.7.0) | ||||
|  | @ -318,9 +318,9 @@ GEM | |||
|       net-ssh (>= 2.6.5) | ||||
|     net-ssh (4.2.0) | ||||
|     nio4r (2.1.0) | ||||
|     nokogiri (1.8.1) | ||||
|     nokogiri (1.8.2) | ||||
|       mini_portile2 (~> 2.3.0) | ||||
|     nokogumbo (1.4.13) | ||||
|     nokogumbo (1.5.0) | ||||
|       nokogiri | ||||
|     nsa (0.2.4) | ||||
|       activesupport (>= 4.2, < 6) | ||||
|  | @ -499,10 +499,10 @@ GEM | |||
|     rufus-scheduler (3.4.2) | ||||
|       et-orbi (~> 1.0) | ||||
|     safe_yaml (1.0.4) | ||||
|     sanitize (4.5.0) | ||||
|     sanitize (4.6.4) | ||||
|       crass (~> 1.0.2) | ||||
|       nokogiri (>= 1.4.4) | ||||
|       nokogumbo (~> 1.4.1) | ||||
|       nokogumbo (~> 1.4) | ||||
|     sass (3.5.3) | ||||
|       sass-listen (~> 4.0.0) | ||||
|     sass-listen (4.0.0) | ||||
|  | @ -704,7 +704,7 @@ DEPENDENCIES | |||
|   rubocop | ||||
|   ruby-oembed (~> 0.12) | ||||
|   ruby-progressbar (~> 1.4) | ||||
|   sanitize (~> 4.4) | ||||
|   sanitize (~> 4.6.4) | ||||
|   scss_lint (~> 0.55) | ||||
|   sidekiq (~> 5.0) | ||||
|   sidekiq-bulk (~> 0.1.1) | ||||
|  |  | |||
|  | @ -1,4 +1,5 @@ | |||
| import api from '../api'; | ||||
| import { CancelToken } from 'axios'; | ||||
| import { throttle } from 'lodash'; | ||||
| import { search as emojiSearch } from '../features/emoji/emoji_mart_search_light'; | ||||
| import { tagHistory } from '../settings'; | ||||
|  | @ -11,6 +12,8 @@ import { | |||
|   refreshPublicTimeline, | ||||
| } from './timelines'; | ||||
| 
 | ||||
| let cancelFetchComposeSuggestionsAccounts; | ||||
| 
 | ||||
| export const COMPOSE_CHANGE          = 'COMPOSE_CHANGE'; | ||||
| export const COMPOSE_SUBMIT_REQUEST  = 'COMPOSE_SUBMIT_REQUEST'; | ||||
| export const COMPOSE_SUBMIT_SUCCESS  = 'COMPOSE_SUBMIT_SUCCESS'; | ||||
|  | @ -257,13 +260,22 @@ export function undoUploadCompose(media_id) { | |||
| }; | ||||
| 
 | ||||
| export function clearComposeSuggestions() { | ||||
|   if (cancelFetchComposeSuggestionsAccounts) { | ||||
|     cancelFetchComposeSuggestionsAccounts(); | ||||
|   } | ||||
|   return { | ||||
|     type: COMPOSE_SUGGESTIONS_CLEAR, | ||||
|   }; | ||||
| }; | ||||
| 
 | ||||
| const fetchComposeSuggestionsAccounts = throttle((dispatch, getState, token) => { | ||||
|   if (cancelFetchComposeSuggestionsAccounts) { | ||||
|     cancelFetchComposeSuggestionsAccounts(); | ||||
|   } | ||||
|   api(getState).get('/api/v1/accounts/search', { | ||||
|     cancelToken: new CancelToken(cancel => { | ||||
|       cancelFetchComposeSuggestionsAccounts = cancel; | ||||
|     }), | ||||
|     params: { | ||||
|       q: token.slice(1), | ||||
|       resolve: false, | ||||
|  |  | |||
|  | @ -94,9 +94,16 @@ class Request | |||
|   class Socket < TCPSocket | ||||
|     class << self | ||||
|       def open(host, *args) | ||||
|         address = IPSocket.getaddress(host) | ||||
|         raise Mastodon::HostValidationError if PrivateAddressCheck.private_address? IPAddr.new(address) | ||||
|         super address, *args | ||||
|         outer_e = nil | ||||
|         Addrinfo.foreach(host, nil, nil, :SOCK_STREAM) do |address| | ||||
|           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 | ||||
| 
 | ||||
|       alias new open | ||||
|  |  | |||
|  | @ -47,7 +47,8 @@ | |||
| # | ||||
| 
 | ||||
| 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 AccountFinderConcern | ||||
|  | @ -70,7 +71,8 @@ class Account < ApplicationRecord | |||
|   validates :username, uniqueness: { scope: :domain, case_sensitive: true }, if: -> { !local? && will_save_change_to_username? } | ||||
| 
 | ||||
|   # 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 :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? } | ||||
|  |  | |||
|  | @ -16,7 +16,7 @@ class ActivityPub::ProcessAccountService < BaseService | |||
| 
 | ||||
|     RedisLock.acquire(lock_options) do |lock| | ||||
|       if lock.acquired? | ||||
|         @account        = Account.find_by(uri: @uri) | ||||
|         @account        = Account.find_remote(@username, @domain) | ||||
|         @old_public_key = @account&.public_key | ||||
|         @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 | ||||
|     if config.i18n.available_locales.include?(config.i18n.default_locale) | ||||
|       config.i18n.fallbacks = [:en] | ||||
|     else | ||||
|     unless config.i18n.available_locales.include?(config.i18n.default_locale) | ||||
|       config.i18n.default_locale = :en | ||||
|     end | ||||
| 
 | ||||
|  |  | |||
|  | @ -55,8 +55,8 @@ Rails.application.configure do | |||
|   # config.action_mailer.raise_delivery_errors = false | ||||
| 
 | ||||
|   # Enable locale fallbacks for I18n (makes lookups for any locale fall back to | ||||
|   # the I18n.default_locale when a translation cannot be found). | ||||
|   config.i18n.fallbacks = true | ||||
|   # English when a translation cannot be found). | ||||
|   config.i18n.fallbacks = [:en] | ||||
| 
 | ||||
|   # Send deprecation notices to registered listeners. | ||||
|   config.active_support.deprecation = :notify | ||||
|  |  | |||
|  | @ -55,6 +55,8 @@ module Devise | |||
|   @@ldap_bind_dn = nil | ||||
|   mattr_accessor :ldap_password | ||||
|   @@ldap_password = nil | ||||
|   mattr_accessor :ldap_tls_no_verify | ||||
|   @@ldap_tls_no_verify = false | ||||
| 
 | ||||
|   class Strategies::PamAuthenticatable | ||||
|     def valid? | ||||
|  | @ -357,5 +359,6 @@ Devise.setup do |config| | |||
|     config.ldap_bind_dn        = ENV.fetch('LDAP_BIND_DN') | ||||
|     config.ldap_password       = ENV.fetch('LDAP_PASSWORD') | ||||
|     config.ldap_uid            = ENV.fetch('LDAP_UID', 'cn') | ||||
|     config.ldap_tls_no_verify  = ENV['LDAP_TLS_NO_VERIFY'] == 'true' | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,6 +1,5 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| if ENV['LDAP_ENABLED'] == 'true' | ||||
| require 'net/ldap' | ||||
| require 'devise/strategies/authenticatable' | ||||
| 
 | ||||
|  | @ -15,7 +14,7 @@ if ENV['LDAP_ENABLED'] == 'true' | |||
|             base: Devise.ldap_base, | ||||
|             encryption: { | ||||
|               method: Devise.ldap_method, | ||||
|                 tls_options: OpenSSL::SSL::SSLContext::DEFAULT_PARAMS, | ||||
|               tls_options: tls_options, | ||||
|             }, | ||||
|             auth: { | ||||
|               method: :simple, | ||||
|  | @ -41,9 +40,14 @@ if ENV['LDAP_ENABLED'] == 'true' | |||
|       def password | ||||
|         params[:user][:password] | ||||
|       end | ||||
| 
 | ||||
|       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 | ||||
| 
 | ||||
| Warden::Strategies.add(:ldap_authenticatable, Devise::Strategies::LdapAuthenticatable) | ||||
| end | ||||
|  |  | |||
|  | @ -21,7 +21,7 @@ module Mastodon | |||
|     end | ||||
| 
 | ||||
|     def flags | ||||
|       'rc3' | ||||
|       'rc4' | ||||
|     end | ||||
| 
 | ||||
|     def to_a | ||||
|  |  | |||
|  | @ -48,6 +48,13 @@ describe Request do | |||
|         expect(a_request(:get, 'http://example.com')).to have_been_made.once | ||||
|       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 | ||||
|         expect(a_request(:get, 'http://example.com').with(headers: subject.headers)).to have_been_made | ||||
|       end | ||||
|  | @ -61,7 +68,9 @@ describe Request do | |||
|       end | ||||
| 
 | ||||
|       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 | ||||
|       end | ||||
|     end | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue