Skip to content

Commit

Permalink
UI - no jquery (#6768)
Browse files Browse the repository at this point in the history
* add no-jquery rule and move event listeners to ember-concurrency tasks

* remove unnecessary onchange and handleKeyDown actions

* add element.closest polyfill and convert linked-block to use native dom apis

* update pretender, fetch, page-object, add optional-features, remove ember/jquery

* turn off jquery inclusion

* remove jQuery.isPlainObject usage

* violatedDirective isn't always formatted the same

* use fetch and the ember-fetch adapter mixin

* move to fetch and lowercase headers for pretender

* display non-ember-data errors

* use new async fn test style and lowercase headers in auth service test

* setContext is not necessary with the new style tests and ember-cli-page-object - it actually triggers jquery usage

* update ember-fetch, ember-cli-pretender

* wait for permissions check

* lowercase header name in auth test

* refactor transit tests to one test per key type

* simplify pollCluster helper

* stop flakey tests by prefering the native fetch

* avoid uncaught TransitionAborted error by navigating directly to unseal

* unset model on controller after unloading it because controllers are singletons

* update yarn.lock
  • Loading branch information
meirish authored Jun 20, 2019
1 parent 76b551f commit aee6566
Show file tree
Hide file tree
Showing 42 changed files with 525 additions and 401 deletions.
1 change: 1 addition & 0 deletions ui/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ module.exports = {
rules: {
'no-unused-vars': ['error', { ignoreRestSiblings: true }],
'prettier/prettier': 'error',
'ember/no-jquery': 'error',
},
globals: {
TextEncoderLite: true,
Expand Down
3 changes: 2 additions & 1 deletion ui/app/adapters/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ import { assign } from '@ember/polyfills';
import { set } from '@ember/object';
import RSVP from 'rsvp';
import DS from 'ember-data';
import AdapterFetch from 'ember-fetch/mixins/adapter-fetch';
import fetch from 'fetch';
import config from '../config/environment';

const { APP } = config;
const { POLLING_URLS, NAMESPACE_ROOT_URLS } = APP;

export default DS.RESTAdapter.extend({
export default DS.RESTAdapter.extend(AdapterFetch, {
auth: service(),
namespaceService: service('namespace'),
controlGroup: service(),
Expand Down
18 changes: 10 additions & 8 deletions ui/app/components/auth-form.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,15 +175,17 @@ export default Component.extend(DEFAULTS, {

handleError(e, prefixMessage = true) {
this.set('loading', false);
if (!e.errors) {
return e;
let errors;
if (e.errors) {
errors = e.errors.map(error => {
if (error.detail) {
return error.detail;
}
return error;
});
} else {
errors = [e];
}
let errors = e.errors.map(error => {
if (error.detail) {
return error.detail;
}
return error;
});
let message = prefixMessage ? 'Authentication failed: ' : '';
this.set('error', `${message}${errors.join('.')}`);
},
Expand Down
10 changes: 5 additions & 5 deletions ui/app/components/linked-block.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ let LinkedBlockComponent = Component.extend({
encode: false,

click(event) {
const $target = this.$(event.target);
const $target = event.target;
const isAnchorOrButton =
$target.is('a') ||
$target.is('button') ||
$target.closest('button', event.currentTarget).length > 0 ||
$target.closest('a', event.currentTarget).length > 0;
$target.tagName === 'A' ||
$target.tagName === 'BUTTON' ||
$target.closest('button') ||
$target.closest('a');
if (!isAnchorOrButton) {
let params = this.get('params');
if (this.encode) {
Expand Down
38 changes: 12 additions & 26 deletions ui/app/components/role-edit.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { inject as service } from '@ember/service';
import { or } from '@ember/object/computed';
import { isBlank } from '@ember/utils';
import $ from 'jquery';
import { task, waitForEvent } from 'ember-concurrency';
import Component from '@ember/component';
import { set, get } from '@ember/object';
import FocusOnInsertMixin from 'vault/mixins/focus-on-insert';
Expand Down Expand Up @@ -42,20 +42,22 @@ export default Component.extend(FocusOnInsertMixin, {
}
},

didInsertElement() {
this._super(...arguments);
$(document).on('keyup.keyEdit', this.onEscape.bind(this));
},

willDestroyElement() {
this._super(...arguments);
const model = this.get('model');
if (get(model, 'isError')) {
model.rollbackAttributes();
if (this.model && this.model.isError) {
this.model.rollbackAttributes();
}
$(document).off('keyup.keyEdit');
},

waitForKeyUp: task(function*() {
while (true) {
let event = yield waitForEvent(document.body, 'keyup');
this.onEscape(event);
}
})
.on('didInsertElement')
.cancelOn('willDestroyElement'),

transitionToRoute() {
this.get('router').transitionTo(...arguments);
},
Expand Down Expand Up @@ -84,18 +86,6 @@ export default Component.extend(FocusOnInsertMixin, {
},

actions: {
handleKeyDown(_, e) {
e.stopPropagation();
if (!(e.keyCode === keys.ENTER && e.metaKey)) {
return;
}
let $form = this.$('form');
if ($form.length) {
$form.submit();
}
$form = null;
},

createOrUpdate(type, event) {
event.preventDefault();

Expand All @@ -112,10 +102,6 @@ export default Component.extend(FocusOnInsertMixin, {
});
},

handleChange() {
this.hasDataChanges();
},

setValue(key, event) {
set(get(this, 'model'), key, event.target.checked);
},
Expand Down
9 changes: 6 additions & 3 deletions ui/app/components/secret-edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ export default Component.extend(FocusOnInsertMixin, WithNavToNearestAncestor, {
updatePath: maybeQueryRecord(
'capabilities',
context => {
if (context.mode === 'create') {
if (!context.model || context.mode === 'create') {
return;
}
let backend = context.isV2 ? context.get('model.engine.id') : context.model.backend;
Expand All @@ -116,7 +116,7 @@ export default Component.extend(FocusOnInsertMixin, WithNavToNearestAncestor, {
v2UpdatePath: maybeQueryRecord(
'capabilities',
context => {
if (context.mode === 'create' || context.isV2 === false) {
if (!context.model || context.mode === 'create' || context.isV2 === false) {
return;
}
let backend = context.get('model.engine.id');
Expand All @@ -137,7 +137,9 @@ export default Component.extend(FocusOnInsertMixin, WithNavToNearestAncestor, {
buttonDisabled: or('requestInFlight', 'model.isFolder', 'model.flagsIsInvalid', 'hasLintError', 'error'),

modelForData: computed('isV2', 'model', function() {
return this.isV2 ? this.model.belongsTo('selectedVersion').value() : this.model;
let { model } = this;
if (!model) return null;
return this.isV2 ? model.belongsTo('selectedVersion').value() : model;
}),

basicModeDisabled: computed('secretDataIsAdvanced', 'showAdvancedMode', function() {
Expand All @@ -160,6 +162,7 @@ export default Component.extend(FocusOnInsertMixin, WithNavToNearestAncestor, {
'model.{failedServerRead,selectedVersion.failedServerRead}',
'isV2',
function() {
if (!this.model) return;
// if the version couldn't be read from the server
if (this.isV2 && this.model.selectedVersion.failedServerRead) {
return true;
Expand Down
43 changes: 13 additions & 30 deletions ui/app/components/transit-edit.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { inject as service } from '@ember/service';
import { or } from '@ember/object/computed';
import { isBlank } from '@ember/utils';
import $ from 'jquery';
import Component from '@ember/component';
import { task, waitForEvent } from 'ember-concurrency';
import { set, get } from '@ember/object';

import FocusOnInsertMixin from 'vault/mixins/focus-on-insert';
import keys from 'vault/lib/keycodes';

Expand All @@ -19,24 +20,22 @@ export default Component.extend(FocusOnInsertMixin, {
key: null,
requestInFlight: or('key.isLoading', 'key.isReloading', 'key.isSaving'),

init() {
this._super(...arguments);
},

didInsertElement() {
this._super(...arguments);
$(document).on('keyup.keyEdit', this.onEscape.bind(this));
},

willDestroyElement() {
this._super(...arguments);
const key = this.get('key');
if (get(key, 'isError')) {
key.rollbackAttributes();
if (this.key && this.key.isError) {
this.key.rollbackAttributes();
}
$(document).off('keyup.keyEdit');
},

waitForKeyUp: task(function*() {
while (true) {
let event = yield waitForEvent(document.body, 'keyup');
this.onEscape(event);
}
})
.on('didInsertElement')
.cancelOn('willDestroyElement'),

transitionToRoute() {
this.get('router').transitionTo(...arguments);
},
Expand Down Expand Up @@ -69,18 +68,6 @@ export default Component.extend(FocusOnInsertMixin, {
},

actions: {
handleKeyDown(_, e) {
e.stopPropagation();
if (!(e.keyCode === keys.ENTER && e.metaKey)) {
return;
}
let $form = this.$('form');
if ($form.length) {
$form.submit();
}
$form = null;
},

createOrUpdateKey(type, event) {
event.preventDefault();

Expand All @@ -101,10 +88,6 @@ export default Component.extend(FocusOnInsertMixin, {
);
},

handleChange() {
this.hasDataChanges();
},

setValueOnKey(key, event) {
set(get(this, 'key'), key, event.target.checked);
},
Expand Down
2 changes: 1 addition & 1 deletion ui/app/controllers/vault/cluster/settings/seal.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export default Controller.extend({
.then(() => {
this.model.cluster.get('leaderNode').set('sealed', true);
this.get('auth').deleteCurrentToken();
return this.transitionToRoute('vault.cluster');
return this.transitionToRoute('vault.cluster.unseal');
});
},
},
Expand Down
5 changes: 4 additions & 1 deletion ui/app/mixins/unload-model-route.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@ import Mixin from '@ember/object/mixin';
export default Mixin.create({
modelPath: 'model',
unloadModel() {
const model = this.controller.get(this.get('modelPath'));
let { modelPath } = this;
let model = this.controller.get(modelPath);
if (!model || !model.unloadRecord) {
return;
}
this.store.unloadRecord(model);
model.destroy();
// it's important to unset the model on the controller since controllers are singletons
this.controller.set(modelPath, null);
},

actions: {
Expand Down
4 changes: 2 additions & 2 deletions ui/app/routes/vault/cluster.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,14 @@ export default Route.extend(ModelBoundaryRoute, ClusterRoute, {
}
},

beforeModel() {
async beforeModel() {
const params = this.paramsFor(this.routeName);
this.clearNonGlobalModels();
this.get('namespaceService').setNamespace(params.namespaceQueryParam);
const id = this.getClusterId(params);
if (id) {
this.get('auth').setCluster(id);
this.get('permissions').getPaths.perform();
await this.get('permissions').getPaths.perform();
return this.get('version').fetchFeatures();
} else {
return reject({ httpStatus: 404, message: 'not found', path: params.cluster_name });
Expand Down
18 changes: 15 additions & 3 deletions ui/app/services/auth.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import Ember from 'ember';
import { resolve } from 'rsvp';
import { resolve, reject } from 'rsvp';
import { assign } from '@ember/polyfills';
import $ from 'jquery';
import { isArray } from '@ember/array';
import { computed, get } from '@ember/object';

import fetch from 'fetch';
import { getOwner } from '@ember/application';
import Service, { inject as service } from '@ember/service';
import getStorage from '../lib/token-storage';
Expand Down Expand Up @@ -86,7 +87,18 @@ export default Service.extend({
if (namespace) {
defaults.headers['X-Vault-Namespace'] = namespace;
}
return $.ajax(assign(defaults, options));
let opts = assign(defaults, options);

return fetch(url, {
method: opts.method || 'GET',
headers: opts.headers || {},
}).then(response => {
if (response.status >= 200 && response.status < 300) {
return resolve(response.json());
} else {
return reject();
}
});
},

renewCurrentToken() {
Expand Down
5 changes: 3 additions & 2 deletions ui/app/services/csp-event.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/*eslint-disable no-constant-condition*/
import { computed } from '@ember/object';
import { filterBy } from '@ember/object/computed';

import Service from '@ember/service';
import { task, waitForEvent } from 'ember-concurrency';
Expand All @@ -9,7 +8,9 @@ export default Service.extend({
events: computed(function() {
return [];
}),
connectionViolations: filterBy('events', 'violatedDirective', 'connect-src'),
connectionViolations: computed('events.[].violatedDirective', function() {
return this.get('events').filter(e => e.violatedDirective.startsWith('connect-src'));
}),

attach() {
this.monitor.perform();
Expand Down
2 changes: 1 addition & 1 deletion ui/app/templates/partials/role-aws/form.hbs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<form onsubmit={{action "createOrUpdate" "create"}} onchange={{action "handleChange"}}>
<form onsubmit={{action "createOrUpdate" "create"}}>
<div class="box is-sideless is-fullwidth is-marginless">
{{message-error model=model}}
<NamespaceReminder @mode={{mode}} @noun="AWS role" />
Expand Down
2 changes: 1 addition & 1 deletion ui/app/templates/partials/role-pki/form.hbs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<form onsubmit={{action "createOrUpdate" "create"}} onchange={{action "handleChange"}}>
<form onsubmit={{action "createOrUpdate" "create"}}>
<div class="box is-sideless is-fullwidth is-marginless">
{{message-error model=model}}
<NamespaceReminder @mode={{mode}} @noun="PKI role" />
Expand Down
Loading

0 comments on commit aee6566

Please sign in to comment.