From 456f7b05ca87278d6efbf92455033e6ae7135281 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Wed, 11 Mar 2020 10:16:36 +0100 Subject: [PATCH 1/4] Allow mail_handler to find case insensitive keys --- app/models/mail_handler.rb | 16 +++-- .../wp_on_given_project_case_insensitive.eml | 61 +++++++++++++++++++ spec/models/mail_handler_spec.rb | 35 +++++++++++ 3 files changed, 107 insertions(+), 5 deletions(-) create mode 100644 spec/fixtures/mail_handler/wp_on_given_project_case_insensitive.eml diff --git a/app/models/mail_handler.rb b/app/models/mail_handler.rb index 60a4e3f68ab..c95dfe86b1f 100644 --- a/app/models/mail_handler.rb +++ b/app/models/mail_handler.rb @@ -334,13 +334,13 @@ class MailHandler < ActionMailer::Base project = issue.project attrs = { - 'type_id' => (k = get_keyword(:type)) && project.types.find_by(name: k).try(:id), - 'status_id' => (k = get_keyword(:status)) && Status.find_by(name: k).try(:id), + 'type_id' => lookup_case_insensitive_key(project.types, :type), + 'status_id' => lookup_case_insensitive_key(Status, :status), 'parent_id' => (k = get_keyword(:parent)), - 'priority_id' => (k = get_keyword(:priority)) && IssuePriority.find_by(name: k).try(:id), - 'category_id' => (k = get_keyword(:category)) && project.categories.find_by(name: k).try(:id), + 'priority_id' => lookup_case_insensitive_key(IssuePriority, :priority), + 'category_id' => lookup_case_insensitive_key(project.categories, :category), 'assigned_to_id' => assigned_to.try(:id), - 'fixed_version_id' => (k = get_keyword(:fixed_version)) && project.shared_versions.find_by(name: k).try(:id), + 'fixed_version_id' => lookup_case_insensitive_key(project.shared_versions, :fixed_version, Arel.sql("#{Version.table_name}.name")), 'start_date' => get_keyword(:start_date, override: true, format: '\d{4}-\d{2}-\d{2}'), 'due_date' => get_keyword(:due_date, override: true, format: '\d{4}-\d{2}-\d{2}'), 'estimated_hours' => get_keyword(:estimated_hours, override: true), @@ -363,6 +363,12 @@ class MailHandler < ActionMailer::Base end end + def lookup_case_insensitive_key(scope, attribute, column_name = Arel.sql('name')) + if k = get_keyword(attribute) + scope.find_by("lower(#{column_name}) = ?", k.downcase).try(:id) + end + end + # Returns the text/plain part of the email # If not found (eg. HTML-only email), returns the body with tags removed def plain_text_body diff --git a/spec/fixtures/mail_handler/wp_on_given_project_case_insensitive.eml b/spec/fixtures/mail_handler/wp_on_given_project_case_insensitive.eml new file mode 100644 index 00000000000..b77e3dfe520 --- /dev/null +++ b/spec/fixtures/mail_handler/wp_on_given_project_case_insensitive.eml @@ -0,0 +1,61 @@ +Return-Path: +Received: from osiris ([127.0.0.1]) + by OSIRIS + with hMailServer ; Sun, 22 Jun 2008 12:28:07 +0200 +Message-ID: <000501c8d452$a95cd7e0$0a00a8c0@osiris> +From: "John Smith" +To: +Subject: New ticket on a given project +Date: Sun, 22 Jun 2008 12:28:07 +0200 +MIME-Version: 1.0 +Content-Type: text/plain; + format=flowed; + charset="iso-8859-1"; + reply-type=original +Content-Transfer-Encoding: 7bit +X-Priority: 3 +X-MSMail-Priority: Normal +X-Mailer: Microsoft Outlook Express 6.00.2900.2869 +X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.2869 + +Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas imperdiet +turpis et odio. Integer eget pede vel dolor euismod varius. Phasellus +blandit eleifend augue. Nulla facilisi. Duis id diam. Class aptent taciti +sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. In +in urna sed tellus aliquet lobortis. Morbi scelerisque tortor in dolor. Cras +sagittis odio eu lacus. Aliquam sem tortor, consequat sit amet, vestibulum +id, iaculis at, lectus. Fusce tortor libero, congue ut, euismod nec, luctus +eget, eros. Pellentesque tortor enim, feugiat in, dignissim eget, tristique +sed, mauris --- Pellentesque habitant morbi tristique senectus et netus et +malesuada fames ac turpis egestas. Quisque sit amet libero. In hac habitasse +platea dictumst. + +--- This line starts with a delimiter and should not be stripped + +This paragraph is before delimiters. + +BREAK + +This paragraph is between delimiters. + +--- + +This paragraph is after the delimiter so it shouldn't appear. + +Nulla et nunc. Duis pede. Donec et ipsum. Nam ut dui tincidunt neque +sollicitudin iaculis. Duis vitae dolor. Vestibulum eget massa. Sed lorem. +Nullam volutpat cursus erat. Cras felis dolor, lacinia quis, rutrum et, +dictum et, ligula. Sed erat nibh, gravida in, accumsan non, placerat sed, +massa. Sed sodales, ante fermentum ultricies sollicitudin, massa leo +pulvinar dui, a gravida orci mi eget odio. Nunc a lacus. + +Project: onlinestore +status: resolved +due date: 2010-12-31 +Start Date:2010-01-01 +Assigned to: John Smith +fixed version: ALPHA +priority: low +estimated hours: 2.5 +done ratio: 30 + diff --git a/spec/models/mail_handler_spec.rb b/spec/models/mail_handler_spec.rb index e0316c862ad..2c7c0d81c7c 100644 --- a/spec/models/mail_handler_spec.rb +++ b/spec/models/mail_handler_spec.rb @@ -66,6 +66,23 @@ describe MailHandler, type: :model do end end + shared_context 'wp_on_given_project_case_insensitive' do + let(:permissions) { %i[add_work_packages assign_versions] } + let!(:user) do + FactoryBot.create(:user, + mail: 'JSmith@somenet.foo', + firstname: 'John', + lastname: 'Smith', + member_in_project: project, + member_with_permissions: permissions) + end + let(:submit_options) { {} } + + subject do + submit_email('wp_on_given_project_case_insensitive.eml', **submit_options) + end + end + shared_context 'wp_update_with_quoted_reply_above' do let(:permissions) { %i[edit_work_packages view_work_packages] } let!(:user) do @@ -344,6 +361,24 @@ describe MailHandler, type: :model do .to eql(status) end end + + context 'wp with status case insensitive' do + let!(:status) { FactoryBot.create(:status, name: 'Resolved') } + let!(:priority_low) { FactoryBot.create(:priority_low, name: 'Low', is_default: true) } + let!(:version) { FactoryBot.create(:version, name: 'alpha', project: project) } + let(:submit_options) { {allow_override: 'fixed_version'} } + + # This email contains: 'Project: onlinestore' and 'Status: resolved' + include_context 'wp_on_given_project_case_insensitive' + + it_behaves_like 'work package created' + + it 'assigns the status to the created work package' do + expect(subject.status).to eq(status) + expect(subject.fixed_version).to eq(version) + expect(subject.priority).to eq priority_low + end + end end describe 'update work package' do From 18e4ed1a9a2ef6808617aa0784165075be981f6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Wed, 11 Mar 2020 11:13:27 +0100 Subject: [PATCH 2/4] Change case insensitive validations to false --- app/models/category.rb | 2 +- app/models/enumeration.rb | 4 +++- app/models/type.rb | 2 +- app/models/version.rb | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/app/models/category.rb b/app/models/category.rb index a905aacdcbc..1db15e12455 100644 --- a/app/models/category.rb +++ b/app/models/category.rb @@ -33,7 +33,7 @@ class Category < ActiveRecord::Base has_many :work_packages, foreign_key: 'category_id', dependent: :nullify validates :name, - uniqueness: { scope: [:project_id], case_sensitive: true }, + uniqueness: { scope: [:project_id], case_sensitive: false }, length: { maximum: 255 } # validates that assignee is member of the issue category's project diff --git a/app/models/enumeration.rb b/app/models/enumeration.rb index ea7ac137ab2..7c9c4cdd436 100644 --- a/app/models/enumeration.rb +++ b/app/models/enumeration.rb @@ -40,7 +40,9 @@ class Enumeration < ActiveRecord::Base before_destroy :check_integrity validates_presence_of :name - validates_uniqueness_of :name, scope: %i(type project_id) + validates_uniqueness_of :name, + scope: %i(type project_id), + case_sensitive: false validates_length_of :name, maximum: 30 scope :shared, -> { where(project_id: nil) } diff --git a/app/models/type.rb b/app/models/type.rb index 070b350dcd4..1a86a8d99af 100644 --- a/app/models/type.rb +++ b/app/models/type.rb @@ -59,7 +59,7 @@ class ::Type < ActiveRecord::Base validates :name, presence: true, - uniqueness: { case_sensitive: true }, + uniqueness: { case_sensitive: false }, length: { maximum: 255 } validates_inclusion_of :is_default, :is_milestone, in: [true, false] diff --git a/app/models/version.rb b/app/models/version.rb index 2b673d96ab8..e74e12ee0ae 100644 --- a/app/models/version.rb +++ b/app/models/version.rb @@ -41,7 +41,7 @@ class Version < ActiveRecord::Base validates :name, presence: true, - uniqueness: { scope: [:project_id], case_sensitive: true } + uniqueness: { scope: [:project_id], case_sensitive: false } validates_format_of :effective_date, with: /\A\d{4}-\d{2}-\d{2}\z/, message: :not_a_date, allow_nil: true validates_format_of :start_date, with: /\A\d{4}-\d{2}-\d{2}\z/, message: :not_a_date, allow_nil: true From da52a19bab053dd1f4b13f7ebd22026805f310f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Wed, 11 Mar 2020 13:20:58 +0100 Subject: [PATCH 3/4] Remove duplicate type_standard "None" and "none" in legacy spec --- spec_legacy/fixtures/types.yml | 2 +- spec_legacy/unit/project_spec.rb | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/spec_legacy/fixtures/types.yml b/spec_legacy/fixtures/types.yml index 779d790db32..c5f72d945ca 100644 --- a/spec_legacy/fixtures/types.yml +++ b/spec_legacy/fixtures/types.yml @@ -43,7 +43,7 @@ types_003: position: 3 is_default: true types_999: - name: none + name: None id: 999 is_standard: true position: 0 diff --git a/spec_legacy/unit/project_spec.rb b/spec_legacy/unit/project_spec.rb index 03d75b7c3cb..e39e6890f1f 100644 --- a/spec_legacy/unit/project_spec.rb +++ b/spec_legacy/unit/project_spec.rb @@ -33,7 +33,6 @@ describe Project, type: :model do fixtures :all before do - FactoryBot.create(:type_standard) @ecookbook = Project.find(1) @ecookbook_sub1 = Project.find(3) User.current = nil From b42f9892310d34933bb935b554c777296a64df1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Wed, 11 Mar 2020 13:23:55 +0100 Subject: [PATCH 4/4] Avoid overridden submit_options in context --- spec/models/mail_handler_spec.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/spec/models/mail_handler_spec.rb b/spec/models/mail_handler_spec.rb index 2c7c0d81c7c..a6e9d6ea8bd 100644 --- a/spec/models/mail_handler_spec.rb +++ b/spec/models/mail_handler_spec.rb @@ -76,7 +76,7 @@ describe MailHandler, type: :model do member_in_project: project, member_with_permissions: permissions) end - let(:submit_options) { {} } + let(:submit_options) { {allow_override: 'fixed_version'} } subject do submit_email('wp_on_given_project_case_insensitive.eml', **submit_options) @@ -366,7 +366,6 @@ describe MailHandler, type: :model do let!(:status) { FactoryBot.create(:status, name: 'Resolved') } let!(:priority_low) { FactoryBot.create(:priority_low, name: 'Low', is_default: true) } let!(:version) { FactoryBot.create(:version, name: 'alpha', project: project) } - let(:submit_options) { {allow_override: 'fixed_version'} } # This email contains: 'Project: onlinestore' and 'Status: resolved' include_context 'wp_on_given_project_case_insensitive'