diff --git a/awx/ui/client/src/shared/smart-search/smart-search.controller.js b/awx/ui/client/src/shared/smart-search/smart-search.controller.js index c3898dac41..6f5488ad1d 100644 --- a/awx/ui/client/src/shared/smart-search/smart-search.controller.js +++ b/awx/ui/client/src/shared/smart-search/smart-search.controller.js @@ -164,7 +164,7 @@ export default ['$stateParams', '$scope', '$state', 'GetBasePath', 'QuerySet', ' let splitTerms; if ($scope.singleSearchParam === 'host_filter') { - splitTerms = SmartSearchService.splitHostIntoTerms(terms); + splitTerms = SmartSearchService.splitFilterIntoTerms(terms); } else { splitTerms = SmartSearchService.splitSearchIntoTerms(terms); } diff --git a/awx/ui/client/src/shared/smart-search/smart-search.service.js b/awx/ui/client/src/shared/smart-search/smart-search.service.js index 1fea6ab4c6..8e7b57271d 100644 --- a/awx/ui/client/src/shared/smart-search/smart-search.service.js +++ b/awx/ui/client/src/shared/smart-search/smart-search.service.js @@ -6,20 +6,26 @@ export default [function() { * work is done to encode quotes in quoted values and the spaces within those quoted * values before calling to `splitSearchIntoTerms`. */ - splitHostIntoTerms (searchString) { + splitFilterIntoTerms (searchString) { + if (!searchString) { + return null; + } + let groups = []; let quoted; searchString.split(' ').forEach(substring => { - if (substring.includes(':"')) { - quoted = substring; + if (/:"/g.test(substring)) { + if (/"$/.test(substring)) { + groups.push(this.encode(substring)); + } else { + quoted = substring; + } } else if (quoted) { quoted += ` ${substring}`; - if (substring.includes('"')) { - quoted = quoted.replace(/"/g, encodeURIComponent('"')); - quoted = quoted.replace(/ /g, encodeURIComponent(' ')); - groups.push(quoted); + if (/"/g.test(substring)) { + groups.push(this.encode(quoted)); quoted = undefined; } } else { @@ -29,6 +35,11 @@ export default [function() { return this.splitSearchIntoTerms(groups.join(' ')); }, + encode (string) { + string = string.replace(/'/g, '%27'); + + return string.replace(/("| )/g, match => encodeURIComponent(match)); + }, splitSearchIntoTerms(searchString) { return searchString.match(/(?:[^\s"']+|"[^"]*"|'[^']*')+/g); }, diff --git a/awx/ui/tests/spec/smart-search/smart-search.service-test.js b/awx/ui/tests/spec/smart-search/smart-search.service-test.js index 13af06e51c..cd7aef4848 100644 --- a/awx/ui/tests/spec/smart-search/smart-search.service-test.js +++ b/awx/ui/tests/spec/smart-search/smart-search.service-test.js @@ -42,4 +42,22 @@ describe('Service: SmartSearch', () => { }); }); + describe('fn splitFilterIntoTerms', () => { + it('should convert the filter term to a key and value with encode quotes and spaces', () => { + expect(SmartSearchService.splitFilterIntoTerms()).toEqual(null); + expect(SmartSearchService.splitFilterIntoTerms('foo')).toEqual(["foo"]); + expect(SmartSearchService.splitFilterIntoTerms('foo bar')).toEqual(["foo", "bar"]); + expect(SmartSearchService.splitFilterIntoTerms('name:foo bar')).toEqual(["name:foo", "bar"]); + expect(SmartSearchService.splitFilterIntoTerms('name:foo description:bar')).toEqual(["name:foo", "description:bar"]); + expect(SmartSearchService.splitFilterIntoTerms('name:"foo bar"')).toEqual(["name:%22foo%20bar%22"]); + expect(SmartSearchService.splitFilterIntoTerms('name:"foo bar" description:"bar foo"')).toEqual(["name:%22foo%20bar%22", "description:%22bar%20foo%22"]); + expect(SmartSearchService.splitFilterIntoTerms('name:"foo bar" a b c')).toEqual(["name:%22foo%20bar%22", 'a', 'b', 'c']); + expect(SmartSearchService.splitFilterIntoTerms('name:"1"')).toEqual(["name:%221%22"]); + expect(SmartSearchService.splitFilterIntoTerms('name:1')).toEqual(["name:1"]); + expect(SmartSearchService.splitFilterIntoTerms('name:"foo ba\'r" a b c')).toEqual(["name:%22foo%20ba%27r%22", 'a', 'b', 'c']); + expect(SmartSearchService.splitFilterIntoTerms('name:"foobar" other:"barbaz"')).toEqual(["name:%22foobar%22", "other:%22barbaz%22"]); + expect(SmartSearchService.splitFilterIntoTerms('name:"foobar" other:"bar baz"')).toEqual(["name:%22foobar%22", "other:%22bar%20baz%22"]); + }); + }); + });