ui/lib/global-admin/addon/components/new-edit-role/component.js

262 lines
6.2 KiB
JavaScript

import { alias, or } from '@ember/object/computed';
import { inject as service } from '@ember/service';
import Component from '@ember/component';
import C from 'ui/utils/constants';
import layout from './template';
import { get, computed, set } from '@ember/object';
import { isEmpty } from '@ember/utils';
import ViewNewEdit from 'shared/mixins/view-new-edit';
const ruleVerbs = C.RULE_VERBS.map((verb) => `rolesPage.new.form.allow.${ verb }`);
const BASIC_CONTEXT = [
{
label: 'All',
value: '',
},
{
label: 'Project',
value: 'project',
},
{
label: 'Cluster',
value: 'cluster',
},
];
export default Component.extend(ViewNewEdit, {
intl: service(),
router: service(),
layout,
model: null,
ruleArray: null,
roleArray: null,
readOnly: null,
roleType: null,
contexts: BASIC_CONTEXT,
mode: 'new',
ruleVerbs,
primaryResource: alias('model.role'),
readOnlyOrBuiltIn: or('readOnly', 'builtIn', 'isView'),
init() {
this._super(...arguments);
const ruleArray = [];
const model = get(this, 'primaryResource');
(get(model, 'rules') || []).filter((r) => (r.resources || r.nonResourceURLs)).forEach((rule) => {
ruleArray.push(rule);
});
const roleArray = (get(model, 'roleTemplateIds') || []).map((id) => {
return { roleId: id };
});
this.setProperties({
ruleArray,
roleArray,
});
},
actions: {
cancel() {
this.goBack();
},
addRule() {
get(this, 'ruleArray').pushObject({
apiGroups: ['*'],
type: 'policyRule',
resource: null,
resources: [],
verbs: [],
});
},
removeRule(obj) {
get(this, 'ruleArray').removeObject(obj);
},
addOtherRole() {
get(this, 'roleArray').pushObject({ roleId: null, });
},
removeOtherRole(obj) {
get(this, 'roleArray').removeObject(obj);
},
},
readableRole: computed('roleType', function() {
return get(this, 'roleType').capitalize();
}),
isDefault: computed('roleType', {
get(/* key */) {
const model = get(this, 'model.role');
const type = get(this, 'roleType');
const field = this.getDefaultField(type);
return get(model, field);
},
set(key, value) {
const model = get(this, 'model.role');
const type = get(this, 'roleType');
const field = this.getDefaultField(type);
return model.set(field, value);
}
}),
builtIn: computed('model.role.builtin', function() {
return get(this, 'model.role.builtin') === true;
}),
otherRoles: computed('model.role.id', 'model.roles.@each.id', function() {
return get(this, 'model.roles').filter((role) => get(this, 'model.role.id') !== role.id);
}),
ruleResources: computed('model.globalRoles.[]', 'model.roleTemplates.[]', function() {
const {
model: { globalRoles, roles: roleTemplates },
roleType
} = this;
let groupedResourceRules;
switch (roleType) {
case 'global':
if (!isEmpty(globalRoles)) {
groupedResourceRules = this.getRuleResourceList(globalRoles);
}
break;
default:
if (!isEmpty(roleTemplates)) {
groupedResourceRules = this.getRuleResourceList(roleTemplates.filterBy('context', roleType));
}
break;
}
return groupedResourceRules;
}),
getRuleResourceList(roles) {
const groupedResourceRules = [];
roles.forEach((role) => {
if (!isEmpty(role.rules)) {
// currently is ungrouped but can be grouped.
// The problem is that these are just default resources in a particular role,
// they are not unique so they show up duplicated under different groups.
// we need some discussion whether this is okay or not
// const group = role.name;
role.rules.forEach((rule) => {
if (!isEmpty(rule.resources)) {
rule.resources.forEach((resource) => {
if (resource !== '*') {
groupedResourceRules.push({
// group,
label: resource,
value: resource
});
}
});
}
});
}
});
return groupedResourceRules.uniqBy('value').sortBy('label');
},
getDefaultField(type) {
let out = '';
switch (type) {
case 'global':
out = 'newUserDefault';
break;
case 'cluster':
out = 'clusterCreatorDefault';
break;
case 'project':
out = 'projectCreatorDefault';
break;
default:
break;
}
return out;
},
goBack() {
get(this, 'router').transitionTo('global-admin.security.roles.index', { queryParams: { context: get(this, 'roleType') } });
},
validate() {
this._super();
var errors = get(this, 'errors') || [];
if ((get(this, 'primaryResource.name') || '').trim().length === 0) {
errors.push(get(this, 'intl').t('rolesPage.new.errors.nameReq'));
}
set(this, 'errors', errors);
return get(this, 'errors.length') === 0;
},
willSave() {
const role = get(this, 'model.role');
const actualRules = [];
// Create the actual rules
const rules = get(this, 'ruleArray');
let obj;
for (let i = rules.length - 1; i >= 0; i--) {
obj = rules[i];
if (obj.resources && obj.resources.length && obj.verbs.length) {
const resources = [];
obj.resources.forEach((r) => {
resources.pushObjects((r || '').split(',').filter((r) => r));
});
actualRules.push({
type: obj.type,
apiGroups: obj.apiGroups.slice(),
verbs: obj.verbs.slice(),
resources,
});
} else {
rules.removeObject(obj);
}
}
role.set('rules', actualRules);
// Add roles
const roles = get(this, 'roleArray')
for (let i = roles.length - 1; i >= 0; i--) {
obj = roles[i];
if (!obj.roleId) {
roles.removeObject(obj);
}
}
role.set('roleTemplateIds', roles.map((obj) => obj.roleId));
return this._super(...arguments);
},
doneSaving() {
this.goBack();
},
});