- You may not have access to all resources used by this workflow. Resources that you don\'t have access to will not be copied and may result in an incomplete workflow.
+ You do not have access to all resources used by this workflow. Resources that you don\'t have access to will not be copied and will result in an incomplete workflow.
`;
// Go and grab all of the warning strings
- _.forOwn(result.data.warnings, function(warning) {
- if(warning) {
- _.forOwn(warning, function(warningString) {
- bodyHtml += '
' + warningString + '
';
- });
+ _.forOwn(result.data.templates_unable_to_copy, function(ujt) {
+ if(ujt) {
+ // _.forOwn(ujts, function(warningString) {
+ bodyHtml += '
' + ujt + '
';
+ // });
}
} );
From c452f5fd804db4b2105a33f3234d6c54ec7fe9a9 Mon Sep 17 00:00:00 2001
From: Michael Abashian
Date: Wed, 11 Jan 2017 13:21:19 -0500
Subject: [PATCH 41/55] Added more testing
---
.../smart-search/queryset.service-test.js | 43 +++++++++++--------
.../smart-search/smart-search.service-test.js | 1 +
2 files changed, 25 insertions(+), 19 deletions(-)
diff --git a/awx/ui/tests/spec/smart-search/queryset.service-test.js b/awx/ui/tests/spec/smart-search/queryset.service-test.js
index b932925171..3d49440920 100644
--- a/awx/ui/tests/spec/smart-search/queryset.service-test.js
+++ b/awx/ui/tests/spec/smart-search/queryset.service-test.js
@@ -3,7 +3,8 @@
describe('Service: QuerySet', () => {
let $httpBackend,
QuerySet,
- Authorization;
+ Authorization,
+ SmartSearchService;
beforeEach(angular.mock.module('Tower', ($provide) =>{
// @todo: improve app source / write testing utilities for interim
@@ -17,9 +18,10 @@ describe('Service: QuerySet', () => {
}));
beforeEach(angular.mock.module('RestServices'));
- beforeEach(angular.mock.inject((_$httpBackend_, _QuerySet_) => {
+ beforeEach(angular.mock.inject((_$httpBackend_, _QuerySet_, _SmartSearchService_) => {
$httpBackend = _$httpBackend_;
QuerySet = _QuerySet_;
+ SmartSearchService = _SmartSearchService_;
// @todo: improve app source
// config.js / local_settings emit $http requests in the app's run block
@@ -33,24 +35,27 @@ describe('Service: QuerySet', () => {
.respond(200, '');
}));
- describe('fn encodeQuery', () => {
- xit('null/undefined params should return an empty string', () => {
- expect(QuerySet.encodeQuery(null)).toEqual('');
- expect(QuerySet.encodeQuery(undefined)).toEqual('');
+ describe('fn encodeParam', () => {
+ it('should encode parameters properly', () =>{
+ expect(QuerySet.encodeParam({term: "name:foo", searchTerm: true})).toEqual({"name__icontains_DEFAULT" : "foo"});
+ expect(QuerySet.encodeParam({term: "-name:foo", searchTerm: true})).toEqual({"not__name__icontains_DEFAULT" : "foo"});
+ expect(QuerySet.encodeParam({term: "name:'foo bar'", searchTerm: true})).toEqual({"name__icontains_DEFAULT" : "'foo bar'"});
+ expect(QuerySet.encodeParam({term: "-name:'foo bar'", searchTerm: true})).toEqual({"not__name__icontains_DEFAULT" : "'foo bar'"});
+ expect(QuerySet.encodeParam({term: "organization:foo", relatedSearchTerm: true})).toEqual({"organization__search_DEFAULT" : "foo"});
+ expect(QuerySet.encodeParam({term: "-organization:foo", relatedSearchTerm: true})).toEqual({"not__organization__search_DEFAULT" : "foo"});
+ expect(QuerySet.encodeParam({term: "organization.name:foo", relatedSearchTerm: true})).toEqual({"organization__name" : "foo"});
+ expect(QuerySet.encodeParam({term: "-organization.name:foo", relatedSearchTerm: true})).toEqual({"not__organization__name" : "foo"});
+ expect(QuerySet.encodeParam({term: "id:11", searchTerm: true})).toEqual({"id__icontains_DEFAULT" : "11"});
+ expect(QuerySet.encodeParam({term: "-id:11", searchTerm: true})).toEqual({"not__id__icontains_DEFAULT" : "11"});
+ expect(QuerySet.encodeParam({term: "id:>11", searchTerm: true})).toEqual({"id__gt" : "11"});
+ expect(QuerySet.encodeParam({term: "-id:>11", searchTerm: true})).toEqual({"not__id__gt" : "11"});
+ expect(QuerySet.encodeParam({term: "id:>=11", searchTerm: true})).toEqual({"id__gte" : "11"});
+ expect(QuerySet.encodeParam({term: "-id:>=11", searchTerm: true})).toEqual({"not__id__gte" : "11"});
+ expect(QuerySet.encodeParam({term: "id:<11", searchTerm: true})).toEqual({"id__lt" : "11"});
+ expect(QuerySet.encodeParam({term: "-id:<11", searchTerm: true})).toEqual({"not__id__lt" : "11"});
+ expect(QuerySet.encodeParam({term: "id:<=11", searchTerm: true})).toEqual({"id__lte" : "11"});
+ expect(QuerySet.encodeParam({term: "-id:<=11", searchTerm: true})).toEqual({"not__id__lte" : "11"});
});
- xit('should encode params to a string', () => {
- let params = {
- or__created_by: 'Jenkins',
- or__modified_by: 'Jenkins',
- and__not__status: 'success',
- },
- result = '?or__created_by=Jenkins&or__modified_by=Jenkins&and__not__status=success';
- expect(QuerySet.encodeQuery(params)).toEqual(result);
- });
- });
-
- xdescribe('fn decodeQuery', () => {
-
});
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 679a5656b4..d5c35a08c2 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
@@ -24,6 +24,7 @@ describe('Service: SmartSearch', () => {
expect(SmartSearchService.splitSearchIntoTerms('name:\'foo bar\' description:\'bar foo\'')).toEqual(["name:\'foo bar\'", "description:\'bar foo\'"]);
expect(SmartSearchService.splitSearchIntoTerms('name:\'foo bar\' description:\'bar foo\'')).toEqual(["name:\'foo bar\'", "description:\'bar foo\'"]);
expect(SmartSearchService.splitSearchIntoTerms('name:\"foo bar\" description:\'bar foo\'')).toEqual(["name:\"foo bar\"", "description:\'bar foo\'"]);
+ expect(SmartSearchService.splitSearchIntoTerms('name:\"foo bar\" foo')).toEqual(["name:\"foo bar\"", "foo"]);
});
});
From eaf883f34992d20c10ab6fd13ed7ada6b51635b0 Mon Sep 17 00:00:00 2001
From: Chris Meyers
Date: Wed, 11 Jan 2017 14:02:17 -0500
Subject: [PATCH 42/55] dem controllers just needed to know who headers is
related to #4663
---
awx/ui/client/src/notifications/notificationTemplates.form.js | 1 +
1 file changed, 1 insertion(+)
diff --git a/awx/ui/client/src/notifications/notificationTemplates.form.js b/awx/ui/client/src/notifications/notificationTemplates.form.js
index 48fcbad9d7..51fd4125d0 100644
--- a/awx/ui/client/src/notifications/notificationTemplates.form.js
+++ b/awx/ui/client/src/notifications/notificationTemplates.form.js
@@ -323,6 +323,7 @@ export default ['i18n', function(i18n) {
headers: {
label: i18n._('HTTP Headers'),
type: 'textarea',
+ name: 'headers',
rows: 5,
'class': 'Form-formGroup--fullWidth',
awRequiredWhen: {
From cd61f58b11987e7f44d2ddeacc45ad57816bea4a Mon Sep 17 00:00:00 2001
From: jaredevantabor
Date: Tue, 10 Jan 2017 21:12:29 -0800
Subject: [PATCH 43/55] hiding default search param as a search tag
in scenario where the user types a search that conflicts w/ the default search params.
Ex: searching for kind:gce when kind:ssh is a default search param shouldn't create a
search tag for kind:ssh, as someone shouldn't be able to remove that tag...it's a default!
---
.../smart-search/smart-search.controller.js | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)
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 95f3be3adb..fc9cca9e77 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
@@ -23,11 +23,24 @@ export default ['$stateParams', '$scope', '$state', 'QuerySet', 'GetBasePath', '
// Removes state definition defaults and pagination terms
function stripDefaultParams(params) {
- let stripped =_.pick(params, (value, key) => {
+ let strippedCopy, stripped =_.pick(params, (value, key) => {
// setting the default value of a term to null in a state definition is a very explicit way to ensure it will NEVER generate a search tag, even with a non-default value
return defaults[key] !== value && key !== 'order_by' && key !== 'page' && key !== 'page_size' && defaults[key] !== null;
});
- return _(stripped).map(qs.decodeParam).flatten().value();
+ strippedCopy = _.cloneDeep(stripped);
+ if(_.keys(_.pick(defaults, _.keys(strippedCopy))).length > 0){
+ for (var key in strippedCopy) {
+ if (strippedCopy.hasOwnProperty(key)) {
+ let value = strippedCopy[key];
+ if(_.isArray(value)){
+ let index = _.indexOf(value, defaults[key]);
+ value = value.splice(index, 1)[0];
+ }
+ }
+ }
+ stripped = strippedCopy;
+ }
+ return _(strippedCopy).map(qs.decodeParam).flatten().value();
}
// searchable relationships
From a693aad95da401712efc519fd3b92979aaa46a21 Mon Sep 17 00:00:00 2001
From: AlanCoding
Date: Wed, 11 Jan 2017 14:22:28 -0500
Subject: [PATCH 44/55] a workable version of the new copy GET schema
implemented
---
awx/api/views.py | 12 +++---
.../tests/functional/test_rbac_workflow.py | 6 +--
.../list/templates-list.controller.js | 38 +++++++++++++++----
3 files changed, 38 insertions(+), 18 deletions(-)
diff --git a/awx/api/views.py b/awx/api/views.py
index 7e8ea65540..7c22bdf57f 100644
--- a/awx/api/views.py
+++ b/awx/api/views.py
@@ -2907,12 +2907,12 @@ class WorkflowJobTemplateCopy(WorkflowsEnforcementMixin, GenericAPIView):
def get(self, request, *args, **kwargs):
obj = self.get_object()
can_copy, messages = request.user.can_access_with_errors(self.model, 'copy', obj)
- data = {
- 'can_copy': can_copy, 'can_copy_without_user_input': can_copy,
- 'templates_unable_to_copy': [] if can_copy else ['all'],
- 'credentials_unable_to_copy': [] if can_copy else ['all'],
- 'inventories_unable_to_copy': [] if can_copy else ['all']
- }
+ data = OrderedDict([
+ ('can_copy', can_copy), ('can_copy_without_user_input', can_copy),
+ ('templates_unable_to_copy', [] if can_copy else ['all']),
+ ('credentials_unable_to_copy', [] if can_copy else ['all']),
+ ('inventories_unable_to_copy', [] if can_copy else ['all'])
+ ])
if messages and can_copy:
data['can_copy_without_user_input'] = False
data.update(messages)
diff --git a/awx/main/tests/functional/test_rbac_workflow.py b/awx/main/tests/functional/test_rbac_workflow.py
index a0f0348e38..f2ce04404f 100644
--- a/awx/main/tests/functional/test_rbac_workflow.py
+++ b/awx/main/tests/functional/test_rbac_workflow.py
@@ -120,13 +120,11 @@ class TestWorkflowJobAccess:
access = WorkflowJobTemplateAccess(rando, save_messages=True)
assert not access.can_copy(wfjt)
warnings = access.messages
- assert 1 in warnings
- assert 'inventory' in warnings[1]
+ assert 'inventories_unable_to_copy' in warnings
def test_workflow_copy_warnings_jt(self, wfjt, rando, job_template):
wfjt.workflow_job_template_nodes.create(unified_job_template=job_template)
access = WorkflowJobTemplateAccess(rando, save_messages=True)
assert not access.can_copy(wfjt)
warnings = access.messages
- assert 1 in warnings
- assert 'unified_job_template' in warnings[1]
+ assert 'templates_unable_to_copy' in warnings
diff --git a/awx/ui/client/src/templates/list/templates-list.controller.js b/awx/ui/client/src/templates/list/templates-list.controller.js
index a71f9573c3..d0b910e6b9 100644
--- a/awx/ui/client/src/templates/list/templates-list.controller.js
+++ b/awx/ui/client/src/templates/list/templates-list.controller.js
@@ -239,14 +239,36 @@ export default ['$scope', '$rootScope', '$location', '$stateParams', 'Rest',
`;
- // Go and grab all of the warning strings
- _.forOwn(result.data.templates_unable_to_copy, function(ujt) {
- if(ujt) {
- // _.forOwn(ujts, function(warningString) {
- bodyHtml += '
' + ujt + '
';
- // });
- }
- } );
+ // List the unified job templates user can not access
+ if (result.data.templates_unable_to_copy.length > 0) {
+ bodyHtml += '
Unified Job Templates that can not be copied
';
+ _.forOwn(result.data.templates_unable_to_copy, function(ujt) {
+ if(ujt) {
+ bodyHtml += '- ' + ujt + '
';
+ }
+ });
+ bodyHtml += '
';
+ }
+ // List the prompted inventories user can not access
+ if (result.data.inventories_unable_to_copy.length > 0) {
+ bodyHtml += '
Node prompted inventories that can not be copied
';
+ _.forOwn(result.data.inventories_unable_to_copy, function(inv) {
+ if(inv) {
+ bodyHtml += '- ' + inv + '
';
+ }
+ });
+ bodyHtml += '
';
+ }
+ // List the prompted credentials user can not access
+ if (result.data.credentials_unable_to_copy.length > 0) {
+ bodyHtml += '
Node prompted credentials that can not be copied
';
+ _.forOwn(result.data.credentials_unable_to_copy, function(cred) {
+ if(cred) {
+ bodyHtml += '- ' + cred + '
';
+ }
+ });
+ bodyHtml += '
';
+ }
bodyHtml += '
';
From 33aabfeb4c7416048e52be9aa0688c966272313d Mon Sep 17 00:00:00 2001
From: Michael Abashian