mirror of
https://github.com/ansible/awx.git
synced 2026-05-08 01:47:35 -02:30
Merge pull request #4317 from leigh-johnson/3487
Assign batch resource permissions to users/teams
This commit is contained in:
12
awx/ui/client/src/access/add-rbac-resource/main.js
Normal file
12
awx/ui/client/src/access/add-rbac-resource/main.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
/*************************************************
|
||||||
|
* Copyright (c) 2015 Ansible, Inc.
|
||||||
|
*
|
||||||
|
* All Rights Reserved
|
||||||
|
*************************************************/
|
||||||
|
|
||||||
|
import addRbacResourceDirective from './rbac-resource.directive';
|
||||||
|
import rbacMultiselect from '../rbac-multiselect/main';
|
||||||
|
|
||||||
|
export default
|
||||||
|
angular.module('AddRbacResourceModule', [rbacMultiselect.name])
|
||||||
|
.directive('addRbacResource', addRbacResourceDirective);
|
||||||
@@ -18,16 +18,7 @@ export default ['$rootScope', '$scope', 'GetBasePath', 'Rest', '$q', 'Wait', 'Pr
|
|||||||
// the object permissions are being added to
|
// the object permissions are being added to
|
||||||
scope.object = scope.resourceData.data;
|
scope.object = scope.resourceData.data;
|
||||||
// array for all possible roles for the object
|
// array for all possible roles for the object
|
||||||
scope.roles = Object
|
scope.roles = scope.object.summary_fields.object_roles;
|
||||||
.keys(scope.object.summary_fields.object_roles)
|
|
||||||
.map(function(key) {
|
|
||||||
return {
|
|
||||||
value: scope.object.summary_fields
|
|
||||||
.object_roles[key].id,
|
|
||||||
label: scope.object.summary_fields
|
|
||||||
.object_roles[key].name
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
// TODO: get working with api
|
// TODO: get working with api
|
||||||
// array w roles and descriptions for key
|
// array w roles and descriptions for key
|
||||||
@@ -44,6 +35,11 @@ export default ['$rootScope', '$scope', 'GetBasePath', 'Rest', '$q', 'Wait', 'Pr
|
|||||||
|
|
||||||
scope.showKeyPane = false;
|
scope.showKeyPane = false;
|
||||||
|
|
||||||
|
scope.removeObject = function(obj){
|
||||||
|
_.remove(scope.allSelected, {id: obj.id});
|
||||||
|
obj.isSelected = false;
|
||||||
|
};
|
||||||
|
|
||||||
scope.toggleKeyPane = function() {
|
scope.toggleKeyPane = function() {
|
||||||
scope.showKeyPane = !scope.showKeyPane;
|
scope.showKeyPane = !scope.showKeyPane;
|
||||||
};
|
};
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* All Rights Reserved
|
* All Rights Reserved
|
||||||
*************************************************/
|
*************************************************/
|
||||||
import addPermissionsController from './addPermissions.controller';
|
import controller from './rbac-resource.controller';
|
||||||
|
|
||||||
/* jshint unused: vars */
|
/* jshint unused: vars */
|
||||||
export default ['templateUrl', '$state',
|
export default ['templateUrl', '$state',
|
||||||
@@ -16,8 +16,8 @@ export default ['templateUrl', '$state',
|
|||||||
teamsDataset: '=',
|
teamsDataset: '=',
|
||||||
resourceData: '=',
|
resourceData: '=',
|
||||||
},
|
},
|
||||||
controller: addPermissionsController,
|
controller: controller,
|
||||||
templateUrl: templateUrl('access/addPermissions/addPermissions'),
|
templateUrl: templateUrl('access/add-rbac-resource/rbac-resource'),
|
||||||
link: function(scope, element, attrs) {
|
link: function(scope, element, attrs) {
|
||||||
scope.toggleFormTabs('users');
|
scope.toggleFormTabs('users');
|
||||||
$('#add-permissions-modal').modal('show');
|
$('#add-permissions-modal').modal('show');
|
||||||
@@ -46,10 +46,10 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="AddPermissions-users" class="AddPermissions-list" ng-show="usersSelected">
|
<div id="AddPermissions-users" class="AddPermissions-list" ng-show="usersSelected">
|
||||||
<add-permissions-list view="Users" all-selected="allSelected" dataset="usersDataset"></add-permissions-list>
|
<rbac-multiselect-list view="Users" all-selected="allSelected" dataset="usersDataset"></rbac-multiselect-list>
|
||||||
</div>
|
</div>
|
||||||
<div id="AddPermissions-teams" class="AddPermissions-list" ng-show="teamsSelected">
|
<div id="AddPermissions-teams" class="AddPermissions-list" ng-show="teamsSelected">
|
||||||
<add-permissions-list view="Teams" all-selected="allSelected" dataset="teamsDataset"></add-permissions-list>
|
<rbac-multiselect-list view="Teams" all-selected="allSelected" dataset="teamsDataset"></rbac-multiselect-list>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="AddPermissions-separator"
|
<div class="AddPermissions-separator"
|
||||||
@@ -61,7 +61,7 @@
|
|||||||
2
|
2
|
||||||
</span>
|
</span>
|
||||||
Please assign roles to the selected users/teams
|
Please assign roles to the selected users/teams
|
||||||
<div class="AddPermissions-keyToggle"
|
<div class="AddPermissions-keyToggle btn"
|
||||||
ng-class="{'is-active': showKeyPane}"
|
ng-class="{'is-active': showKeyPane}"
|
||||||
ng-click="toggleKeyPane()">
|
ng-click="toggleKeyPane()">
|
||||||
Key
|
Key
|
||||||
@@ -91,8 +91,8 @@
|
|||||||
{{ obj.type }}
|
{{ obj.type }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<role-select class="AddPermissions-roleSelect">
|
<rbac-multiselect-role class="AddPermissions-roleSelect" roles="roles" model="obj.roles">
|
||||||
</role-select>
|
</rbac-multiselect-role>
|
||||||
<button class="AddPermissions-roleRemove"
|
<button class="AddPermissions-roleRemove"
|
||||||
ng-click="removeObject(obj)">
|
ng-click="removeObject(obj)">
|
||||||
<i class="fa fa-times"></i>
|
<i class="fa fa-times"></i>
|
||||||
13
awx/ui/client/src/access/add-rbac-user-team/main.js
Normal file
13
awx/ui/client/src/access/add-rbac-user-team/main.js
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
/*************************************************
|
||||||
|
* Copyright (c) 2016 Ansible, Inc.
|
||||||
|
*
|
||||||
|
* All Rights Reserved
|
||||||
|
*************************************************/
|
||||||
|
|
||||||
|
import addRbacUserTeamDirective from './rbac-user-team.directive';
|
||||||
|
import rbacSelectedList from './rbac-selected-list.directive';
|
||||||
|
|
||||||
|
export default
|
||||||
|
angular.module('AddRbacUserTeamModule', [])
|
||||||
|
.directive('addRbacUserTeam', addRbacUserTeamDirective)
|
||||||
|
.directive('rbacSelectedList', rbacSelectedList);
|
||||||
@@ -0,0 +1,127 @@
|
|||||||
|
/*************************************************
|
||||||
|
* Copyright (c) 2016 Ansible, Inc.
|
||||||
|
*
|
||||||
|
* All Rights Reserved
|
||||||
|
*************************************************/
|
||||||
|
|
||||||
|
/* jshint unused: vars */
|
||||||
|
export default ['$compile','templateUrl', 'i18n', 'generateList',
|
||||||
|
'ProjectList', 'TemplateList', 'InventoryList', 'CredentialList',
|
||||||
|
function($compile, templateUrl, i18n, generateList,
|
||||||
|
ProjectList, TemplateList, InventoryList, CredentialList) {
|
||||||
|
return {
|
||||||
|
restrict: 'E',
|
||||||
|
scope: {
|
||||||
|
resourceType: "=",
|
||||||
|
collection: "=",
|
||||||
|
selected: "="
|
||||||
|
},
|
||||||
|
link: function(scope, element, attrs) {
|
||||||
|
let listMap, list, list_html;
|
||||||
|
|
||||||
|
listMap = {
|
||||||
|
projects: ProjectList,
|
||||||
|
job_templates: TemplateList,
|
||||||
|
workflow_templates: TemplateList,
|
||||||
|
inventories: InventoryList,
|
||||||
|
credentials: CredentialList
|
||||||
|
};
|
||||||
|
|
||||||
|
list = _.cloneDeep(listMap[scope.resourceType]);
|
||||||
|
|
||||||
|
list.fieldActions = {
|
||||||
|
remove: {
|
||||||
|
ngClick: `removeSelection(${list.iterator}, resourceType)`,
|
||||||
|
iconClass: 'fa fa-times-circle',
|
||||||
|
awToolTip: i18n._(`Remove ${list.iterator}`),
|
||||||
|
label: i18n._('Remove'),
|
||||||
|
class: 'btn-sm'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
delete list.actions;
|
||||||
|
|
||||||
|
list.listTitleBadge = false;
|
||||||
|
|
||||||
|
// @issue - fix field.columnClass values for this view
|
||||||
|
|
||||||
|
switch(scope.resourceType){
|
||||||
|
|
||||||
|
case 'projects':
|
||||||
|
list.fields = {
|
||||||
|
name: list.fields.name,
|
||||||
|
scm_type: list.fields.scm_type
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'inventories':
|
||||||
|
list.fields = {
|
||||||
|
name: list.fields.name,
|
||||||
|
organization: list.fields.organization
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'job_templates':
|
||||||
|
list.name = 'job_templates';
|
||||||
|
list.iterator = 'job_template';
|
||||||
|
list.fields = {
|
||||||
|
name: list.fields.name,
|
||||||
|
description: list.fields.description
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'workflow_templates':
|
||||||
|
list.name = 'workflow_templates';
|
||||||
|
list.iterator = 'workflow_template';
|
||||||
|
list.basePath = 'workflow_job_templates';
|
||||||
|
list.fields = {
|
||||||
|
name: list.fields.name,
|
||||||
|
description: list.fields.description
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case 'credentials':
|
||||||
|
list.fields = {
|
||||||
|
name: list.fields.name,
|
||||||
|
description: list.fields.description
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
list.fields = _.each(list.fields, (field) => field.nosort = true);
|
||||||
|
|
||||||
|
list_html = generateList.build({
|
||||||
|
mode: 'edit',
|
||||||
|
list: list,
|
||||||
|
related: false,
|
||||||
|
title: false,
|
||||||
|
showSearch: false,
|
||||||
|
showEmptyPanel: false,
|
||||||
|
paginate: false
|
||||||
|
});
|
||||||
|
|
||||||
|
scope.list = list;
|
||||||
|
|
||||||
|
scope.$watchCollection('collection', function(selected){
|
||||||
|
scope[`${list.iterator}_dataset`] = scope.collection;
|
||||||
|
scope[list.name] = _.values(scope.collection);
|
||||||
|
});
|
||||||
|
|
||||||
|
scope.removeSelection = function(resource, type){
|
||||||
|
let multiselect_scope, deselectedIdx;
|
||||||
|
|
||||||
|
delete scope.collection[resource.id];
|
||||||
|
delete scope.selected[type][resource.id];
|
||||||
|
|
||||||
|
// a quick & dirty hack
|
||||||
|
// section 1 and section 2 elements produce sibling scopes
|
||||||
|
// This means events propogated from section 2 are not received in section 1
|
||||||
|
// The following code directly accesses the right scope by list table id
|
||||||
|
multiselect_scope = angular.element('#AddPermissions-body').find(`#${type}_table`).scope();
|
||||||
|
deselectedIdx = _.findIndex(multiselect_scope[type], {id: resource.id});
|
||||||
|
multiselect_scope[type][deselectedIdx].isSelected = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
element.append(list_html);
|
||||||
|
$compile(element.contents())(scope);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
@@ -0,0 +1,165 @@
|
|||||||
|
/*************************************************
|
||||||
|
* Copyright (c) 2015 Ansible, Inc.
|
||||||
|
*
|
||||||
|
* All Rights Reserved
|
||||||
|
*************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ngdoc function
|
||||||
|
* @name controllers.function:Access
|
||||||
|
* @description
|
||||||
|
* Controller for handling permissions adding
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default ['$rootScope', '$scope', '$state', 'i18n', 'CreateSelect2', 'GetBasePath', 'Rest', '$q', 'Wait', 'ProcessErrors',
|
||||||
|
function(rootScope, scope, $state, i18n, CreateSelect2, GetBasePath, Rest, $q, Wait, ProcessErrors) {
|
||||||
|
|
||||||
|
init();
|
||||||
|
|
||||||
|
function init(){
|
||||||
|
|
||||||
|
let resources = ['job_templates', 'workflow_templates', 'projects', 'inventories', 'credentials'];
|
||||||
|
|
||||||
|
// data model:
|
||||||
|
// selected - keyed by type of resource
|
||||||
|
// selected[type] - keyed by each resource object's id
|
||||||
|
// selected[type][id] === { roles: [ ... ], ... }
|
||||||
|
|
||||||
|
// collection of resources selected in section 1
|
||||||
|
scope.selected = {};
|
||||||
|
_.each(resources, (type) => scope.selected[type] = {});
|
||||||
|
|
||||||
|
// collection of assignable roles per type of resource
|
||||||
|
scope.keys = {};
|
||||||
|
_.each(resources, (type) => scope.keys[type] = {});
|
||||||
|
|
||||||
|
// collection of currently-selected role to assign in section 2
|
||||||
|
scope.roleSelection = {};
|
||||||
|
_.each(resources, (type) => scope.roleSelection[type] = null);
|
||||||
|
|
||||||
|
// tracks currently-selected tabs, initialized with the job templates tab open
|
||||||
|
scope.tab = {
|
||||||
|
job_templates: true,
|
||||||
|
workflow_templates: false,
|
||||||
|
projects: false,
|
||||||
|
inventories: false,
|
||||||
|
credentials: false
|
||||||
|
};
|
||||||
|
|
||||||
|
// initializes select2 per select field
|
||||||
|
// html snippet:
|
||||||
|
/*
|
||||||
|
<div ng-repeat="(type, roleSet) in keys">
|
||||||
|
<select
|
||||||
|
ng-show="tab[type]"
|
||||||
|
id="{{type}}-role-select" class="form-control"
|
||||||
|
ng-model="roleSelection[type]"
|
||||||
|
ng-options="value.name for (key , value) in roleSet">
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
*/
|
||||||
|
_.each(resources, (type) => buildSelect2(type));
|
||||||
|
|
||||||
|
function buildSelect2(type){
|
||||||
|
CreateSelect2({
|
||||||
|
element: `#${type}-role-select`,
|
||||||
|
multiple: false,
|
||||||
|
placeholder: i18n._('Select a role')
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
scope.showKeyPane = false;
|
||||||
|
|
||||||
|
// the user or team being assigned permissions
|
||||||
|
scope.owner = scope.resolve.resourceData.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// aggregate name/descriptions for each available role, based on resource type
|
||||||
|
// reasoning:
|
||||||
|
function aggregateKey(item, type){
|
||||||
|
_.merge(scope.keys[type], _.omit(item.summary_fields.object_roles, 'read_role'));
|
||||||
|
}
|
||||||
|
|
||||||
|
scope.closeModal = function() {
|
||||||
|
$state.go('^', null, {reload: true});
|
||||||
|
};
|
||||||
|
|
||||||
|
scope.currentTab = function(){
|
||||||
|
return _.findKey(scope.tab, (tab) => tab);
|
||||||
|
};
|
||||||
|
|
||||||
|
scope.toggleKeyPane = function() {
|
||||||
|
scope.showKeyPane = !scope.showKeyPane;
|
||||||
|
};
|
||||||
|
|
||||||
|
scope.showSection2Container = function(){
|
||||||
|
return _.any(scope.selected, (type) => Object.keys(type).length > 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
scope.showSection2Tab = function(tab){
|
||||||
|
return Object.keys(scope.selected[tab]).length > 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
scope.saveEnabled = function(){
|
||||||
|
let missingRole = false;
|
||||||
|
let resourceSelected = false;
|
||||||
|
_.forOwn(scope.selected, function(value, key) {
|
||||||
|
if(Object.keys(value).length > 0) {
|
||||||
|
// A resource from this tab has been selected
|
||||||
|
resourceSelected = true;
|
||||||
|
if(!scope.roleSelection[key]) {
|
||||||
|
missingRole = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return resourceSelected && !missingRole;
|
||||||
|
};
|
||||||
|
|
||||||
|
// handle form tab changes
|
||||||
|
scope.selectTab = function(selected){
|
||||||
|
_.each(scope.tab, (value, key, collection) => {
|
||||||
|
collection[key] = (selected === key);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// pop/push into unified collection of selected resourcesf
|
||||||
|
scope.$on("selectedOrDeselected", function(e, value) {
|
||||||
|
let resourceType = scope.currentTab(),
|
||||||
|
item = value.value;
|
||||||
|
|
||||||
|
if (item.isSelected) {
|
||||||
|
scope.selected[resourceType][item.id] = item;
|
||||||
|
scope.selected[resourceType][item.id].roles = [];
|
||||||
|
aggregateKey(item, resourceType);
|
||||||
|
} else {
|
||||||
|
delete scope.selected[resourceType][item.id];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// post roles to api
|
||||||
|
scope.saveForm = function() {
|
||||||
|
//Wait('start');
|
||||||
|
|
||||||
|
// builds an array of role entities to apply to current user or team
|
||||||
|
let roles = _(scope.selected).map( (resources, type) => {
|
||||||
|
return _.map(resources, (resource) => {
|
||||||
|
return resource.summary_fields.object_roles[scope.roleSelection[type]];
|
||||||
|
});
|
||||||
|
}).flattenDeep().value();
|
||||||
|
|
||||||
|
Rest.setUrl(scope.owner.related.roles);
|
||||||
|
|
||||||
|
$q.all( _.map(roles, (entity) => Rest.post({id: entity.id})) )
|
||||||
|
.then( () =>{
|
||||||
|
Wait('stop');
|
||||||
|
scope.closeModal();
|
||||||
|
}, (error) => {
|
||||||
|
scope.closeModal();
|
||||||
|
ProcessErrors(null, error.data, error.status, null, {
|
||||||
|
hdr: 'Error!',
|
||||||
|
msg: 'Failed to post role(s): POST returned status' +
|
||||||
|
error.status
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}];
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
/*************************************************
|
||||||
|
* Copyright (c) 2016 Ansible, Inc.
|
||||||
|
*
|
||||||
|
* All Rights Reserved
|
||||||
|
*************************************************/
|
||||||
|
import controller from './rbac-user-team.controller';
|
||||||
|
|
||||||
|
/* jshint unused: vars */
|
||||||
|
export default ['templateUrl',
|
||||||
|
function(templateUrl) {
|
||||||
|
return {
|
||||||
|
restrict: 'E',
|
||||||
|
scope: {
|
||||||
|
resolve: "="
|
||||||
|
},
|
||||||
|
controller: controller,
|
||||||
|
templateUrl: templateUrl('access/add-rbac-user-team/rbac-user-team'),
|
||||||
|
link: function(scope, element, attrs) {
|
||||||
|
scope.selectTab('job_templates');
|
||||||
|
$('#add-permissions-modal').modal('show');
|
||||||
|
window.scrollTo(0, 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
@@ -0,0 +1,187 @@
|
|||||||
|
<div id="add-permissions-modal" class="AddPermissions modal fade">
|
||||||
|
<div class="AddPermissions-backDrop is-loggedOut"></div>
|
||||||
|
<div class="AddPermissions-dialog">
|
||||||
|
<div class="AddPermissions-content is-loggedOut">
|
||||||
|
<!-- begin header -->
|
||||||
|
<div class="AddPermissions-header">
|
||||||
|
<div class="List-header">
|
||||||
|
<div class="List-title">
|
||||||
|
<div class="List-titleText ng-binding">
|
||||||
|
{{ owner.name }}
|
||||||
|
<div class="List-titleLockup"></div>
|
||||||
|
Add Permissions
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="Form-exitHolder">
|
||||||
|
<button class="Form-exit" ng-click="closeModal()">
|
||||||
|
<i class="fa fa-times-circle"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- end header -->
|
||||||
|
<div id="AddPermissions-body" class="AddPermissions-body">
|
||||||
|
<!-- begin section 1 -->
|
||||||
|
<div class="AddPermissions-directions">
|
||||||
|
<span class="AddPermissions-directionNumber">
|
||||||
|
1
|
||||||
|
</span>
|
||||||
|
<div>
|
||||||
|
Please select resources from the lists below.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="Form-tabHolder">
|
||||||
|
<div class="Form-tab"
|
||||||
|
ng-click="selectTab('job_templates')"
|
||||||
|
ng-class="{'is-selected': tab.job_templates }">
|
||||||
|
Job Templates
|
||||||
|
</div>
|
||||||
|
<div class="Form-tab"
|
||||||
|
ng-click="selectTab('workflow_templates')"
|
||||||
|
ng-class="{'is-selected': tab.workflow_templates}"
|
||||||
|
>
|
||||||
|
Workflow Templates
|
||||||
|
</div>
|
||||||
|
<div class="Form-tab"
|
||||||
|
ng-click="selectTab('projects')"
|
||||||
|
ng-class="{'is-selected': tab.projects }">
|
||||||
|
Projects
|
||||||
|
</div>
|
||||||
|
<div class="Form-tab"
|
||||||
|
ng-click="selectTab('inventories')"
|
||||||
|
ng-class="{'is-selected': tab.inventories}"
|
||||||
|
>
|
||||||
|
Inventories
|
||||||
|
</div>
|
||||||
|
<div class="Form-tab"
|
||||||
|
ng-click="selectTab('credentials')"
|
||||||
|
ng-class="{'is-selected': tab.credentials}"
|
||||||
|
>
|
||||||
|
Credentials
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="AddPermissions-jobTemplates" class="AddPermissions-list" ng-show="tab.job_templates">
|
||||||
|
<rbac-multiselect-list view="JobTemplates" all-selected="allSelected" dataset="resolve.jobTemplatesDataset"></rbac-multiselect-list>
|
||||||
|
</div>
|
||||||
|
<div id="AddPermissions-workflowTemplates" class="AddPermissions-list" ng-show="tab.workflow_templates">
|
||||||
|
<rbac-multiselect-list view="WorkflowTemplates" all-selected="allSelected" dataset="resolve.workflowTemplatesDataset"></rbac-multiselect-list>
|
||||||
|
</div>
|
||||||
|
<div id="AddPermissions-projects" class="AddPermissions-list" ng-show="tab.projects">
|
||||||
|
<rbac-multiselect-list view="Projects" all-selected="allSelected" dataset="resolve.projectsDataset"></rbac-multiselect-list>
|
||||||
|
</div>
|
||||||
|
<div id="AddPermissions-inventories" class="AddPermissions-list" ng-show="tab.inventories">
|
||||||
|
<rbac-multiselect-list view="Inventories" all-selected="allSelected" dataset="resolve.inventoriesDataset"></rbac-multiselect-list>
|
||||||
|
</div>
|
||||||
|
<div id="AddPermissions-credentials" class="AddPermissions-list" ng-show="tab.credentials">
|
||||||
|
<rbac-multiselect-list view="Credentials" all-selected="allSelected" dataset="resolve.credentialsDataset"></rbac-multiselect-list>
|
||||||
|
</div>
|
||||||
|
<!-- end section 1 -->
|
||||||
|
|
||||||
|
<!-- begin section 2 -->
|
||||||
|
<div ng-show="showSection2Container()">
|
||||||
|
<div class="AddPermissions-separator"></div>
|
||||||
|
<div class="AddPermissions-directions">
|
||||||
|
<span class="AddPermissions-directionNumber">
|
||||||
|
2
|
||||||
|
</span>
|
||||||
|
Please assign roles to the selected resources
|
||||||
|
<div class="AddPermissions-keyToggle btn"
|
||||||
|
ng-class="{'is-active': showKeyPane}"
|
||||||
|
ng-click="toggleKeyPane()">
|
||||||
|
Key
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="Form-tabHolder">
|
||||||
|
<div class="Form-tab"
|
||||||
|
ng-click="selectTab('job_templates')"
|
||||||
|
ng-class="{'is-selected': tab.job_templates }"
|
||||||
|
ng-show="showSection2Tab('job_templates')">
|
||||||
|
Job Templates
|
||||||
|
</div>
|
||||||
|
<div class="Form-tab"
|
||||||
|
ng-click="selectTab('workflow_templates')"
|
||||||
|
ng-class="{'is-selected': tab.workflow_templates }"
|
||||||
|
ng-show="showSection2Tab('workflow_templates')">
|
||||||
|
Workflow Templates
|
||||||
|
</div>
|
||||||
|
<div class="Form-tab"
|
||||||
|
ng-click="selectTab('projects')"
|
||||||
|
ng-class="{'is-selected': tab.projects}"
|
||||||
|
ng-show="showSection2Tab('projects')"
|
||||||
|
>
|
||||||
|
Projects
|
||||||
|
</div>
|
||||||
|
<div class="Form-tab"
|
||||||
|
ng-click="selectTab('inventories')"
|
||||||
|
ng-class="{'is-selected': tab.inventories}"
|
||||||
|
ng-show="showSection2Tab('inventories')"
|
||||||
|
>
|
||||||
|
Inventories
|
||||||
|
</div>
|
||||||
|
<div class="Form-tab"
|
||||||
|
ng-click="selectTab('credentials')"
|
||||||
|
ng-class="{'is-selected': tab.credentials}"
|
||||||
|
ng-show="showSection2Tab('credentials')"
|
||||||
|
>
|
||||||
|
Credentials
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="AddPermissions-keyPane"
|
||||||
|
ng-show="showKeyPane">
|
||||||
|
<div class="AddPermissions-keyRow"
|
||||||
|
ng-repeat="key in keys[currentTab()]">
|
||||||
|
<div class="AddPermissions-keyName">
|
||||||
|
{{ key.name }}
|
||||||
|
</div>
|
||||||
|
<div class="AddPermissions-keyDescription">
|
||||||
|
{{ key.description || "No description provided" }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- role drop-downs -->
|
||||||
|
<div ng-repeat="(type, roleSet) in keys" ng-show="tab[type]">
|
||||||
|
<select
|
||||||
|
id="{{type}}-role-select" class="form-control"
|
||||||
|
ng-model="roleSelection[type]"
|
||||||
|
ng-options="key as value.name for (key , value) in roleSet">
|
||||||
|
<option value="" selected hidden />
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- lists of selected resources -->
|
||||||
|
<!-- (type, collection) => ('resource', {id: {}, ... }) -->
|
||||||
|
<div ng-repeat="(type, collection) in selected">
|
||||||
|
<rbac-selected-list
|
||||||
|
resource-type="type"
|
||||||
|
collection="collection"
|
||||||
|
selected="selected"
|
||||||
|
ng-show="tab[type]">
|
||||||
|
</rbac-selected-list>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!-- end section 2 -->
|
||||||
|
</div>
|
||||||
|
<!-- begin footer -->
|
||||||
|
<div class="AddPermissions-footer">
|
||||||
|
<div class="buttons Form-buttons AddPermissions-buttons">
|
||||||
|
<button type="button"
|
||||||
|
class="btn btn-sm Form-cancelButton"
|
||||||
|
ng-click="closeModal()">
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
<button type="button"
|
||||||
|
class="btn btn-sm Form-saveButton"
|
||||||
|
ng-click="saveForm()"
|
||||||
|
ng-disabled="!saveEnabled()">
|
||||||
|
Save
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- end footer -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
@import "../../shared/branding/colors.default.less";
|
@import "../shared/branding/colors.default.less";
|
||||||
|
|
||||||
/** @define AddPermissions */
|
/** @define AddPermissions */
|
||||||
|
|
||||||
@@ -168,13 +168,14 @@
|
|||||||
.AddPermissions-keyToggle {
|
.AddPermissions-keyToggle {
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
padding: 3px 9px;
|
|
||||||
font-size: 12px;
|
|
||||||
background-color: @default-bg;
|
background-color: @default-bg;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
color: @default-interface-txt;
|
color: @default-interface-txt;
|
||||||
border: 1px solid @d7grey;
|
border: 1px solid @d7grey;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
width: 70px;
|
||||||
|
height: 34px;
|
||||||
|
line-height: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.AddPermissions-keyToggle:hover {
|
.AddPermissions-keyToggle:hover {
|
||||||
@@ -185,6 +186,9 @@
|
|||||||
background-color: @default-link;
|
background-color: @default-link;
|
||||||
border-color: @default-link;
|
border-color: @default-link;
|
||||||
color: @default-bg;
|
color: @default-bg;
|
||||||
|
&:hover{
|
||||||
|
background-color: @default-link-hov;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.AddPermissions-keyPane {
|
.AddPermissions-keyPane {
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
/*************************************************
|
|
||||||
* Copyright (c) 2015 Ansible, Inc.
|
|
||||||
*
|
|
||||||
* All Rights Reserved
|
|
||||||
*************************************************/
|
|
||||||
|
|
||||||
/* jshint unused: vars */
|
|
||||||
export default ['addPermissionsTeamsList', 'addPermissionsUsersList', '$compile', 'generateList', 'GetBasePath', 'SelectionInit', function(addPermissionsTeamsList,
|
|
||||||
addPermissionsUsersList, $compile, generateList,
|
|
||||||
GetBasePath, SelectionInit) {
|
|
||||||
return {
|
|
||||||
restrict: 'E',
|
|
||||||
scope: {
|
|
||||||
allSelected: '=',
|
|
||||||
view: '@',
|
|
||||||
dataset: '='
|
|
||||||
},
|
|
||||||
template: "<div class='addPermissionsList-inner'></div>",
|
|
||||||
link: function(scope, element, attrs, ctrl) {
|
|
||||||
let listMap, list, list_html;
|
|
||||||
|
|
||||||
listMap = {Teams: addPermissionsTeamsList, Users: addPermissionsUsersList};
|
|
||||||
list = listMap[scope.view];
|
|
||||||
list_html = generateList.build({
|
|
||||||
mode: 'edit',
|
|
||||||
list: list
|
|
||||||
});
|
|
||||||
|
|
||||||
scope.list = listMap[scope.view];
|
|
||||||
scope[`${list.iterator}_dataset`] = scope.dataset.data;
|
|
||||||
scope[`${list.name}`] = scope[`${list.iterator}_dataset`].results;
|
|
||||||
|
|
||||||
scope.$watch(list.name, function(){
|
|
||||||
_.forEach(scope[`${list.name}`], isSelected);
|
|
||||||
});
|
|
||||||
|
|
||||||
function isSelected(item){
|
|
||||||
if(_.find(scope.allSelected, {id: item.id})){
|
|
||||||
item.isSelected = true;
|
|
||||||
}
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
element.append(list_html);
|
|
||||||
$compile(element.contents())(scope);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}];
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
/*************************************************
|
|
||||||
* Copyright (c) 2015 Ansible, Inc.
|
|
||||||
*
|
|
||||||
* All Rights Reserved
|
|
||||||
*************************************************/
|
|
||||||
|
|
||||||
import addPermissionsDirective from './addPermissions.directive';
|
|
||||||
import roleSelect from './roleSelect.directive';
|
|
||||||
import addPermissionsList from './addPermissionsList/main';
|
|
||||||
|
|
||||||
export default
|
|
||||||
angular.module('AddPermissions', [addPermissionsList.name])
|
|
||||||
.directive('addPermissions', addPermissionsDirective)
|
|
||||||
.directive('roleSelect', roleSelect);
|
|
||||||
@@ -4,9 +4,13 @@
|
|||||||
* All Rights Reserved
|
* All Rights Reserved
|
||||||
*************************************************/
|
*************************************************/
|
||||||
|
|
||||||
import roleList from './roleList.directive';
|
import roleList from './rbac-role-column/roleList.directive';
|
||||||
import addPermissions from './addPermissions/main';
|
import addRbacResource from './add-rbac-resource/main';
|
||||||
|
import addRbacUserTeam from './add-rbac-user-team/main';
|
||||||
|
|
||||||
export default
|
export default
|
||||||
angular.module('access', [addPermissions.name])
|
angular.module('RbacModule', [
|
||||||
|
addRbacResource.name,
|
||||||
|
addRbacUserTeam.name
|
||||||
|
])
|
||||||
.directive('roleList', roleList);
|
.directive('roleList', roleList);
|
||||||
|
|||||||
@@ -4,12 +4,14 @@
|
|||||||
* All Rights Reserved
|
* All Rights Reserved
|
||||||
*************************************************/
|
*************************************************/
|
||||||
|
|
||||||
import addPermissionsListDirective from './addPermissionsList.directive';
|
import rbacMultiselectList from './rbac-multiselect-list.directive';
|
||||||
|
import rbacMultiselectRole from './rbac-multiselect-role.directive';
|
||||||
import teamsList from './permissionsTeams.list';
|
import teamsList from './permissionsTeams.list';
|
||||||
import usersList from './permissionsUsers.list';
|
import usersList from './permissionsUsers.list';
|
||||||
|
|
||||||
export default
|
export default
|
||||||
angular.module('addPermissionsListModule', [])
|
angular.module('rbacMultiselectModule', [])
|
||||||
.directive('addPermissionsList', addPermissionsListDirective)
|
.directive('rbacMultiselectList', rbacMultiselectList)
|
||||||
|
.directive('rbacMultiselectRole', rbacMultiselectRole)
|
||||||
.factory('addPermissionsTeamsList', teamsList)
|
.factory('addPermissionsTeamsList', teamsList)
|
||||||
.factory('addPermissionsUsersList', usersList);
|
.factory('addPermissionsUsersList', usersList);
|
||||||
@@ -0,0 +1,112 @@
|
|||||||
|
/*************************************************
|
||||||
|
* Copyright (c) 2015 Ansible, Inc.
|
||||||
|
*
|
||||||
|
* All Rights Reserved
|
||||||
|
*************************************************/
|
||||||
|
|
||||||
|
/* jshint unused: vars */
|
||||||
|
export default ['addPermissionsTeamsList', 'addPermissionsUsersList', 'TemplateList', 'ProjectList',
|
||||||
|
'InventoryList', 'CredentialList', '$compile', 'generateList', 'GetBasePath', 'SelectionInit',
|
||||||
|
function(addPermissionsTeamsList, addPermissionsUsersList, TemplateList, ProjectList,
|
||||||
|
InventoryList, CredentialList, $compile, generateList, GetBasePath, SelectionInit) {
|
||||||
|
return {
|
||||||
|
restrict: 'E',
|
||||||
|
scope: {
|
||||||
|
allSelected: '=',
|
||||||
|
view: '@',
|
||||||
|
dataset: '='
|
||||||
|
},
|
||||||
|
template: "<div class='addPermissionsList-inner'></div>",
|
||||||
|
link: function(scope, element, attrs, ctrl) {
|
||||||
|
let listMap, list, list_html;
|
||||||
|
|
||||||
|
listMap = {
|
||||||
|
Teams: addPermissionsTeamsList,
|
||||||
|
Users: addPermissionsUsersList,
|
||||||
|
Projects: ProjectList,
|
||||||
|
JobTemplates: TemplateList,
|
||||||
|
WorkflowTemplates: TemplateList,
|
||||||
|
Inventories: InventoryList,
|
||||||
|
Credentials: CredentialList
|
||||||
|
};
|
||||||
|
list = _.cloneDeep(listMap[scope.view]);
|
||||||
|
list.multiSelect = true;
|
||||||
|
list.multiSelectExtended = true;
|
||||||
|
list.listTitleBadge = false;
|
||||||
|
delete list.actions;
|
||||||
|
delete list.fieldActions;
|
||||||
|
|
||||||
|
switch(scope.view){
|
||||||
|
|
||||||
|
case 'Projects':
|
||||||
|
list.fields = {
|
||||||
|
name: list.fields.name,
|
||||||
|
scm_type: list.fields.scm_type
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'Inventories':
|
||||||
|
list.fields = {
|
||||||
|
name: list.fields.name,
|
||||||
|
organization: list.fields.organization
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'JobTemplates':
|
||||||
|
list.name = 'job_templates';
|
||||||
|
list.iterator = 'job_template';
|
||||||
|
list.fields = {
|
||||||
|
name: list.fields.name,
|
||||||
|
description: list.fields.description
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'WorkflowTemplates':
|
||||||
|
list.name = 'workflow_templates';
|
||||||
|
list.iterator = 'workflow_template';
|
||||||
|
list.basePath = 'workflow_job_templates';
|
||||||
|
list.fields = {
|
||||||
|
name: list.fields.name,
|
||||||
|
description: list.fields.description
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case 'Users':
|
||||||
|
list.fields = {
|
||||||
|
username: list.fields.username,
|
||||||
|
first_name: list.fields.first_name,
|
||||||
|
last_name: list.fields.last_name
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
list.fields = {
|
||||||
|
name: list.fields.name,
|
||||||
|
description: list.fields.description
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
list_html = generateList.build({
|
||||||
|
mode: 'edit',
|
||||||
|
list: list,
|
||||||
|
related: false,
|
||||||
|
title: false
|
||||||
|
});
|
||||||
|
|
||||||
|
scope.list = list;
|
||||||
|
scope[`${list.iterator}_dataset`] = scope.dataset.data;
|
||||||
|
scope[`${list.name}`] = scope[`${list.iterator}_dataset`].results;
|
||||||
|
|
||||||
|
scope.$watch(list.name, function(){
|
||||||
|
_.forEach(scope[`${list.name}`], isSelected);
|
||||||
|
});
|
||||||
|
|
||||||
|
function isSelected(item){
|
||||||
|
if(_.find(scope.allSelected, {id: item.id})){
|
||||||
|
item.isSelected = true;
|
||||||
|
}
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
element.append(list_html);
|
||||||
|
$compile(element.contents())(scope);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}];
|
||||||
@@ -11,8 +11,12 @@ export default
|
|||||||
function(CreateSelect2) {
|
function(CreateSelect2) {
|
||||||
return {
|
return {
|
||||||
restrict: 'E',
|
restrict: 'E',
|
||||||
scope: false,
|
scope: {
|
||||||
template: '<select ng-cloak class="AddPermissions-selectHide roleSelect2 form-control" ng-model="obj.roles" ng-options="role.label for role in roles | filter:{label: \'!Read\'} track by role.value" multiple required></select>',
|
roles: '=',
|
||||||
|
model: '='
|
||||||
|
},
|
||||||
|
// @issue why is the read-only role ommited from this selection?
|
||||||
|
template: '<select ng-cloak class="AddPermissions-selectHide roleSelect2 form-control" ng-model="model" ng-options="role.name for role in roles track by role.id" multiple required></select>',
|
||||||
link: function(scope, element, attrs, ctrl) {
|
link: function(scope, element, attrs, ctrl) {
|
||||||
CreateSelect2({
|
CreateSelect2({
|
||||||
element: '.roleSelect2',
|
element: '.roleSelect2',
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/** @define RoleList */
|
/** @define RoleList */
|
||||||
@import "../shared/branding/colors.default.less";
|
@import "../../shared/branding/colors.default.less";
|
||||||
|
|
||||||
.RoleList {
|
.RoleList {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -5,7 +5,7 @@ export default
|
|||||||
return {
|
return {
|
||||||
restrict: 'E',
|
restrict: 'E',
|
||||||
scope: true,
|
scope: true,
|
||||||
templateUrl: templateUrl('access/roleList'),
|
templateUrl: templateUrl('access/rbac-role-column/roleList'),
|
||||||
link: function(scope, element, attrs) {
|
link: function(scope, element, attrs) {
|
||||||
// given a list of roles (things like "project
|
// given a list of roles (things like "project
|
||||||
// auditor") which are pulled from two different
|
// auditor") which are pulled from two different
|
||||||
@@ -64,7 +64,7 @@ export default
|
|||||||
},
|
},
|
||||||
|
|
||||||
related: {
|
related: {
|
||||||
permissions: {
|
users: {
|
||||||
dataPlacement: 'top',
|
dataPlacement: 'top',
|
||||||
awToolTip: i18n._('Please save before adding users'),
|
awToolTip: i18n._('Please save before adding users'),
|
||||||
basePath: 'api/v1/teams/{{$stateParams.team_id}}/access_list/',
|
basePath: 'api/v1/teams/{{$stateParams.team_id}}/access_list/',
|
||||||
@@ -73,15 +73,14 @@ export default
|
|||||||
},
|
},
|
||||||
type: 'collection',
|
type: 'collection',
|
||||||
title: i18n._('Users'),
|
title: i18n._('Users'),
|
||||||
iterator: 'permission',
|
iterator: 'user',
|
||||||
index: false,
|
index: false,
|
||||||
open: false,
|
open: false,
|
||||||
actions: {
|
actions: {
|
||||||
add: {
|
add: {
|
||||||
// @issue https://github.com/ansible/ansible-tower/issues/3487
|
ngClick: "$state.go('.add')",
|
||||||
//ngClick: "addPermissionWithoutTeamTab",
|
|
||||||
label: i18n._('Add'),
|
label: i18n._('Add'),
|
||||||
awToolTip: i18n._('Add user to team'),
|
awToolTip: i18n._('Add User'),
|
||||||
actionClass: 'btn List-buttonSubmit',
|
actionClass: 'btn List-buttonSubmit',
|
||||||
buttonContent: '+ ' + i18n._('ADD'),
|
buttonContent: '+ ' + i18n._('ADD'),
|
||||||
ngShow: '(team_obj.summary_fields.user_capabilities.edit || canAdd)'
|
ngShow: '(team_obj.summary_fields.user_capabilities.edit || canAdd)'
|
||||||
@@ -104,45 +103,44 @@ export default
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
roles: {
|
permissions: {
|
||||||
hideSearchAndActions: true,
|
|
||||||
dataPlacement: 'top',
|
|
||||||
awToolTip: i18n._('Please save before assigning permissions'),
|
|
||||||
basePath: 'api/v1/teams/{{$stateParams.team_id}}/roles/',
|
basePath: 'api/v1/teams/{{$stateParams.team_id}}/roles/',
|
||||||
search: {
|
search: {
|
||||||
page_size: '10',
|
page_size: '10',
|
||||||
// @todo ask about name field / serializer on this endpoint
|
// @todo ask about name field / serializer on this endpoint
|
||||||
order_by: 'id'
|
order_by: 'id'
|
||||||
},
|
},
|
||||||
|
awToolTip: i18n._('Please save before assigning permissions'),
|
||||||
|
dataPlacement: 'top',
|
||||||
|
hideSearchAndActions: true,
|
||||||
type: 'collection',
|
type: 'collection',
|
||||||
title: i18n._('Granted Permissions'),
|
title: i18n._('Permissions'),
|
||||||
iterator: 'role',
|
iterator: 'permission',
|
||||||
open: false,
|
open: false,
|
||||||
index: false,
|
index: false,
|
||||||
actions: {},
|
|
||||||
emptyListText: i18n._('No permissions have been granted'),
|
emptyListText: i18n._('No permissions have been granted'),
|
||||||
fields: {
|
fields: {
|
||||||
name: {
|
name: {
|
||||||
label: i18n._('Name'),
|
label: i18n._('Name'),
|
||||||
ngBind: 'role.summary_fields.resource_name',
|
ngBind: 'permission.summary_fields.resource_name',
|
||||||
linkTo: '{{convertApiUrl(role.related[role.summary_fields.resource_type])}}',
|
linkTo: '{{convertApiUrl(permission.related[permission.summary_fields.resource_type])}}',
|
||||||
noSort: true
|
noSort: true
|
||||||
},
|
},
|
||||||
type: {
|
type: {
|
||||||
label: i18n._('Type'),
|
label: i18n._('Type'),
|
||||||
ngBind: 'role.summary_fields.resource_type_display_name',
|
ngBind: 'permission.summary_fields.resource_type_display_name',
|
||||||
noSort: true
|
noSort: true
|
||||||
},
|
},
|
||||||
role: {
|
role: {
|
||||||
label: i18n._('Role'),
|
label: i18n._('Role'),
|
||||||
ngBind: 'role.name',
|
ngBind: 'permission.name',
|
||||||
noSort: true
|
noSort: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
fieldActions: {
|
fieldActions: {
|
||||||
"delete": {
|
"delete": {
|
||||||
label: i18n._('Remove'),
|
label: i18n._('Remove'),
|
||||||
ngClick: 'deletePermissionFromTeam(team_id, team_obj.name, role.name, role.summary_fields.resource_name, role.related.teams)',
|
ngClick: 'deletePermissionFromTeam(team_id, team_obj.name, permission.name, permission.summary_fields.resource_name, permission.related.teams)',
|
||||||
'class': "List-actionButton--delete",
|
'class': "List-actionButton--delete",
|
||||||
iconClass: 'fa fa-times',
|
iconClass: 'fa fa-times',
|
||||||
awToolTip: i18n._('Dissasociate permission from team'),
|
awToolTip: i18n._('Dissasociate permission from team'),
|
||||||
@@ -150,7 +148,16 @@ export default
|
|||||||
ngShow: 'permission.summary_fields.user_capabilities.unattach'
|
ngShow: 'permission.summary_fields.user_capabilities.unattach'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
//hideOnSuperuser: true // defunct with RBAC
|
actions: {
|
||||||
|
add: {
|
||||||
|
ngClick: "$state.go('.add')",
|
||||||
|
label: 'Add',
|
||||||
|
awToolTip: i18n._('Grant Permission'),
|
||||||
|
actionClass: 'btn List-buttonSubmit',
|
||||||
|
buttonContent: '+ ' + i18n._('ADD PERMISSIONS'),
|
||||||
|
ngShow: '(team_obj.summary_fields.user_capabilities.edit || canAdd)'
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};}]); //InventoryForm
|
};}]); //InventoryForm
|
||||||
|
|||||||
@@ -173,14 +173,13 @@ export default
|
|||||||
basePath: 'api/v1/users/{{$stateParams.user_id}}/roles/',
|
basePath: 'api/v1/users/{{$stateParams.user_id}}/roles/',
|
||||||
search: {
|
search: {
|
||||||
page_size: '10',
|
page_size: '10',
|
||||||
// @todo ask about name field / serializer on this endpoint
|
|
||||||
order_by: 'id'
|
order_by: 'id'
|
||||||
},
|
},
|
||||||
awToolTip: i18n._('Please save before assigning to organizations'),
|
awToolTip: i18n._('Please save before assigning to organizations'),
|
||||||
dataPlacement: 'top',
|
dataPlacement: 'top',
|
||||||
hideSearchAndActions: true,
|
hideSearchAndActions: true,
|
||||||
type: 'collection',
|
type: 'collection',
|
||||||
title: i18n._('Granted permissions'),
|
title: i18n._('Permissions'),
|
||||||
iterator: 'permission',
|
iterator: 'permission',
|
||||||
open: false,
|
open: false,
|
||||||
index: false,
|
index: false,
|
||||||
@@ -203,12 +202,16 @@ export default
|
|||||||
noSort: true
|
noSort: true
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// @issue https://github.com/ansible/ansible-tower/issues/3487
|
actions: {
|
||||||
// actions: {
|
add: {
|
||||||
// add: {
|
ngClick: "$state.go('.add')",
|
||||||
|
label: 'Add',
|
||||||
// }
|
awToolTip: i18n._('Grant Permission'),
|
||||||
// }
|
actionClass: 'btn List-buttonSubmit',
|
||||||
|
buttonContent: '+ ' + i18n._('ADD PERMISSIONS'),
|
||||||
|
ngShow: '(user_obj.summary_fields.user_capabilities.edit || canAdd)'
|
||||||
|
}
|
||||||
|
},
|
||||||
fieldActions: {
|
fieldActions: {
|
||||||
"delete": {
|
"delete": {
|
||||||
label: i18n._('Remove'),
|
label: i18n._('Remove'),
|
||||||
|
|||||||
@@ -1760,7 +1760,6 @@ angular.module('FormGenerator', [GeneratorHelpers.name, 'Utilities', listGenerat
|
|||||||
if (this.form.horizontal) {
|
if (this.form.horizontal) {
|
||||||
html += "</div>\n";
|
html += "</div>\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -241,9 +241,11 @@ export default ['$location', '$compile', '$rootScope', 'Attr', 'Icon',
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Show the "no items" box when loading is done and the user isn't actively searching and there are no results
|
// Show the "no items" box when loading is done and the user isn't actively searching and there are no results
|
||||||
html += `<div class="List-noItems" ng-show="${list.name}.length === 0 && (searchTags | isEmpty)">`;
|
if (options.showEmptyPanel === undefined || options.showEmptyPanel === true){
|
||||||
html += (list.emptyListText) ? list.emptyListText : i18n._("PLEASE ADD ITEMS TO THIS LIST");
|
html += `<div class="List-noItems" ng-show="${list.name}.length === 0 && (searchTags | isEmpty)">`;
|
||||||
html += "</div>";
|
html += (list.emptyListText) ? list.emptyListText : i18n._("PLEASE ADD ITEMS TO THIS LIST");
|
||||||
|
html += "</div>";
|
||||||
|
}
|
||||||
|
|
||||||
// Add a title and optionally a close button (used on Inventory->Groups)
|
// Add a title and optionally a close button (used on Inventory->Groups)
|
||||||
if (options.mode !== 'lookup' && list.showTitle) {
|
if (options.mode !== 'lookup' && list.showTitle) {
|
||||||
@@ -443,12 +445,14 @@ export default ['$location', '$compile', '$rootScope', 'Attr', 'Icon',
|
|||||||
html += "</div>\n";
|
html += "</div>\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
html += `<paginate
|
if (options.paginate === undefined || options.paginate === true) {
|
||||||
|
html += `<paginate
|
||||||
base-path="${list.basePath || list.name}"
|
base-path="${list.basePath || list.name}"
|
||||||
collection="${list.name}"
|
collection="${list.name}"
|
||||||
dataset="${list.iterator}_dataset"
|
dataset="${list.iterator}_dataset"
|
||||||
iterator="${list.iterator}">
|
iterator="${list.iterator}">
|
||||||
</paginate></div>`;
|
</paginate></div>`;
|
||||||
|
}
|
||||||
|
|
||||||
return html;
|
return html;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -236,7 +236,84 @@ export default ['$injector', '$stateExtender', '$log', function($injector, $stat
|
|||||||
*/
|
*/
|
||||||
generateFormListDefinitions: function(form, formStateDefinition) {
|
generateFormListDefinitions: function(form, formStateDefinition) {
|
||||||
|
|
||||||
function buildPermissionDirective() {
|
function buildRbacUserTeamDirective(){
|
||||||
|
let states = [];
|
||||||
|
|
||||||
|
states.push($stateExtender.buildDefinition({
|
||||||
|
name: `${formStateDefinition.name}.permissions.add`,
|
||||||
|
squashSearchUrl: true,
|
||||||
|
url: '/add-permissions',
|
||||||
|
params: {
|
||||||
|
project_search: {
|
||||||
|
value: {order_by: 'name', page_size: '5', role_level: 'admin_role'},
|
||||||
|
dynamic: true
|
||||||
|
},
|
||||||
|
job_template_search: {
|
||||||
|
value: {order_by: 'name', page_size: '5', role_level: 'admin_role'},
|
||||||
|
dynamic: true
|
||||||
|
},
|
||||||
|
workflow_template_search: {
|
||||||
|
value: {order_by: 'name', page_size: '5', role_level: 'admin_role'},
|
||||||
|
dynamic: true
|
||||||
|
},
|
||||||
|
inventory_search: {
|
||||||
|
value: {order_by: 'name', page_size: '5', role_level: 'admin_role'},
|
||||||
|
dynamic: true
|
||||||
|
},
|
||||||
|
credential_search: {
|
||||||
|
value: {order_by: 'name', page_size: '5', role_level: 'admin_role'},
|
||||||
|
dynamic: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
views: {
|
||||||
|
[`modal@${formStateDefinition.name}`]: {
|
||||||
|
template: `<add-rbac-user-team resolve="$resolve"></add-rbac-user-team>`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
jobTemplatesDataset: ['QuerySet', '$stateParams', 'GetBasePath',
|
||||||
|
function(qs, $stateParams, GetBasePath) {
|
||||||
|
let path = GetBasePath('job_templates');
|
||||||
|
return qs.search(path, $stateParams.job_template_search);
|
||||||
|
}
|
||||||
|
],
|
||||||
|
workflowTemplatesDataset: ['QuerySet', '$stateParams', 'GetBasePath',
|
||||||
|
function(qs, $stateParams, GetBasePath) {
|
||||||
|
let path = GetBasePath('workflow_job_templates');
|
||||||
|
return qs.search(path, $stateParams.workflow_template_search);
|
||||||
|
}
|
||||||
|
],
|
||||||
|
projectsDataset: ['ProjectList', 'QuerySet', '$stateParams', 'GetBasePath',
|
||||||
|
function(list, qs, $stateParams, GetBasePath) {
|
||||||
|
let path = GetBasePath(list.basePath) || GetBasePath(list.name);
|
||||||
|
return qs.search(path, $stateParams[`${list.iterator}_search`]);
|
||||||
|
}
|
||||||
|
],
|
||||||
|
inventoriesDataset: ['InventoryList', 'QuerySet', '$stateParams', 'GetBasePath',
|
||||||
|
function(list, qs, $stateParams, GetBasePath) {
|
||||||
|
let path = GetBasePath(list.basePath) || GetBasePath(list.name);
|
||||||
|
return qs.search(path, $stateParams[`${list.iterator}_search`]);
|
||||||
|
}
|
||||||
|
],
|
||||||
|
credentialsDataset: ['CredentialList', 'QuerySet', '$stateParams', 'GetBasePath',
|
||||||
|
function(list, qs, $stateParams, GetBasePath) {
|
||||||
|
let path = GetBasePath(list.basePath) || GetBasePath(list.name);
|
||||||
|
return qs.search(path, $stateParams[`${list.iterator}_search`]);
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
onExit: function($state) {
|
||||||
|
if ($state.transition) {
|
||||||
|
$('#add-permissions-modal').modal('hide');
|
||||||
|
$('.modal-backdrop').remove();
|
||||||
|
$('body').removeClass('modal-open');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
return states;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildRbacResourceDirective() {
|
||||||
let states = [];
|
let states = [];
|
||||||
|
|
||||||
states.push($stateExtender.buildDefinition({
|
states.push($stateExtender.buildDefinition({
|
||||||
@@ -255,7 +332,7 @@ export default ['$injector', '$stateExtender', '$log', function($injector, $stat
|
|||||||
},
|
},
|
||||||
views: {
|
views: {
|
||||||
[`modal@${formStateDefinition.name}`]: {
|
[`modal@${formStateDefinition.name}`]: {
|
||||||
template: `<add-permissions users-dataset="$resolve.usersDataset" teams-dataset="$resolve.teamsDataset" selected="allSelected" resource-data="$resolve.resourceData"></add-permissions>`
|
template: `<add-rbac-resource users-dataset="$resolve.usersDataset" teams-dataset="$resolve.teamsDataset" selected="allSelected" resource-data="$resolve.resourceData"></add-rbac-resource>`
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
@@ -288,7 +365,13 @@ export default ['$injector', '$stateExtender', '$log', function($injector, $stat
|
|||||||
let states = [];
|
let states = [];
|
||||||
states.push(buildListDefinition(field));
|
states.push(buildListDefinition(field));
|
||||||
if (field.iterator === 'permission' && field.actions && field.actions.add) {
|
if (field.iterator === 'permission' && field.actions && field.actions.add) {
|
||||||
states.push(buildPermissionDirective());
|
if (form.name === 'user' || form.name === 'team'){
|
||||||
|
states.push(buildRbacUserTeamDirective());
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
states.push(buildRbacResourceDirective());
|
||||||
|
}
|
||||||
states = _.flatten(states);
|
states = _.flatten(states);
|
||||||
}
|
}
|
||||||
return states;
|
return states;
|
||||||
|
|||||||
Reference in New Issue
Block a user