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 #36017 - Remove spacing from array type settings #9614

Merged
merged 1 commit into from Apr 20, 2023

Conversation

girijaasoni
Copy link
Contributor

…ts to make it into a valid format

@theforeman-bot
Copy link
Member

Issues: #36017

@theforeman-bot
Copy link
Member

Can one of the admins verify this patch?

2 similar comments
@theforeman-bot
Copy link
Member

Can one of the admins verify this patch?

@theforeman-bot
Copy link
Member

Can one of the admins verify this patch?

@stejskalleos
Copy link
Contributor

ok to test

@girijaasoni girijaasoni changed the title Fixes #36017 -Used .strip to solve space and comma issue between inpu… Fixes #36017 - .strip for input validation Feb 8, 2023
@girijaasoni girijaasoni changed the title Fixes #36017 - .strip for input validation Fixes #36017 - Input validation to accept spaces Feb 8, 2023
@Ron-Lavi Ron-Lavi self-assigned this Feb 8, 2023
Copy link
Member

@Ron-Lavi Ron-Lavi left a comment

Choose a reason for hiding this comment

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

Thanks @girijaasoni !
the value which is stored in the DB still has spaces,
can we also trim the spaces from it?

Screenshot from 2023-02-08 14-59-18

Copy link
Member

@Ron-Lavi Ron-Lavi left a comment

Choose a reason for hiding this comment

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

We should consider trimming the values from the frontend, e.g:

Though to better protect the DB also from the API point, maybe we can use this library: https://github.com/holli/auto_strip_attributes

this can be a solution for more scenarios across Foreman and plugins...
interested in what @nofaralfasi and @theforeman/packaging have to say about it.

Copy link
Member

@ekohl ekohl left a comment

Choose a reason for hiding this comment

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

I'm with @Ron-Lavi that I'd avoid changing the validators, but rather make sure the input is clean. As @Ron-Lavi pointed out, you will end up with more complex values in the DB which may confuse other code later on and create subtle bugs.

@@ -1,5 +1,5 @@
class ArrayTypeValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
record.errors.add attribute, _("must be comma separated") unless Array(value).map { |item| item.to_s.match /\A\S+\z/ }.all?
record.errors.add attribute, _("must be comma separated") unless Array(value).map { |item| item.to_s.strip.match /\A\S+\z/ }.all?
Copy link
Member

Choose a reason for hiding this comment

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

Unrelated to this PR, but I think .all? accepts a block and this could be optimized:

Suggested change
record.errors.add attribute, _("must be comma separated") unless Array(value).map { |item| item.to_s.strip.match /\A\S+\z/ }.all?
record.errors.add attribute, _("must be comma separated") unless Array(value).all? { |item| item.to_s.strip.match?(/\A\S+\z/) }

Note I didn't test this and it's probably better to do in a separate PR

Copy link
Contributor Author

Choose a reason for hiding this comment

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

To be explicit: the changes to the validators should be reverted. They should not accept any whitespace.

@ekohl Are you suggesting that we shall apply the change somewhere else or we can modify the Regex for the same validation?

Copy link
Member

Choose a reason for hiding this comment

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

I'd apply the change elsewhere. Normally the flow is:

  • User input
  • Apply normalization
  • Apply validators
  • Process data

Processing data can mean storing it in the DB, but you want it to be as clean as possible. The main reason is that if you can assume that data in the database doesn't have whitespace around the value, you can keep the code that uses data from the database simpler. Or put in another way: if you must remember to always call .strip on a value, you can easily introduce bugs. That's more important than the potential performance difference, but that's another factor.

An example:

if model.value == 'value'
  # Do X
else
  # Do Y
end

This will work most of the time, but if the user (accidentally) has spaces in the value it can introduce a bug.

Looking back at the flow, this means we want to clean up the data before processing it. A validator is then only supposed to validate. It never changes data. This means normalization can happen in the UI, before it's submitted, or in the controller before it's passed to the validators. But the validator must remain strict.

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks a lot for the clarification Ewoud!!

Copy link
Member

@ekohl ekohl left a comment

Choose a reason for hiding this comment

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

To be explicit: the changes to the validators should be reverted. They should not accept any whitespace.

@nofaralfasi
Copy link
Contributor

nofaralfasi commented Mar 1, 2023

@girijaasoni Some tests are failing.
And can you also update the commit message to reflect your new changes?

Ron-Lavi
Ron-Lavi previously approved these changes Apr 2, 2023
Copy link
Member

@Ron-Lavi Ron-Lavi left a comment

Choose a reason for hiding this comment

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

Thanks @girijaasoni, I tested and it works as expected now 👍🏼

@@ -44,13 +44,13 @@ def setup
end

test 'if audience is not valid' do
Setting['oidc_audience'] = "no-client"
Setting['oidc_audience'] = ["no-client"]
Copy link
Member

Choose a reason for hiding this comment

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

Nice catch, it was indeed moved to setting_type of array in

@girijaasoni
Copy link
Contributor Author

@ekohl , could you please review the updated changes?

ekohl
ekohl previously approved these changes Apr 3, 2023
Copy link
Member

@ekohl ekohl left a comment

Choose a reason for hiding this comment

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

Changes look good to me. It would be great to have a test, but I don't know where would be a great place.

assert Setting.create(name: 'trusted_hosts', value: [])
setting = Setting.find_by_name("trusted_hosts")
setting.value = ["localhost ", " remotehost"]
assert setting.save
Copy link
Contributor

Choose a reason for hiding this comment

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

setting = Setting.create(name: 'trusted_hosts', value: ["localhost ", "  remotehost"])
assert_equal ["localhost", "remotehost"], setting.value

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thank you @stejskalleos

@@ -174,6 +174,13 @@ def test_settings_should_save_strings
assert_equal "must be comma separated", setting.errors[:value].first
end

test "trusted_hosts should accept values with spaces" do
Copy link
Contributor

Choose a reason for hiding this comment

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

trusted_hosts should trim values with spaces

Copy link
Member

Choose a reason for hiding this comment

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

https://www.betterspecs.org/#should says you should make it:

Suggested change
test "trusted_hosts should accept values with spaces" do
test "trusted_hosts accepts values with spaces" do

Granted, that's for RSpec, but I like the convention.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks @ekohl , updated it

stejskalleos
stejskalleos previously approved these changes Apr 19, 2023
Copy link
Contributor

@stejskalleos stejskalleos left a comment

Choose a reason for hiding this comment

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

🍏 LGTM

Failed tests are not related, but let's wait with the merge until they are fixed.

@girijaasoni
Copy link
Contributor Author

girijaasoni commented Apr 19, 2023

green_apple LGTM

Failed tests are not related, but let's wait with the merge until they are fixed.

The tests pass now!

Copy link
Contributor

@stejskalleos stejskalleos left a comment

Choose a reason for hiding this comment

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

🍏 LGTM

Works as expected.
Thanks @girijaasoni!

@stejskalleos stejskalleos merged commit 6368162 into theforeman:develop Apr 20, 2023
12 checks passed
@MariaAga MariaAga added the Needs cherrypick This should be cherrypicked to the stable branches or branches label Apr 25, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs cherrypick This should be cherrypicked to the stable branches or branches Templates UI
Projects
None yet
8 participants