Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #10479 - prevent validation error on host creation when domain … #2374

Closed
wants to merge 1 commit into from

Conversation

tbrisker
Copy link
Member

…contains capital letters

@domcleal
Copy link
Contributor

This needs unit tests.

@domcleal
Copy link
Contributor

There are a lot of bugs filed against our handling of mixed case hostnames, particularly that we downcase them unnecessarily, which causes more issues. I don't believe increasing the amount of downcasing is a very good idea here, but rather we should perhaps fix the underlying bug which is probably that we're not treating the domain name as case insensitive?

@domcleal
Copy link
Contributor

I'm not sure I understand why this level of support was chosen in the latest update, could you comment please?

The expectation from the test, and when creating hosts is that the name is downcased.. I guess that meets the very basic requirement that there's no validation error, but if you've specified an upper case domain, then should it be stored and used that way? It seems incomplete to allow someone to enter an upper case domain, then ignore it.

The alternative is to block entering upper case domains, but as I mentioned earlier, I don't think decreasing support for mixed or upper case domains is the right direction.

http://projects.theforeman.org/issues/8859 and http://projects.theforeman.org/issues/8754 are relevant.

@tbrisker
Copy link
Member Author

tbrisker commented Jun 3, 2015

@domcleal The idea behind the change is to make domains case-insensitive while keeping them case-aware, so that applications which are case-sensitive will be able to get the correct domain name (as in the related issues you mentioned). Note that the domain name maintains it's case, only the host name ignores it and downcases everything.
I am not sure why we force downcase host names at all. I would suggest we also do this for host names, solving those issues, and downcase only if a certain use-case requires the name in lower case (or better, make any comparisons case-insensitive if possible). However that is outside the scope of this PR.

@ohadlevy
Copy link
Member

ohadlevy commented Jun 9, 2015

@tbrisker @domcleal ping?

@domcleal
Copy link
Contributor

so that applications which are case-sensitive will be able to get the correct domain name

This is the right direction, but I don't see much use for it, since 98% of domain name consumption is via the host name.

Note that the domain name maintains it's case, only the host name ignores it and downcases everything.
I am not sure why we force downcase host names at all. I would suggest we also do this for host names, solving those issues, and downcase only if a certain use-case requires the name in lower case (or better, make any comparisons case-insensitive if possible). However that is outside the scope of this PR.

Right, this is what I'm getting at. Perhaps you could consider fixing those issues as further commits to this PR?

I don't get the impression that they will be fixed otherwise, which leaves us with a commit that doesn't really fix the issues that matter... just closes a trivial ticket.

@@ -26,7 +26,7 @@ class Domain < ActiveRecord::Base

accepts_nested_attributes_for :domain_parameters, :allow_destroy => true
include ParameterValidators
validates :name, :presence => true, :uniqueness => true
validates :name, :presence => true, :uniqueness => { :case_sensitive => false }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be enforced with a DB index of some sort too?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a case-insensitive unique index for this.
I will also attach to this PR another commit making host names case insensitive, feel free to return this PR to waiting on contributor.

test "should have a unique case-insensitive name" do
other_domain = Domain.new(:name => @domain.name.upcase)
refute other_domain.save
assert_raises ActiveRecord::RecordNotUnique, ActiveRecord::StatementInvalid do
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the index is only enforcing this on MySQL, Postgres and sqlite won't raise this exception.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The weirdest part is that if I remove the migration and add the index manually running CREATE UNIQUE INDEX domain_name_index ON domains (name collate nocase), this test pass. The migration is certainly running for pg and sqlite as you can see on Jenkins console.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The failure is actually because rake test runs rake db:test:prepare which loads the test db schema from schema.rb. However, the SQL commands I created for sqlite and pgsql aren't preserved in schema.rb as they aren't adapter agnostic.
If you run only this test after running migrations on the test db it passes.
I'm actually a bit stumped as to what would be the best approach here:

  • remove this test knowing that it works and the problem is in the way rake loads the test DB schema.
  • remove the case-insensitive enforcement from the DB altogether and rely on validations only
  • create a duplicate column that saves the lowercase (similar to what we have for user names), causing this to work but introducing data duplication and increasing complexity for something the DB should do on its own.
  • create something like foreigner that allows case-insensitive indices in schema.rb and migrations (most likely the most complex yet most reusable solution)

I'd be happy to get your input on what would be the best approach, as I will need to do the same for the next commit addressing the host names as well.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dLobatog ping, trying to revive this old PR. Could I get you input about the previous comment?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing the case-insensitive enforcement from the database isn't the way to go as you can encounter this situation when 2 people submit a domain to be created or updated.

1. USER1 - Query the database to see if this domain already exists.
2. USER2 - Query the database to see if this domain already exists.
3. USER1 - OK, doesn't exist, let's insert the record.
4. USER2 - OK, doesn't exist, let's insert the record.

Removing the test isn't good either IMO. We want to verify this behavior. I'm not sure right now how to move forward, I'm checking why exactly this happens, even when not loading the test via rake (ruby -I'test' test/unit/domain_test.rb)

@dLobatog
Copy link
Member

@tbrisker 👍 with me, except for the failure on pg and sqlite, if you can fix that that'd be great. Seems like the migration is not running properly or something. Thanks!

when "sqlite3"
execute 'CREATE UNIQUE INDEX domain_name_index ON domains (name collate nocase)'
else
add_index :domains, :name, :name => 'domain_name_index', :unique => true
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this relies on MySQL unique indexes being case sensitive by default, please leave a comment

@dLobatog
Copy link
Member

@tbrisker This was nearly ready, mind to rebase & update the branch? Thanks!

@tbrisker
Copy link
Member Author

Closing this for now. may reopen in the future.

@tbrisker tbrisker closed this Sep 25, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants