diff --git a/.travis.yml b/.travis.yml index 62961abc4a2..6fdc8353554 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,6 @@ env: - RUBY_GC_MALLOC_LIMIT=50000000 matrix: - "RAILS_MASTER=0" - - "RAILS42=1" - "RAILS_MASTER=1" addons: @@ -21,7 +20,6 @@ addons: matrix: allow_failures: - env: "RAILS_MASTER=1" - - env: "RAILS42=1" - rvm: rbx-2 fast_finish: true @@ -51,7 +49,6 @@ before_script: - bundle exec rake db:create db:migrate install: - - bash -c "if [ '$RAILS42' == '1' ]; then bundle update --retry=3 --jobs=3 rails rails-observers; fi" - bash -c "if [ '$RAILS_MASTER' == '1' ]; then bundle update --retry=3 --jobs=3 arel rails rails-observers seed-fu; fi" - bash -c "if [ '$RAILS_MASTER' == '0' ]; then bundle install --without development --deployment --retry=3 --jobs=3; fi" diff --git a/Gemfile b/Gemfile index 2332689189a..1476657d6f9 100644 --- a/Gemfile +++ b/Gemfile @@ -6,30 +6,19 @@ def rails_master? ENV["RAILS_MASTER"] == '1' end -def rails_42? - ENV["RAILS42"] == '1' -end - if rails_master? gem 'arel', git: 'https://github.com/rails/arel.git' gem 'rails', git: 'https://github.com/rails/rails.git' gem 'rails-observers', git: 'https://github.com/rails/rails-observers.git' gem 'seed-fu', git: 'https://github.com/SamSaffron/seed-fu.git', branch: 'discourse' -elsif rails_42? - gem 'rails', '~> 4.2.1' - gem 'rails-observers', git: 'https://github.com/rails/rails-observers.git' - gem 'seed-fu', '~> 2.3.5' else - gem 'rails', '~> 4.1.10' + gem 'rails', '~> 4.2' gem 'rails-observers' - gem 'seed-fu', '~> 2.3.3' + gem 'seed-fu', '~> 2.3.5' end -# Rails 4.1.6+ will relax the mail gem version requirement to `~> 2.5, >= 2.5.4`. -# However, mail gem 2.6.x currently does not work with discourse because of the -# reference to `Mail::RFC2822Parser` in `lib/email.rb`. This ensure discourse -# would continue to work with Rails 4.1.6+ when it is released. -gem 'mail', '~> 2.5.4' +gem 'mail' +gem 'mime-types', require: 'mime/types/columnar' #gem 'redis-rails' gem 'hiredis' diff --git a/Gemfile.lock b/Gemfile.lock index 46f0d552f39..3c7f5cba96a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -6,38 +6,47 @@ PATH GEM remote: https://rubygems.org/ specs: - actionmailer (4.1.10) - actionpack (= 4.1.10) - actionview (= 4.1.10) + actionmailer (4.2.4) + actionpack (= 4.2.4) + actionview (= 4.2.4) + activejob (= 4.2.4) mail (~> 2.5, >= 2.5.4) - actionpack (4.1.10) - actionview (= 4.1.10) - activesupport (= 4.1.10) - rack (~> 1.5.2) + rails-dom-testing (~> 1.0, >= 1.0.5) + actionpack (4.2.4) + actionview (= 4.2.4) + activesupport (= 4.2.4) + rack (~> 1.6) rack-test (~> 0.6.2) - actionview (4.1.10) - activesupport (= 4.1.10) + rails-dom-testing (~> 1.0, >= 1.0.5) + rails-html-sanitizer (~> 1.0, >= 1.0.2) + actionview (4.2.4) + activesupport (= 4.2.4) builder (~> 3.1) erubis (~> 2.7.0) + rails-dom-testing (~> 1.0, >= 1.0.5) + rails-html-sanitizer (~> 1.0, >= 1.0.2) active_model_serializers (0.8.3) activemodel (>= 3.0) - activemodel (4.1.10) - activesupport (= 4.1.10) + activejob (4.2.4) + activesupport (= 4.2.4) + globalid (>= 0.3.0) + activemodel (4.2.4) + activesupport (= 4.2.4) builder (~> 3.1) - activerecord (4.1.10) - activemodel (= 4.1.10) - activesupport (= 4.1.10) - arel (~> 5.0.0) - activesupport (4.1.10) - i18n (~> 0.6, >= 0.6.9) + activerecord (4.2.4) + activemodel (= 4.2.4) + activesupport (= 4.2.4) + arel (~> 6.0) + activesupport (4.2.4) + i18n (~> 0.7) json (~> 1.7, >= 1.7.7) minitest (~> 5.1) - thread_safe (~> 0.1) + thread_safe (~> 0.3, >= 0.3.4) tzinfo (~> 1.1) annotate (2.6.6) activerecord (>= 2.3.0) rake (~> 10.4.2, >= 10.4.2) - arel (5.0.1.20140414130214) + arel (6.0.3) aws-sdk (2.0.45) aws-sdk-resources (= 2.0.45) aws-sdk-core (2.0.45) @@ -118,6 +127,8 @@ GEM gctools (0.2.3) given_core (3.5.4) sorcerer (>= 0.3.7) + globalid (0.3.6) + activesupport (>= 4.1.0) guess_html_encoding (0.0.11) handlebars-source (2.0.0) hashie (3.4.0) @@ -149,19 +160,20 @@ GEM libv8 (3.16.14.7) listen (0.7.3) logster (1.0.0.3.pre) + loofah (2.0.3) + nokogiri (>= 1.5.9) lru_redux (1.1.0) - mail (2.5.4) - mime-types (~> 1.16) - treetop (~> 1.4.8) + mail (2.6.3) + mime-types (>= 1.16, < 3) memory_profiler (0.9.3) message_bus (1.0.16) rack (>= 1.1.3) redis metaclass (0.0.4) method_source (0.8.2) - mime-types (1.25.1) + mime-types (2.6.2) mini_portile (0.6.2) - minitest (5.6.1) + minitest (5.8.0) mocha (1.1.0) metaclass (~> 0.0.1) mock_redis (0.14.0) @@ -218,7 +230,6 @@ GEM redis ruby-openid pg (0.18.1) - polyglot (0.3.5) progress (3.1.0) pry (0.10.1) coderay (~> 1.1.0) @@ -231,7 +242,7 @@ GEM puma (2.11.1) rack (>= 1.1, < 2.0) r2 (0.2.5) - rack (1.5.5) + rack (1.6.4) rack-mini-profiler (0.9.6) rack (>= 1.1.3) rack-openid (1.3.1) @@ -241,21 +252,30 @@ GEM rack rack-test (0.6.3) rack (>= 1.0) - rails (4.1.10) - actionmailer (= 4.1.10) - actionpack (= 4.1.10) - actionview (= 4.1.10) - activemodel (= 4.1.10) - activerecord (= 4.1.10) - activesupport (= 4.1.10) + rails (4.2.4) + actionmailer (= 4.2.4) + actionpack (= 4.2.4) + actionview (= 4.2.4) + activejob (= 4.2.4) + activemodel (= 4.2.4) + activerecord (= 4.2.4) + activesupport (= 4.2.4) bundler (>= 1.3.0, < 2.0) - railties (= 4.1.10) - sprockets-rails (~> 2.0) + railties (= 4.2.4) + sprockets-rails + rails-deprecated_sanitizer (1.0.3) + activesupport (>= 4.2.0.alpha) + rails-dom-testing (1.0.7) + activesupport (>= 4.2.0.beta, < 5.0) + nokogiri (~> 1.6.0) + rails-deprecated_sanitizer (>= 1.0.1) + rails-html-sanitizer (1.0.2) + loofah (~> 2.0) rails-observers (0.1.2) activemodel (~> 4.0) - railties (4.1.10) - actionpack (= 4.1.10) - activesupport (= 4.1.10) + railties (4.2.4) + actionpack (= 4.2.4) + activesupport (= 4.2.4) rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) raindrops (0.13.0) @@ -374,9 +394,6 @@ GEM timecop (0.7.3) timers (4.0.1) hitimes - treetop (1.4.15) - polyglot - polyglot (>= 0.3.1) trollop (2.1.1) tzinfo (1.2.2) thread_safe (~> 0.1) @@ -427,9 +444,10 @@ DEPENDENCIES listen (= 0.7.3) logster lru_redux - mail (~> 2.5.4) + mail memory_profiler message_bus + mime-types minitest mocha mock_redis @@ -453,7 +471,7 @@ DEPENDENCIES r2 (~> 0.2.5) rack-mini-profiler rack-protection - rails (~> 4.1.10) + rails (~> 4.2) rails-observers rails_multisite! rake @@ -473,7 +491,7 @@ DEPENDENCIES sanitize sass sass-rails (~> 4.0.5) - seed-fu (~> 2.3.3) + seed-fu (~> 2.3.5) shoulda sidekiq sidekiq-statistic diff --git a/app/models/post.rb b/app/models/post.rb index c486e327d9d..5693369e8d2 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -90,7 +90,7 @@ class Post < ActiveRecord::Base end def limit_posts_per_day - if user.first_day_user? && post_number && post_number > 1 + if user && user.first_day_user? && post_number && post_number > 1 RateLimiter.new(user, "first-day-replies-per-day", SiteSetting.max_replies_in_first_day, 1.day.to_i) end end diff --git a/app/models/report.rb b/app/models/report.rb index 204bc3e9bc5..8d1d971077f 100644 --- a/app/models/report.rb +++ b/app/models/report.rb @@ -58,7 +58,7 @@ class Report if filter == :page_view_total ApplicationRequest.where(req_type: [ ApplicationRequest.req_types.reject{|k,v| k =~ /mobile/}.map{|k,v| v if k =~ /page_view/}.compact - ]) + ].flatten) else ApplicationRequest.where(req_type: ApplicationRequest.req_types[filter]) end diff --git a/app/models/topic.rb b/app/models/topic.rb index 0cf7dad3001..71111defccc 100644 --- a/app/models/topic.rb +++ b/app/models/topic.rb @@ -259,7 +259,7 @@ class Topic < ActiveRecord::Base # Additional rate limits on topics: per day and private messages per day def limit_topics_per_day apply_per_day_rate_limit_for("topics", :max_topics_per_day) - limit_first_day_topics_per_day if user.first_day_user? + limit_first_day_topics_per_day if user && user.first_day_user? end def limit_private_messages_per_day diff --git a/config/application.rb b/config/application.rb index 203442efff2..f1df9881c68 100644 --- a/config/application.rb +++ b/config/application.rb @@ -122,10 +122,7 @@ module Discourse # see: http://stackoverflow.com/questions/11894180/how-does-one-correctly-add-custom-sql-dml-in-migrations/11894420#11894420 config.active_record.schema_format = :sql - if Rails.version >= "4.2.0" && Rails.version < "5.0.0" - # Opt-into the default behavior in Rails 5 - config.active_record.raise_in_transactional_callbacks = false - end + config.active_record.raise_in_transactional_callbacks = true # per https://www.owasp.org/index.php/Password_Storage_Cheat_Sheet config.pbkdf2_iterations = 64000 diff --git a/config/environments/production.rb b/config/environments/production.rb index 013e37f597f..c637fb67b1d 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -10,7 +10,7 @@ Discourse::Application.configure do config.action_controller.perform_caching = true # Disable Rails's static asset server (Apache or nginx will already do this) - config.serve_static_assets = GlobalSetting.serve_static_assets + config.serve_static_files = GlobalSetting.serve_static_assets config.assets.js_compressor = :uglifier diff --git a/config/environments/profile.rb b/config/environments/profile.rb index 1784a23528b..3f672a9c472 100644 --- a/config/environments/profile.rb +++ b/config/environments/profile.rb @@ -13,7 +13,7 @@ Discourse::Application.configure do config.action_controller.perform_caching = true # in profile mode we serve static assets - config.serve_static_assets = true + config.serve_static_files = true # Compress JavaScripts and CSS config.assets.compress = true diff --git a/config/environments/test.rb b/config/environments/test.rb index b885d72ab32..16cab97ce13 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -8,7 +8,7 @@ Discourse::Application.configure do config.cache_classes = true # Configure static asset server for tests with Cache-Control for performance - config.serve_static_assets = true + config.serve_static_files = true # Show full error reports and disable caching config.consider_all_requests_local = true diff --git a/lib/email.rb b/lib/email.rb index 1b728aee7ea..f0fbc28e57c 100644 --- a/lib/email.rb +++ b/lib/email.rb @@ -10,13 +10,14 @@ module Email return false unless String === email - parser = Mail::RFC2822Parser.new - parser.root = :addr_spec - result = parser.parse(email) + parsed = Mail::Address.new(email) + # Don't allow for a TLD by itself list (sam@localhost) # The Grammar is: (local_part "@" domain) / local_part ... need to discard latter - result && result.respond_to?(:domain) && result.domain.dot_atom_text.elements.size > 1 + parsed.address == email && parsed.local != parsed.address && parsed.domain && parsed.domain.split(".").length > 1 + rescue Mail::Field::ParseError + false end def self.downcase(email) diff --git a/spec/models/user_email_observer_spec.rb b/spec/models/user_email_observer_spec.rb index 74dec64b5e3..f9307e1c4cf 100644 --- a/spec/models/user_email_observer_spec.rb +++ b/spec/models/user_email_observer_spec.rb @@ -2,10 +2,17 @@ require 'spec_helper' describe UserEmailObserver do - context 'user_mentioned' do + # something is off with fabricator + def create_notification(type=nil, user=nil) + user ||= Fabricate(:user) + type ||= Notification.types[:mentioned] + Notification.create(data: '', user: user, notification_type: type) + end - let(:user) { Fabricate(:user) } - let!(:notification) { Fabricate(:notification, user: user) } + context 'user_mentioned' do + let!(:notification) do + create_notification + end it "enqueues a job for the email" do Jobs.expects(:enqueue_in).with(SiteSetting.email_time_window_mins.minutes, :user_email, type: :user_mentioned, user_id: notification.user_id, notification_id: notification.id) @@ -13,19 +20,19 @@ describe UserEmailObserver do end it "enqueue a delayed job for users that are online" do - user.last_seen_at = 1.minute.ago + notification.user.last_seen_at = 1.minute.ago Jobs.expects(:enqueue_in).with(SiteSetting.email_time_window_mins.minutes, :user_email, type: :user_mentioned, user_id: notification.user_id, notification_id: notification.id) UserEmailObserver.send(:new).after_commit(notification) end it "doesn't enqueue an email if the user has mention emails disabled" do - user.expects(:email_direct?).returns(false) + notification.user.expects(:email_direct?).returns(false) Jobs.expects(:enqueue_in).with(SiteSetting.email_time_window_mins.minutes, :user_email, has_entry(type: :user_mentioned)).never UserEmailObserver.send(:new).after_commit(notification) end it "doesn't enqueue an email if the user account is deactivated" do - user.active = false + notification.user.active = false Jobs.expects(:enqueue_in).with(SiteSetting.email_time_window_mins.minutes, :user_email, has_entry(type: :user_mentioned)).never UserEmailObserver.send(:new).after_commit(notification) end @@ -34,8 +41,8 @@ describe UserEmailObserver do context 'posted' do - let(:user) { Fabricate(:user) } - let!(:notification) { Fabricate(:notification, user: user, notification_type: 9) } + let!(:notification) { create_notification(9) } + let(:user) { notification.user } it "enqueues a job for the email" do Jobs.expects(:enqueue_in).with(SiteSetting.email_time_window_mins.minutes, :user_email, type: :user_posted, user_id: notification.user_id, notification_id: notification.id) @@ -58,8 +65,8 @@ describe UserEmailObserver do context 'user_replied' do - let(:user) { Fabricate(:user) } - let!(:notification) { Fabricate(:notification, user: user, notification_type: 2) } + let!(:notification) { create_notification(2) } + let(:user) { notification.user } it "enqueues a job for the email" do Jobs.expects(:enqueue_in).with(SiteSetting.email_time_window_mins.minutes, :user_email, type: :user_replied, user_id: notification.user_id, notification_id: notification.id) @@ -82,8 +89,8 @@ describe UserEmailObserver do context 'user_quoted' do - let(:user) { Fabricate(:user) } - let!(:notification) { Fabricate(:notification, user: user, notification_type: 3) } + let!(:notification) { create_notification(3) } + let(:user) { notification.user } it "enqueues a job for the email" do Jobs.expects(:enqueue_in).with(SiteSetting.email_time_window_mins.minutes, :user_email, type: :user_quoted, user_id: notification.user_id, notification_id: notification.id) @@ -106,8 +113,8 @@ describe UserEmailObserver do context 'email_user_invited_to_private_message' do - let(:user) { Fabricate(:user) } - let!(:notification) { Fabricate(:notification, user: user, notification_type: 7) } + let!(:notification) { create_notification(7) } + let(:user) { notification.user } it "enqueues a job for the email" do Jobs.expects(:enqueue_in).with(SiteSetting.email_time_window_mins.minutes, :user_email, type: :user_invited_to_private_message, user_id: notification.user_id, notification_id: notification.id) @@ -130,8 +137,8 @@ describe UserEmailObserver do context 'private_message' do - let(:user) { Fabricate(:user) } - let!(:notification) { Fabricate(:notification, user: user, notification_type: 6) } + let!(:notification) { create_notification(6) } + let(:user) { notification.user } it "enqueues a job for the email" do Jobs.expects(:enqueue_in).with(SiteSetting.email_time_window_mins.minutes, :user_email, type: :user_private_message, user_id: notification.user_id, notification_id: notification.id) @@ -154,8 +161,8 @@ describe UserEmailObserver do context 'user_invited_to_topic' do - let(:user) { Fabricate(:user) } - let!(:notification) { Fabricate(:notification, user: user, notification_type: 13) } + let!(:notification) { create_notification(13) } + let(:user) { notification.user } it "enqueues a job for the email" do Jobs.expects(:enqueue_in).with(SiteSetting.email_time_window_mins.minutes, :user_email, type: :user_invited_to_topic, user_id: notification.user_id, notification_id: notification.id)