ui/lib/global-admin/addon/components/form-global-roles/component.js

242 lines
7.3 KiB
JavaScript

import Component from '@ember/component'
import { all as PromiseAll } from 'rsvp';
import { inject as service } from '@ember/service';
import { get, set, setProperties } from '@ember/object';
import layout from './template';
import $ from 'jquery';
import { isEmpty } from '@ember/utils';
import { computed } from '@ember/object';
import { isArray } from '@ember/array';
const USER = 'user';
const ADMIN = 'admin';
const RESTRICTED_ADMIN = 'restricted-admin';
const BASE = 'user-base';
const LOGIN_ACCESS_ROLES = [
{
name: USER,
translationKey: 'formGlobalRoles.mode.user.label',
descriptionTranslationKey: 'formGlobalRoles.mode.user.detail',
},
{
name: ADMIN,
translationKey: 'formGlobalRoles.mode.admin.label',
descriptionTranslationKey: 'formGlobalRoles.mode.admin.detail',
},
{
name: RESTRICTED_ADMIN,
translationKey: 'formGlobalRoles.mode.restrictedAdmin.label',
descriptionTranslationKey: 'formGlobalRoles.mode.restrictedAdmin.detail',
},
{
name: BASE,
translationKey: 'formGlobalRoles.mode.userBase.label',
descriptionTranslationKey: 'formGlobalRoles.mode.userBase.detail',
},
];
export default Component.extend({
settings: service(),
globalStore: service(),
layout,
user: null,
groupPrincipalId: null,
mode: null,
allRoles: null,
_boundSave: null,
_boundValidator: null,
init() {
this._super(...arguments);
set(this, 'allRoles', this.globalStore.all('globalRole'));
this.initRoles();
this.initBindings();
},
actions: {
toggle(e) {
const $target = $(e.target);
const $row = $target.closest('.input-group');
const check = $('input[type =checkbox]', $row)[0];
if ( check && e.target !== check && e.target.tagName !== 'LABEL' ) {
check.click();
}
}
},
baseRoles: computed('allRoles.[]', function() {
const { allRoles } = this;
return [ADMIN, RESTRICTED_ADMIN, USER, BASE].map((r) => allRoles.findBy('id', r)).compact();
}),
make(role) {
const out = this.globalStore.createRecord({
type: 'globalRoleBinding',
globalRoleId: get(role, 'id'),
});
if (!isEmpty(this.user)) {
set(out, 'userId', this.user.id);
}
if (!isEmpty(this.groupPrincipalId)) {
set(out, 'groupPrincipalId', this.groupPrincipalId);
}
return out;
},
save() {
set(this, 'errors', null);
const allRoles = [...this.baseRoles, ...this.additionalRoles, ...this.userRoles];
// all active non-existant roles remapped to an array of the role resources for the save
const add = allRoles.filterBy('active').filterBy('existing', false).map((r) => this.make(r.role));
// all inactive existing roles remapped to an array of the role resources for the remove save
const remove = allRoles.filterBy('active', false).filterBy('existing').map((r) => r.existing);
return PromiseAll(add.map((x) => x.save())).then(() => {
return PromiseAll(remove.map((x) => x.delete())).then(() => {
return true;
});
});
},
initBindings() {
if (!isEmpty(this.setSave)) {
set(this, '_boundSave', this.save.bind(this));
this.setSave(this._boundSave);
}
if (!isEmpty(this.setGRValidator)) {
set(this, '_boundValidator', this.confirmUserCanLogIn.bind(this));
this.setGRValidator(this._boundValidator);
}
},
initBaseRoles() {
set(this, 'baseRoles', this.baseRoles.map(this.roleMapper.bind(this)))
},
initRoles() {
setProperties(this, {
baseRoles: this.baseRoles.map(this.roleMapper.bind(this)),
additionalRoles: this.allRoles.filterBy('isHidden', false).filterBy('builtin').filter((role) => role.id !== 'restricted-admin').map(this.roleMapper.bind(this)),
userRoles: this.allRoles.filterBy('isHidden', false).filterBy('builtin', false).map(this.roleMapper.bind(this))
});
if (this.mode === 'new') {
this.populateDefaultRoles();
}
},
roleMapper(role) {
const { user, groupGlobalRoleBindings = [] } = this;
const usersGlobalRoleBindings = [];
let hasTranslation = true;
if (!isEmpty(user)) {
usersGlobalRoleBindings.pushObjects(user.globalRoleBindings.filterBy('groupPrincipalId', null));
} else {
usersGlobalRoleBindings.pushObjects(groupGlobalRoleBindings.slice());
}
const binding = usersGlobalRoleBindings.findBy('globalRole', role) || false;
let translationKey = null;
let descriptionTranslationKey = null;
if ( this.baseRoles.findBy('id', role.id) ) {
let roleMatch = LOGIN_ACCESS_ROLES.findBy('name', role.id);
({ translationKey, descriptionTranslationKey } = roleMatch);
} else {
hasTranslation = false;
}
return {
role,
translationKey,
descriptionTranslationKey,
hasTranslation,
active: !!binding,
existing: binding,
}
},
confirmUserCanLogIn() {
const allRoles = [...this.baseRoles, ...this.additionalRoles, ...this.userRoles];
let roles = allRoles.filterBy('active').map((r) => r.role);
let allRolesRules = [];
roles.forEach((r) => {
if (!isEmpty(r.rules)) {
allRolesRules.pushObjects(r.rules);
}
});
let matchingRules = allRolesRules.filter((rule) => {
if (this.isRuleValid(rule)) {
return rule;
}
return false;
});
if (isEmpty(matchingRules)) {
return false;
}
return true;
},
isRuleValid(rule) {
if (( rule.resources || [] ).any(resourceValidator) && ( rule.apiGroups || [] ).any(apiGroupValidator) && verbsValidator(( rule.verbs || [] ))) {
return true;
}
return false;
function resourceValidator(resource) {
const resourcesRequiredForLogin = ['*', 'preferences', 'settings', 'features'];
// console.log(`resourceValidator status: `, resourcesRequiredForLogin.includes(resource), resource);
return resourcesRequiredForLogin.includes(resource);
}
function apiGroupValidator(apiGroup) {
const apiGroupsRequiredForLogin = ['*', 'management.cattle.io'];
// console.log(`apiGroupsRequiredForLogin status: `, apiGroupsRequiredForLogin.includes(apiGroup), apiGroup);
return apiGroupsRequiredForLogin.includes(apiGroup);
}
function verbsValidator(verbs) {
const restrictedTarget = ['get', 'list', 'watch'];
const verbsRequiredForLogin = ['*', ...restrictedTarget];
if (isArray(verbs) && verbs.length > 1) {
// console.log(`verbsRequiredForLogin status 1: `, restrictedTarget.every((rt) => verbs.includes(rt)), verbs);
return restrictedTarget.every((rt) => verbs.includes(rt));
}
// console.log(`verbsRequiredForLogin status 2: `, verbsRequiredForLogin.includes(verbs), verbs);
return verbsRequiredForLogin.includes(verbs.firstObject);
}
},
populateDefaultRoles() {
[...this.baseRoles, ...this.additionalRoles, ...this.userRoles].forEach((r) => {
if (!isEmpty(r.role)) {
if (r.role.id === 'user' || r.role.newUserDefault) {
set(r, 'active', true);
}
}
});
}
});