consul/ui-v2/app/components/hashicorp-consul/index.js

145 lines
5.3 KiB
JavaScript

import Component from '@ember/component';
import { inject as service } from '@ember/service';
import { get, set, computed } from '@ember/object';
import { getOwner } from '@ember/application';
export default Component.extend({
dom: service('dom'),
env: service('env'),
feedback: service('feedback'),
router: service('router'),
http: service('repository/type/event-source'),
client: service('client/http'),
store: service('store'),
settings: service('settings'),
didInsertElement: function() {
this.dom.root().classList.remove('template-with-vertical-menu');
},
// TODO: Right now this is the only place where we need permissions
// but we are likely to need it elsewhere, so probably need a nice helper
canManageNspaces: computed('permissions', function() {
return (
typeof (this.permissions || []).find(function(item) {
return item.Resource === 'operator' && item.Access === 'write' && item.Allow;
}) !== 'undefined'
);
}),
forwardForACL: function(token) {
let routeName = this.router.currentRouteName;
const route = getOwner(this).lookup(`route:${routeName}`);
// a null AccessorID means we are in legacy mode
// take the user to the legacy acls
// otherwise just refresh the page
if (get(token, 'AccessorID') === null) {
// returning false for a feedback action means even though
// its successful, please skip this notification and don't display it
return route.transitionTo('dc.acls');
} else {
// TODO: Ideally we wouldn't need to use env() at a component level
// transitionTo should probably remove it instead if NSPACES aren't enabled
if (this.env.var('CONSUL_NSPACES_ENABLED') && get(token, 'Namespace') !== this.nspace.Name) {
if (!routeName.startsWith('nspace')) {
routeName = `nspace.${routeName}`;
}
const nspace = get(token, 'Namespace');
// you potentially have a new namespace
if (typeof nspace !== 'undefined') {
return route.transitionTo(`${routeName}`, `~${nspace}`, this.dc.Name);
}
// you are logging out, just refresh
return route.refresh();
} else {
if (route.routeName === 'dc.acls.index') {
return route.transitionTo('dc.acls.tokens.index');
}
return route.refresh();
}
}
},
actions: {
send: function(el, method, ...rest) {
const component = this.dom.component(el);
component.actions[method].apply(component, rest || []);
},
changeToken: function(token = {}) {
const prev = this.token;
if (token === '') {
token = {};
}
set(this, 'token', token);
// if this is just the initial 'find out what the current token is'
// then don't do anything
if (typeof prev === 'undefined') {
return;
}
let notification;
let action = () => this.forwardForACL(token);
switch (true) {
case get(this, 'token.AccessorID') === null && get(this, 'token.SecretID') === null:
// 'everything is null, 403 this needs deleting' token
this.settings.delete('token');
return;
case get(prev, 'AccessorID') === null && get(prev, 'SecretID') === null:
// we just had an 'everything is null, this needs deleting' token
// reject and break so this acts differently to just logging out
action = () => Promise.reject({});
notification = 'authorize';
break;
case typeof get(prev, 'AccessorID') !== 'undefined' &&
typeof get(this, 'token.AccessorID') !== 'undefined':
// change of both Accessor and Secret, means use
notification = 'use';
break;
case get(this, 'token.AccessorID') === null &&
typeof get(this, 'token.SecretID') !== 'undefined':
// legacy login, don't do anything as we don't use self for auth here but the endpoint itself
// self is successful, but skip this notification and don't display it
return this.forwardForACL(token);
case typeof get(prev, 'AccessorID') === 'undefined' &&
typeof get(this, 'token.AccessorID') !== 'undefined':
// normal login
notification = 'authorize';
break;
case (typeof get(prev, 'AccessorID') !== 'undefined' || get(prev, 'AccessorID') === null) &&
typeof get(this, 'token.AccessorID') === 'undefined':
//normal logout
notification = 'logout';
break;
}
this.actions.reauthorize.apply(this, [
{
type: notification,
action: action,
},
]);
},
reauthorize: function(e) {
this.client.abort();
this.http.resetCache();
this.store.init();
const type = get(e, 'type');
this.feedback.execute(
e.action,
type,
function(type, e) {
return type;
},
{}
);
},
change: function(e) {
const win = this.dom.viewport();
const $root = this.dom.root();
const $body = this.dom.element('body');
if (e.target.checked) {
$root.classList.add('template-with-vertical-menu');
$body.style.height = $root.style.height = win.innerHeight + 'px';
} else {
$root.classList.remove('template-with-vertical-menu');
$body.style.height = $root.style.height = null;
}
},
},
});