From 7f567862d74e10ce1a3bc48b2e45fb4313a2b0bb Mon Sep 17 00:00:00 2001
From: Jyri-Petteri Paloposki
Date: Thu, 6 Jun 2024 01:43:38 +0300
Subject: [PATCH 1/3] Upgrade Rails to 6.1
---
Gemfile | 2 +-
Gemfile.lock | 152 ++++++++++++++++++++++++++-------------------------
2 files changed, 79 insertions(+), 75 deletions(-)
diff --git a/Gemfile b/Gemfile
index cb2ca3e6..ca474828 100644
--- a/Gemfile
+++ b/Gemfile
@@ -8,7 +8,7 @@ gem 'coffee-rails', '~> 5.0.0'
gem 'jquery-rails', '~> 4.6'
gem 'jquery-ui-rails', '~>6.0.1'
-gem 'rails', '~> 6.0.0'
+gem 'rails', '~> 6.1'
gem 'sassc-rails', '~> 2.1.2'
gem 'bootstrap-sass', '3.4.1'
diff --git a/Gemfile.lock b/Gemfile.lock
index 70958586..f01f1abf 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -4,70 +4,75 @@ GEM
RedCloth (4.3.3)
aasm (5.5.0)
concurrent-ruby (~> 1.0)
- actioncable (6.0.6.1)
- actionpack (= 6.0.6.1)
+ actioncable (6.1.7.8)
+ actionpack (= 6.1.7.8)
+ activesupport (= 6.1.7.8)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
- actionmailbox (6.0.6.1)
- actionpack (= 6.0.6.1)
- activejob (= 6.0.6.1)
- activerecord (= 6.0.6.1)
- activestorage (= 6.0.6.1)
- activesupport (= 6.0.6.1)
+ actionmailbox (6.1.7.8)
+ actionpack (= 6.1.7.8)
+ activejob (= 6.1.7.8)
+ activerecord (= 6.1.7.8)
+ activestorage (= 6.1.7.8)
+ activesupport (= 6.1.7.8)
mail (>= 2.7.1)
- actionmailer (6.0.6.1)
- actionpack (= 6.0.6.1)
- actionview (= 6.0.6.1)
- activejob (= 6.0.6.1)
+ actionmailer (6.1.7.8)
+ actionpack (= 6.1.7.8)
+ actionview (= 6.1.7.8)
+ activejob (= 6.1.7.8)
+ activesupport (= 6.1.7.8)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0)
- actionpack (6.0.6.1)
- actionview (= 6.0.6.1)
- activesupport (= 6.0.6.1)
- rack (~> 2.0, >= 2.0.8)
+ actionpack (6.1.7.8)
+ actionview (= 6.1.7.8)
+ activesupport (= 6.1.7.8)
+ rack (~> 2.0, >= 2.0.9)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.2.0)
actionpack-xml_parser (2.0.1)
actionpack (>= 5.0)
railties (>= 5.0)
- actiontext (6.0.6.1)
- actionpack (= 6.0.6.1)
- activerecord (= 6.0.6.1)
- activestorage (= 6.0.6.1)
- activesupport (= 6.0.6.1)
+ actiontext (6.1.7.8)
+ actionpack (= 6.1.7.8)
+ activerecord (= 6.1.7.8)
+ activestorage (= 6.1.7.8)
+ activesupport (= 6.1.7.8)
nokogiri (>= 1.8.5)
- actionview (6.0.6.1)
- activesupport (= 6.0.6.1)
+ actionview (6.1.7.8)
+ activesupport (= 6.1.7.8)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
- activejob (6.0.6.1)
- activesupport (= 6.0.6.1)
+ activejob (6.1.7.8)
+ activesupport (= 6.1.7.8)
globalid (>= 0.3.6)
- activemodel (6.0.6.1)
- activesupport (= 6.0.6.1)
+ activemodel (6.1.7.8)
+ activesupport (= 6.1.7.8)
activemodel-serializers-xml (1.0.2)
activemodel (> 5.x)
activesupport (> 5.x)
builder (~> 3.1)
- activerecord (6.0.6.1)
- activemodel (= 6.0.6.1)
- activesupport (= 6.0.6.1)
- activestorage (6.0.6.1)
- actionpack (= 6.0.6.1)
- activejob (= 6.0.6.1)
- activerecord (= 6.0.6.1)
+ activerecord (6.1.7.8)
+ activemodel (= 6.1.7.8)
+ activesupport (= 6.1.7.8)
+ activestorage (6.1.7.8)
+ actionpack (= 6.1.7.8)
+ activejob (= 6.1.7.8)
+ activerecord (= 6.1.7.8)
+ activesupport (= 6.1.7.8)
marcel (~> 1.0)
- activesupport (6.0.6.1)
+ mini_mime (>= 1.1.0)
+ activesupport (6.1.7.8)
concurrent-ruby (~> 1.0, >= 1.0.2)
- i18n (>= 0.7, < 2)
- minitest (~> 5.1)
- tzinfo (~> 1.1)
- zeitwerk (~> 2.2, >= 2.2.2)
- acts_as_list (1.1.0)
- activerecord (>= 4.2)
+ i18n (>= 1.6, < 2)
+ minitest (>= 5.1)
+ tzinfo (~> 2.0)
+ zeitwerk (~> 2.3)
+ acts_as_list (1.2.1)
+ activerecord (>= 6.1)
+ activesupport (>= 6.1)
ast (2.4.2)
autoprefixer-rails (10.4.7.0)
execjs (~> 2)
@@ -102,7 +107,7 @@ GEM
concurrent-ruby (1.3.1)
crass (1.0.6)
database_cleaner (1.99.0)
- date (3.3.3)
+ date (3.3.4)
diff-lcs (1.5.0)
docile (1.1.5)
e2mmap (0.1.0)
@@ -116,8 +121,8 @@ GEM
ffi (1.16.3)
font-awesome-sass (6.5.1)
sassc (~> 2.0)
- globalid (1.1.0)
- activesupport (>= 5.0)
+ globalid (1.2.1)
+ activesupport (>= 6.1)
highline (2.1.0)
htmlentities (4.3.4)
i18n (1.14.5)
@@ -169,21 +174,21 @@ GEM
mime-types (3.4.1)
mime-types-data (~> 3.2015)
mime-types-data (3.2023.0218.1)
- mini_mime (1.1.2)
+ mini_mime (1.1.5)
mini_portile2 (2.8.5)
minitest (5.23.1)
minitest-stub-const (0.6)
mocha (2.1.0)
ruby2_keywords (>= 0.0.5)
mysql2 (0.5.5)
- net-imap (0.3.6)
+ net-imap (0.4.12)
date
net-protocol
net-pop (0.1.2)
net-protocol
- net-protocol (0.2.1)
+ net-protocol (0.2.2)
timeout
- net-smtp (0.3.3)
+ net-smtp (0.5.0)
net-protocol
nio4r (2.7.3)
nokogiri (1.15.5)
@@ -202,20 +207,20 @@ GEM
rack (>= 1.2.0)
rack-test (2.1.0)
rack (>= 1.3)
- rails (6.0.6.1)
- actioncable (= 6.0.6.1)
- actionmailbox (= 6.0.6.1)
- actionmailer (= 6.0.6.1)
- actionpack (= 6.0.6.1)
- actiontext (= 6.0.6.1)
- actionview (= 6.0.6.1)
- activejob (= 6.0.6.1)
- activemodel (= 6.0.6.1)
- activerecord (= 6.0.6.1)
- activestorage (= 6.0.6.1)
- activesupport (= 6.0.6.1)
- bundler (>= 1.3.0)
- railties (= 6.0.6.1)
+ rails (6.1.7.8)
+ actioncable (= 6.1.7.8)
+ actionmailbox (= 6.1.7.8)
+ actionmailer (= 6.1.7.8)
+ actionpack (= 6.1.7.8)
+ actiontext (= 6.1.7.8)
+ actionview (= 6.1.7.8)
+ activejob (= 6.1.7.8)
+ activemodel (= 6.1.7.8)
+ activerecord (= 6.1.7.8)
+ activestorage (= 6.1.7.8)
+ activesupport (= 6.1.7.8)
+ bundler (>= 1.15.0)
+ railties (= 6.1.7.8)
sprockets-rails (>= 2.0.0)
rails-controller-testing (1.0.5)
actionpack (>= 5.0.1.rc1)
@@ -235,12 +240,12 @@ GEM
actionview (> 3.1)
activesupport (> 3.1)
railties (> 3.1)
- railties (6.0.6.1)
- actionpack (= 6.0.6.1)
- activesupport (= 6.0.6.1)
+ railties (6.1.7.8)
+ actionpack (= 6.1.7.8)
+ activesupport (= 6.1.7.8)
method_source
- rake (>= 0.8.7)
- thor (>= 0.20.3, < 2.0)
+ rake (>= 12.2)
+ thor (~> 1.0)
rainbow (3.1.1)
rake (13.1.0)
rb-fsevent (0.11.2)
@@ -325,22 +330,21 @@ GEM
libv8 (~> 3.16.14.15)
ref
thor (1.3.0)
- thread_safe (0.3.6)
tilt (2.3.0)
- timeout (0.3.2)
+ timeout (0.4.1)
tolk (5.0.1)
rails (>= 6.0)
safe_yaml (>= 0.8.6)
sprockets-rails (~> 3.4)
tracks-chartjs-ror (3.6.4)
rails (>= 3.1)
- tzinfo (1.2.11)
- thread_safe (~> 0.1)
+ tzinfo (2.0.6)
+ concurrent-ruby (~> 1.0)
uglifier (4.2.0)
execjs (>= 0.3.0, < 3)
unicode-display_width (2.5.0)
uniform_notifier (1.16.0)
- websocket-driver (0.7.5)
+ websocket-driver (0.7.6)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5)
will_paginate (4.0.0)
@@ -377,7 +381,7 @@ DEPENDENCIES
pg (~> 1.5.4)
puma (~> 6.4)
rack-mini-profiler
- rails (~> 6.0.0)
+ rails (~> 6.1)
rails-controller-testing
rails-dom-testing (~> 2.2.0)
rails_autolink
@@ -397,4 +401,4 @@ DEPENDENCIES
yard
BUNDLED WITH
- 2.2.33
+ 2.4.19
From 86e36b07a65838afa4c69481e9a4479af35e9bde Mon Sep 17 00:00:00 2001
From: Jyri-Petteri Paloposki
Date: Tue, 4 Jan 2022 01:18:13 +0200
Subject: [PATCH 2/3] Fix syntax errors for upgrade of Rails version
---
app/controllers/contexts_controller.rb | 2 +-
app/controllers/projects_controller.rb | 2 +-
app/controllers/todos_controller.rb | 6 +++---
app/controllers/users_controller.rb | 2 +-
.../recurring_todos/abstract_recurrence_pattern.rb | 8 ++++----
app/models/recurring_todos/daily_recurrence_pattern.rb | 2 +-
.../recurring_todos/weekly_recurrence_pattern.rb | 2 +-
..._projects_contexts_remove_not_null_from_position.rb | 8 ++++----
test/models/todo_test.rb | 10 +++++-----
9 files changed, 21 insertions(+), 21 deletions(-)
diff --git a/app/controllers/contexts_controller.rb b/app/controllers/contexts_controller.rb
index b1ff4c1b..c6510c40 100644
--- a/app/controllers/contexts_controller.rb
+++ b/app/controllers/contexts_controller.rb
@@ -83,7 +83,7 @@ class ContextsController < ApplicationController
end
format.xml do
if @context.new_record?
- render_failure @context.errors.to_xml.html_safe, 409
+ render_failure @context.errors.full_messages.to_xml(root: "errors", skip_types: true).html_safe, 409
else
head :created, :location => context_url(@context)
end
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index e116bb08..5d75d7c9 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -186,7 +186,7 @@ class ProjectsController < ApplicationController
end
format.xml do
if @project.new_record?
- render_failure @project.errors.to_xml.html_safe, 409
+ render_failure @project.errors.full_messages.to_xml(root: "errors", skip_types: true).html_safe, 409
else
head :created, :location => project_url(@project), :text => @project.id
end
diff --git a/app/controllers/todos_controller.rb b/app/controllers/todos_controller.rb
index 9c98c88d..1c852420 100644
--- a/app/controllers/todos_controller.rb
+++ b/app/controllers/todos_controller.rb
@@ -154,7 +154,7 @@ class TodosController < ApplicationController
if @saved
head :created, :location => todo_url(@todo)
else
- render_failure @todo.errors.to_xml.html_safe, 409
+ render_failure @todo.errors.full_messages.to_xml(root: "errors", skip_types: true).html_safe, 409
end
end
end
@@ -438,7 +438,7 @@ class TodosController < ApplicationController
rescue ActiveRecord::RecordInvalid => exception
record = exception.record
if record.is_a?(Dependency)
- record.errors.each { |key, value| @todo.errors[key] << value }
+ record.errors.each { |key, value| @todo.errors.add(key, value) }
end
@saved = false
end
@@ -1192,7 +1192,7 @@ end
begin
parse_date_per_user_prefs(date)
rescue
- @todo.errors[:base] << error_msg
+ @todo.errors.add(:base, error_msg)
end
end
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 8198025a..30b63172 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -125,7 +125,7 @@ class UsersController < ApplicationController
unless user.new_record?
render :body => t('users.user_created'), :status => 200
else
- render_failure user.errors.to_xml, 409
+ render_failure user.errors.full_messages.to_xml(root: "errors", skip_types: true), 409
end
return
end
diff --git a/app/models/recurring_todos/abstract_recurrence_pattern.rb b/app/models/recurring_todos/abstract_recurrence_pattern.rb
index 91276f2e..2ad33b34 100644
--- a/app/models/recurring_todos/abstract_recurrence_pattern.rb
+++ b/app/models/recurring_todos/abstract_recurrence_pattern.rb
@@ -80,11 +80,11 @@ module RecurringTodos
end
def validate_not_blank(object, msg)
- errors[:base] << msg if object.blank?
+ errors.add(:base, msg) if object.blank?
end
def validate_not_nil(object, msg)
- errors[:base] << msg if object.nil?
+ errors.add(:base, msg) if object.nil?
end
def validate
@@ -100,7 +100,7 @@ module RecurringTodos
when "ends_on_end_date"
validate_not_blank(end_date, "The end date needs to be filled in for 'Ends on'")
else
- errors[:base] << "The end of the recurrence is not selected" unless ends_on == "no_end_date"
+ errors.add(:base, "The end of the recurrence is not selected") unless ends_on == "no_end_date"
end
end
@@ -113,7 +113,7 @@ module RecurringTodos
validate_not_nil(show_always?, "Please select when to show the action")
validate_not_blank(show_from_delta, "Please fill in the number of days to show the todo before the due date") unless show_always?
else
- errors[:base] << "Unexpected value of recurrence target selector '#{target}'"
+ errors.add(:base, "Unexpected value of recurrence target selector '#{target}'")
end
end
diff --git a/app/models/recurring_todos/daily_recurrence_pattern.rb b/app/models/recurring_todos/daily_recurrence_pattern.rb
index 35a0ea16..8caaa716 100644
--- a/app/models/recurring_todos/daily_recurrence_pattern.rb
+++ b/app/models/recurring_todos/daily_recurrence_pattern.rb
@@ -24,7 +24,7 @@ module RecurringTodos
def validate
super
- errors[:base] << "Every other nth day may not be empty for this daily recurrence setting" if (!only_work_days?) && every_x_days.blank?
+ errors.add(:base, "Every other nth day may not be empty for this daily recurrence setting") if (!only_work_days?) && every_x_days.blank?
end
def get_next_date(previous)
diff --git a/app/models/recurring_todos/weekly_recurrence_pattern.rb b/app/models/recurring_todos/weekly_recurrence_pattern.rb
index 5ba3a13f..c554b016 100644
--- a/app/models/recurring_todos/weekly_recurrence_pattern.rb
+++ b/app/models/recurring_todos/weekly_recurrence_pattern.rb
@@ -30,7 +30,7 @@ module RecurringTodos
super
validate_not_blank(every_x_week, "Every other nth week may not be empty for weekly recurrence setting")
something_set = %w{ sunday monday tuesday wednesday thursday friday saturday }.inject(false) { |set, day| set || send("on_#{day}") }
- errors[:base] << "You must specify at least one day on which the todo recurs" unless something_set
+ errors.add(:base, "You must specify at least one day on which the todo recurs") unless something_set
end
def get_next_date(previous)
diff --git a/db/migrate/038_projects_contexts_remove_not_null_from_position.rb b/db/migrate/038_projects_contexts_remove_not_null_from_position.rb
index af167857..45ea7c26 100644
--- a/db/migrate/038_projects_contexts_remove_not_null_from_position.rb
+++ b/db/migrate/038_projects_contexts_remove_not_null_from_position.rb
@@ -1,7 +1,7 @@
class ProjectsContextsRemoveNotNullFromPosition < ActiveRecord::Migration[5.2]
def self.up
- change_column :projects, :position, :integer, {:null => true, :default => nil}
- change_column :contexts, :position, :integer, {:null => true, :default => nil}
+ change_column :projects, :position, :integer, :null => true, :default => nil
+ change_column :contexts, :position, :integer, :null => true, :default => nil
end
def self.down
@@ -10,13 +10,13 @@ class ProjectsContextsRemoveNotNullFromPosition < ActiveRecord::Migration[5.2]
project.position = 0 if !project.position?
project.save
end
- change_column :projects, :position, :integer, {:null => false, :default => nil}
+ change_column :projects, :position, :integer, :null => false, :default => nil
@contexts = Context.find(:all)
@contexts.each do |context|
context.position = 0 if !context.position?
context.save
end
- change_column :contexts, :position, :integer, {:null => false, :default => nil}
+ change_column :contexts, :position, :integer, :null => false, :default => nil
end
end
diff --git a/test/models/todo_test.rb b/test/models/todo_test.rb
index c257c0fe..dd1e084b 100644
--- a/test/models/todo_test.rb
+++ b/test/models/todo_test.rb
@@ -102,7 +102,7 @@ class TodoTest < ActiveSupport::TestCase
@not_completed2
assert_equal :active, @not_completed2.aasm.current_state
@not_completed2.show_from = Time.zone.now + 1.week
- assert @not_completed2.save, "should have saved successfully" + @not_completed2.errors.to_xml
+ assert @not_completed2.save, "should have saved successfully " + @not_completed2.errors.full_messages.to_s
assert_equal :deferred, @not_completed2.aasm.current_state
end
@@ -112,14 +112,14 @@ class TodoTest < ActiveSupport::TestCase
todo.show_from = next_week
todo.context_id = 1
todo.description = 'foo'
- assert todo.save, "should have saved successfully" + todo.errors.to_xml
+ assert todo.save, "should have saved successfully" + todo.errors.full_messages.to_s
assert_equal :deferred, todo.aasm.current_state
end
def test_create_a_new_deferred_todo_by_passing_attributes
user = users(:other_user)
todo = user.todos.build(:show_from => next_week, :context_id => 1, :description => 'foo')
- assert todo.save, "should have saved successfully" + todo.errors.to_xml
+ assert todo.save, "should have saved successfully " + todo.errors.full_messages.to_s
assert_equal :deferred, todo.aasm.current_state
end
@@ -551,7 +551,7 @@ class TodoTest < ActiveSupport::TestCase
new_path = attachment.file.path
# then the attachment should be there
- assert File.exists?(new_path), "attachment should be on file system"
+ assert File.exist?(new_path), "attachment should be on file system"
assert_equal 1, todo.attachments.reload.count, "should have one attachment"
# When I destroy the todo
@@ -559,7 +559,7 @@ class TodoTest < ActiveSupport::TestCase
# Then the attachement and file should nogt be there anymore
assert_equal 0, todo.user.attachments.reload.count
- assert !File.exists?(new_path), "attachment should not be on file system"
+ assert !File.exist?(new_path), "attachment should not be on file system"
end
def test_destroying_action_activates_successors
From a94d4fa00baeb4c78b4d1f3ff675f7ae322493a3 Mon Sep 17 00:00:00 2001
From: Jyri-Petteri Paloposki
Date: Thu, 6 Jun 2024 02:04:29 +0300
Subject: [PATCH 3/3] Remove the inbound message handling to get the Rails
upgrade done. Pull requests for re-implementing with ActionMailbox are
welcome.
Fixes #2463.
---
app/controllers/integrations_controller.rb | 26 +---
app/controllers/mailgun_controller.rb | 36 -----
app/models/message_gateway.rb | 141 ------------------
app/views/integrations/index.html.erb | 37 -----
.../integrations_controller_test.rb | 61 --------
test/controllers/mailgun_controller_test.rb | 74 ---------
test/controllers/message_gateway_test.rb | 103 -------------
7 files changed, 1 insertion(+), 477 deletions(-)
delete mode 100644 app/controllers/mailgun_controller.rb
delete mode 100644 app/models/message_gateway.rb
delete mode 100644 test/controllers/mailgun_controller_test.rb
delete mode 100644 test/controllers/message_gateway_test.rb
diff --git a/app/controllers/integrations_controller.rb b/app/controllers/integrations_controller.rb
index bb47497b..fd5b4238 100644
--- a/app/controllers/integrations_controller.rb
+++ b/app/controllers/integrations_controller.rb
@@ -1,8 +1,7 @@
class IntegrationsController < ApplicationController
require 'mail'
- skip_before_action :login_required, :only => [:cloudmailin, :search_plugin]
- skip_before_action :verify_authenticity_token, only: [:cloudmailin]
+ skip_before_action :login_required, :only => [:search_plugin]
def index
@page_title = 'TRACKS::Integrations'
@@ -21,31 +20,8 @@ class IntegrationsController < ApplicationController
.pack('m').gsub(/\n/, '')
end
- def cloudmailin
- if !verify_cloudmailin_signature
- render :body => "Message signature verification failed.", :status => 403
- return false
- end
-
- if process_message(params[:message])
- render :body => 'success', :status => 200
- else
- render :body => "No user found or other error", :status => 404
- end
- end
-
private
- def process_message(message)
- MessageGateway.receive(Mail.new(message))
- end
-
- def verify_cloudmailin_signature
- provided = request.request_parameters.delete(:signature)
- signature = Digest::MD5.hexdigest(flatten_params(request.request_parameters).sort.map { |k, v| v }.join + SITE_CONFIG['cloudmailin'])
- return provided == signature
- end
-
def flatten_params(params, title = nil, result = {})
params.each do |key, value|
if value.is_a? Hash
diff --git a/app/controllers/mailgun_controller.rb b/app/controllers/mailgun_controller.rb
deleted file mode 100644
index d3eac091..00000000
--- a/app/controllers/mailgun_controller.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-require 'openssl'
-
-class MailgunController < ApplicationController
- skip_before_action :login_required, :only => [:mailgun]
- before_action :verify, :only => [:mailgun]
- protect_from_forgery with: :null_session
-
- def mailgun
- unless params.include? 'body-mime'
- Rails.logger.info "Cannot process Mailgun request, no body-mime sent"
- render_failure "Unacceptable body-mime", 406
- return
- end
-
- todo = MessageGateway.receive(params['body-mime'])
- if todo
- render :xml => todo.to_xml(*todo_xml_params)
- else
- render_failure "Todo not saved", 406
- end
- end
-
- private
-
- def verify
- unless params['signature'] == OpenSSL::HMAC.hexdigest(
- OpenSSL::Digest.new('sha256'),
- SITE_CONFIG['mailgun_api_key'],
- '%s%s' % [params['timestamp'], params['token']]
- )
- Rails.logger.info "Cannot verify Mailgun signature"
- render_failure "Access denied", 406
- return
- end
- end
-end
diff --git a/app/models/message_gateway.rb b/app/models/message_gateway.rb
deleted file mode 100644
index 2a125cd7..00000000
--- a/app/models/message_gateway.rb
+++ /dev/null
@@ -1,141 +0,0 @@
-class MessageGateway < ActionMailer::Base
- def receive(email)
- user = get_receiving_user_from_email_address(email)
- return false if user.nil?
- return false unless check_sender_is_in_mailmap(user, email)
-
- context = user.prefs.sms_context
- todo_params = get_todo_params(email)
-
- todo_builder = TodoFromRichMessage.new(user, context.id, todo_params[:description], todo_params[:notes])
- todo = todo_builder.construct
-
- if todo.save!
- Rails.logger.info "Saved email as todo for user #{user.login} in context #{context.name}"
-
- if attach_email_to_todo(todo, email)
- Rails.logger.info "Saved email as attachment to todo for user #{user.login} in context #{context.name}"
- end
- end
- todo
- end
-
- private
-
- def attach_email_to_todo(todo, email)
- attachment = todo.attachments.build
-
- # create temp file
- tmp = Tempfile.new(['attachment', '.eml'], universal_newline: true)
- tmp.write email.raw_source.gsub(/\r/, "")
-
- # add temp file to attachment. paperclip will copy the file to the right location
- Rails.logger.info "Saved received email to #{tmp.path}"
- attachment.file = tmp
- tmp.close
- saved = attachment.save!
-
- # enable write permissions on group, since MessageGateway could be run under different
- # user than Tracks (i.e. apache versus mail)
- dir = File.open(File.dirname(attachment.file.path))
- dir.chmod(0770)
-
- # delete temp file
- tmp.unlink
- end
-
- def get_todo_params(email)
- params = {}
-
- if email.multipart?
- params[:description] = get_text_or_nil(email.subject)
- params[:notes] = get_first_text_plain_part(email)
- else
- if email.subject.blank?
- params[:description] = get_decoded_text_or_nil(email.body)
- params[:notes] = nil
- else
- params[:description] = get_text_or_nil(email.subject)
- params[:notes] = get_decoded_text_or_nil(email.body)
- end
- end
- params
- end
-
- def get_receiving_user_from_email_address(email)
- SITE_CONFIG['email_dispatch'] == 'single_user' ? get_receiving_user_from_env_setting : get_receiving_user_from_mail_header(email)
- end
-
- def get_receiving_user_from_env_setting
- Rails.logger.info "All received email goes to #{ENV['TRACKS_MAIL_RECEIVER']}"
- user = User.where(:login => ENV['TRACKS_MAIL_RECEIVER']).first
- Rails.logger.info "WARNING: Unknown user set for TRACKS_MAIL_RECEIVER (#{ENV['TRACKS_MAIL_RECEIVER']})" if user.nil?
- return user
- end
-
- def get_receiving_user_from_mail_header(email)
- user = get_receiving_user_from_sms_email(get_address(email))
- Rails.logger.info(user.nil? ? "User unknown" : "Email belongs to #{user.login}")
- return user
- end
-
- def get_address(email)
- return SITE_CONFIG['email_dispatch'] == 'to' ? email.to[0] : email.from[0]
- end
-
- def get_receiving_user_from_sms_email(address)
- Rails.logger.info "Looking for user with email #{address}"
- user = User.where("preferences.sms_email" => address.strip).includes(:preference).first
- user = User.where("preferences.sms_email" => address.strip[1.100]).includes(:preference).first if user.nil?
- return user
- end
-
- def check_sender_is_in_mailmap(user, email)
- if user.present? && !sender_is_in_mailmap?(user, email)
- Rails.logger.warn "#{email.from[0]} not found in mailmap for #{user.login}"
- return false
- end
- return true
- end
-
- def sender_is_in_mailmap?(user, email)
- if (SITE_CONFIG['mailmap'].is_a? Hash) && SITE_CONFIG['email_dispatch'] == 'to'
- # Look for the sender in the map of allowed senders
- SITE_CONFIG['mailmap'][user.preference.sms_email].include? email.from[0]
- else
- # We can't check the map if it's not defined, or if the lookup is the
- # wrong way round, so just allow it
- true
- end
- end
-
- def get_text_or_nil(text)
- return text ? text.strip : nil
- end
-
- def get_decoded_text_or_nil(text)
- return text ? text.decoded.strip : nil
- end
-
- def get_first_text_plain_part(email)
- # get all parts from multipart/alternative attachments
- parts = get_all_parts(email.parts)
-
- # remove all parts that are not text/plain
- parts.reject { |part| !part.content_type.start_with?("text/plain") }
-
- return parts.count > 0 ? parts[0].decoded.strip : ""
- end
-
- def get_all_parts(parts)
- # return a flattened array of parts. If a multipart attachment is found, recurse over its parts
- all_parts = parts.inject([]) do |set, elem|
- if elem.content_type.start_with?("multipart/alternative")
- # recurse to handle multiparts in this multipart
- set += get_all_parts(elem.parts)
- else
- set << elem
- end
- end
- end
-end
diff --git a/app/views/integrations/index.html.erb b/app/views/integrations/index.html.erb
index 5de4fbf9..a8db5c15 100644
--- a/app/views/integrations/index.html.erb
+++ b/app/views/integrations/index.html.erb
@@ -4,8 +4,6 @@
<%= I18n.t 'integrations.contents_header' %>
<%= raw I18n.t 'integrations.add_your_own', tell_us_link: link_to(I18n.t('integrations.tell_us_link_text'), 'https://github.com/TracksApp/tracks/issues') %>
@@ -19,41 +17,6 @@
<%= raw I18n.t 'integrations.cron_2', feeds_link: link_to(I18n.t('integrations.feeds_link_text'), feeds_path) %>
-
-<%= I18n.t 'integrations.sections.message_gateway' %>
-<%= I18n.t 'integrations.message_gateway.description' %>
-
-<%= I18n.t 'integrations.message_gateway.rich_api_tip' %>
-<%= raw I18n.t 'integrations.message_gateway.configuration', site_yml: 'site.yml', to_name: 'to:', from_name: 'from:' %>
-<%= raw I18n.t 'integrations.message_gateway.one_user_configuration', single_user_value: 'single_user', code: "
TRACKS_MAIL_RECEIVER=" + current_user.login + " /PATH/TO/TRACKS/bin/rails r -e production 'MessageGateway.receive(STDIN.read)'
" %>
-
-
-<%= I18n.t 'integrations.sections.mailgun' %>
-<%= raw I18n.t 'integrations.mailgun.description', mailgun_link: link_to('Mailgun', 'http://www.mailgun.com/') %>
-<%= I18n.t 'integrations.mailgun.conditions' %>
-
-<%= I18n.t 'integrations.mailgun.gateway_instructions' %>
-
<%= I18n.t 'integrations.sections.email_rich' %>
<%= I18n.t 'integrations.email_rich.description' %>
diff --git a/test/controllers/integrations_controller_test.rb b/test/controllers/integrations_controller_test.rb
index d01c0e06..bfbcd42d 100644
--- a/test/controllers/integrations_controller_test.rb
+++ b/test/controllers/integrations_controller_test.rb
@@ -13,65 +13,4 @@ class IntegrationsControllerTest < ActionController::TestCase
assert_response :success
end
- def test_cloudmailin_integration_success
- stub_site_config do
- SITE_CONFIG['cloudmailin'] = "123456789"
- SITE_CONFIG['email_dispatch'] = 'from'
- post :cloudmailin, params: {
- "html"=>"",
- "plain"=>"asdasd",
- "x_to_header"=>"[\"81496ecea21032d35a7a@cloudmailin.net\"]",
- "disposable"=>"",
- "from"=>"5555555555@tmomail.net",
- "signature"=>"e85e908fb893394762047c21e54ce248",
- "to"=>"<123123@cloudmailin.net>",
- "subject"=>"asd",
- "x_cc_header"=>"",
- "message"=>"Received: from VMBX103.ihostexchange.net ([192.168.3.3]) by\r\n HUB103.ihostexchange.net ([66.46.182.53]) with mapi; Wed, 5 Oct 2011 17:12:44\r\n -0400\r\nFrom: SMS User <5555555555@tmomail.net>\r\nTo: Tracks <123123@cloudmailin.net>\r\nDate: Wed, 5 Oct 2011 17:12:43 -0400\r\nSubject: asd\r\nThread-Topic: asd\r\nThread-Index: AcyDo4aig2wghvcsTAOkleWqi4t/FQ==\r\nMessage-ID: <7D7CB176-7559-4997-A301-8DF9726264C7@tmomail.net>\r\nAccept-Language: de-DE, en-US\r\nContent-Language: en-US\r\nX-MS-Has-Attach:\r\nX-MS-TNEF-Correlator:\r\nacceptlanguage: de-DE, en-US\r\nContent-Type: text/plain; charset=\"us-ascii\"\r\nContent-Transfer-Encoding: quoted-printable\r\nMIME-Version: 1.0\r\n\r\nasdasd\r\n"
- }
-
- assert_response :success
- end
- end
-
- def test_cloudmailin_integration_invalid_signature
- stub_site_config do
- SITE_CONFIG['cloudmailin'] = "12345678901234567890"
- post :cloudmailin, params: {
- "html"=>"",
- "plain"=>"asdasd",
- "x_to_header"=>"[\"81496ecea21032d35a7a@cloudmailin.net\"]",
- "disposable"=>"",
- "from"=>"5555555555@tmomail.net",
- "signature"=>"e85e908fb893394762047c21e54ce248",
- "to"=>"<123123@cloudmailin.net>",
- "subject"=>"asd",
- "x_cc_header"=>"",
- "message"=>"Received: from VMBX103.ihostexchange.net ([192.168.3.3]) by\r\n HUB103.ihostexchange.net ([66.46.182.53]) with mapi; Wed, 5 Oct 2011 17:12:44\r\n -0400\r\nFrom: SMS User <5555555555@tmomail.net>\r\nTo: Tracks <123123@cloudmailin.net>\r\nDate: Wed, 5 Oct 2011 17:12:43 -0400\r\nSubject: asd\r\nThread-Topic: asd\r\nThread-Index: AcyDo4aig2wghvcsTAOkleWqi4t/FQ==\r\nMessage-ID: <7D7CB176-7559-4997-A301-8DF9726264C7@tmomail.net>\r\nAccept-Language: de-DE, en-US\r\nContent-Language: en-US\r\nX-MS-Has-Attach:\r\nX-MS-TNEF-Correlator:\r\nacceptlanguage: de-DE, en-US\r\nContent-Type: text/plain; charset=\"us-ascii\"\r\nContent-Transfer-Encoding: quoted-printable\r\nMIME-Version: 1.0\r\n\r\nasdasd\r\n"
- }
-
- assert_response 403
- end
- end
-
- def test_cloudmailin_integration_unknown_address
- stub_site_config do
- SITE_CONFIG['cloudmailin'] = "123456789"
- post :cloudmailin, params: {
- "html"=>"",
- "plain"=>"asdasd",
- "x_to_header"=>"[\"81496ecea21032d35a7a@cloudmailin.net\"]",
- "disposable"=>"",
- "from"=>"444444444444@tmomail.net",
- "signature"=>"6d2df0e807bfa9b77d24c31dce6d4515",
- "to"=>"<123123@cloudmailin.net>",
- "subject"=>"asd",
- "x_cc_header"=>"",
- "message"=>"Received: from VMBX103.ihostexchange.net ([192.168.3.3]) by\r\n HUB103.ihostexchange.net ([66.46.182.53]) with mapi; Wed, 5 Oct 2011 17:12:44\r\n -0400\r\nFrom: SMS User <444444444444@tmomail.net>\r\nTo: Tracks <123123@cloudmailin.net>\r\nDate: Wed, 5 Oct 2011 17:12:43 -0400\r\nSubject: asd\r\nThread-Topic: asd\r\nThread-Index: AcyDo4aig2wghvcsTAOkleWqi4t/FQ==\r\nMessage-ID: <7D7CB176-7559-4997-A301-8DF9726264C7@tmomail.net>\r\nAccept-Language: de-DE, en-US\r\nContent-Language: en-US\r\nX-MS-Has-Attach:\r\nX-MS-TNEF-Correlator:\r\nacceptlanguage: de-DE, en-US\r\nContent-Type: text/plain; charset=\"us-ascii\"\r\nContent-Transfer-Encoding: quoted-printable\r\nMIME-Version: 1.0\r\n\r\nasdasd\r\n"
- }
-
- assert_response 404
- end
- end
-
end
diff --git a/test/controllers/mailgun_controller_test.rb b/test/controllers/mailgun_controller_test.rb
deleted file mode 100644
index 0b1300e2..00000000
--- a/test/controllers/mailgun_controller_test.rb
+++ /dev/null
@@ -1,74 +0,0 @@
-require 'test_helper'
-require 'support/stub_site_config_helper'
-
-class MailgunControllerTest < ActionController::TestCase
- include StubSiteConfigHelper
-
- def setup
- @user = users(:sms_user)
- @inbox = contexts(:inbox)
- end
-
- def load_message(filename)
- File.read(File.join(Rails.root, 'test', 'fixtures', filename))
- end
-
- def test_mailgun_signature_verifies
- stub_site_config do
- SITE_CONFIG['mailgun_api_key'] = "123456789"
- SITE_CONFIG['email_dispatch'] = 'from'
-
- post :mailgun, params: {
- "timestamp" => "1379539674",
- "token" => "5km6cwo0e3bfvg78hw4s69znro09xhk1h8u6-s633yasc8hcr5",
- "signature" => "da92708b8f2c9dcd7ecdc91d52946c01802833e6683e46fc00b3f081920dd5b1",
- "body-mime" => load_message('mailgun_message1.txt')
- }
-
- assert_response :success
- end
- end
-
- def test_mailgun_creates_todo_with_mailmap
- stub_site_config do
- SITE_CONFIG['mailgun_api_key'] = "123456789"
- SITE_CONFIG['email_dispatch'] = 'to'
- SITE_CONFIG['mailmap'] = {
- '5555555555@tmomail.net' => ['incoming@othermail.com', 'notused@foo.org']
- }
-
- todo_count = Todo.count
- post :mailgun, params: {
- "timestamp" => "1379539674",
- "token" => "5km6cwo0e3bfvg78hw4s69znro09xhk1h8u6-s633yasc8hcr5",
- "signature" => "da92708b8f2c9dcd7ecdc91d52946c01802833e6683e46fc00b3f081920dd5b1",
- "body-mime" => load_message('mailgun_message2.txt')
- }
-
- assert_response :success
-
- assert_equal(todo_count+1, Todo.count)
- message_todo = Todo.where(:description => "test").first
- assert_not_nil(message_todo)
- assert_equal(@inbox, message_todo.context)
- assert_equal(@user, message_todo.user)
- end
- end
-
- def test_mailgun_signature_fails
- stub_site_config do
- SITE_CONFIG['mailgun_api_key'] = "invalidkey"
- SITE_CONFIG['email_dispatch'] = 'from'
-
- post :mailgun, params: {
- "timestamp" => "1379539674",
- "token" => "5km6cwo0e3bfvg78hw4s69znro09xhk1h8u6-s633yasc8hcr5",
- "signature" => "da92708b8f2c9dcd7ecdc91d52946c01802833e6683e46fc00b3f081920dd5b1",
- "body-mime" => load_message('mailgun_message1.txt')
- }
-
- assert_response 406
- end
- end
-
-end
diff --git a/test/controllers/message_gateway_test.rb b/test/controllers/message_gateway_test.rb
deleted file mode 100644
index 6bb3eab9..00000000
--- a/test/controllers/message_gateway_test.rb
+++ /dev/null
@@ -1,103 +0,0 @@
-require 'test_helper'
-
-class MessageGatewayTest < ActiveSupport::TestCase
-
- def setup
- @user = users(:sms_user)
- @inbox = contexts(:inbox)
- end
-
- def load_message(filename)
- MessageGateway.receive(File.read(File.join(Rails.root, 'test', 'fixtures', filename)))
- end
-
- def test_sms_with_no_subject
- todo_count = Todo.count
-
- load_message('sample_sms.txt')
- # assert some stuff about it being created
- assert_equal(todo_count+1, Todo.count)
-
- message_todo = Todo.where(:description => "message_content").first
- assert_not_nil(message_todo)
-
- assert_equal(@inbox, message_todo.context)
- assert_equal(@user, message_todo.user)
- end
-
- def test_mms_with_subject
- todo_count = Todo.count
-
- load_message('sample_mms.txt')
-
- # assert some stuff about it being created
- assert_equal(todo_count+1, Todo.count)
-
- message_todo = Todo.where(:description => "This is the subject").first
- assert_not_nil(message_todo)
-
- assert_equal(@inbox, message_todo.context)
- assert_equal(@user, message_todo.user)
- assert_equal("This is the message body", message_todo.notes)
- end
-
- def test_email_with_winmail_dat
- todo_count = Todo.count
-
- load_message('email_with_winmail.txt')
-
- # assert some stuff about it being created
- assert_equal(todo_count+1, Todo.count)
- end
-
- def test_email_with_multipart_attachments
- todo_count = Todo.count
-
- load_message('email_with_multipart.txt')
-
- # assert some stuff about it being created
- assert_equal(todo_count+1, Todo.count)
- end
-
- def test_no_user
- todo_count = Todo.count
- badmessage = File.read(File.join(Rails.root, 'test', 'fixtures', 'sample_sms.txt'))
- badmessage.gsub!("5555555555", "notauser")
- MessageGateway.receive(badmessage)
- assert_equal(todo_count, Todo.count)
- end
-
- def test_direct_to_context
- message = File.read(File.join(Rails.root, 'test', 'fixtures', 'sample_sms.txt'))
-
- valid_context_msg = message.gsub('message_content', 'this is a task @ anothercontext')
- invalid_context_msg = message.gsub('message_content', 'this is also a task @ notacontext')
-
- MessageGateway.receive(valid_context_msg)
- valid_context_todo = Todo.where(:description => "this is a task").first
- assert_not_nil(valid_context_todo)
- assert_equal(contexts(:anothercontext), valid_context_todo.context)
-
- MessageGateway.receive(invalid_context_msg)
- invalid_context_todo = Todo.where(:description => 'this is also a task').first
- assert_not_nil(invalid_context_todo)
- assert_equal(@inbox, invalid_context_todo.context)
- end
-
- def test_receiving_email_adds_attachment
- attachment_count = Attachment.count
-
- load_message('sample_mms.txt')
-
- message_todo = Todo.where(:description => "This is the subject").first
- assert_not_nil(message_todo)
-
- assert_equal attachment_count+1, Attachment.count
- assert_equal 1,message_todo.attachments.count
-
- orig = File.read(File.join(Rails.root, 'test', 'fixtures', 'sample_mms.txt'))
- attachment = File.read(message_todo.attachments.first.file.path)
-
- assert_equal orig, attachment
- end
-end