mirror of
https://github.com/hashicorp/vault.git
synced 2025-08-15 19:17:02 +02:00
use model dirty tracking to track changes
This commit is contained in:
parent
e5ff92962d
commit
077f366954
@ -74,13 +74,6 @@ export default Component.extend(FocusOnInsertMixin, {
|
||||
}
|
||||
},
|
||||
|
||||
willDestroyElement() {
|
||||
this._super(...arguments);
|
||||
if (this.model.isError && !this.model.isDestroyed) {
|
||||
this.model.rollbackAttributes();
|
||||
}
|
||||
},
|
||||
|
||||
waitForKeyUp: task(function*() {
|
||||
while (true) {
|
||||
let event = yield waitForEvent(document.body, 'keyup');
|
||||
@ -115,6 +108,25 @@ export default Component.extend(FocusOnInsertMixin, {
|
||||
canDelete: alias('updatePath.canDelete'),
|
||||
canEdit: alias('updatePath.canUpdate'),
|
||||
|
||||
v2UpdatePath: queryRecord(
|
||||
'capabilities',
|
||||
context => {
|
||||
if (context.mode === 'create' || context.isV2 === false) {
|
||||
return {};
|
||||
}
|
||||
let backend = context.model.belongsTo('engine').id;
|
||||
let id = context.model.id;
|
||||
return {
|
||||
id: `${backend}/metadata/${id}`,
|
||||
};
|
||||
},
|
||||
'isV2',
|
||||
'model',
|
||||
'model.id',
|
||||
'mode'
|
||||
),
|
||||
canEditV2Secret: alias('updatePath.canUpdate'),
|
||||
|
||||
requestInFlight: or('model.isLoading', 'model.isReloading', 'model.isSaving'),
|
||||
|
||||
buttonDisabled: or(
|
||||
@ -164,7 +176,9 @@ export default Component.extend(FocusOnInsertMixin, {
|
||||
|
||||
// successCallback is called in the context of the component
|
||||
persistKey(successCallback) {
|
||||
let secret = this.model;
|
||||
let model = this.modelForData;
|
||||
let isV2 = this.isV2;
|
||||
let key = model.get('path') || model.id;
|
||||
|
||||
if (key.startsWith('/')) {
|
||||
@ -174,13 +188,28 @@ export default Component.extend(FocusOnInsertMixin, {
|
||||
|
||||
return model.save().then(() => {
|
||||
if (!model.isError) {
|
||||
if (this.wizard.featureState === 'secret') {
|
||||
this.wizard.transitionFeatureMachine('secret', 'CONTINUE');
|
||||
if (isV2 && Object.keys(secret.changedAttributes()).length) {
|
||||
// save secret metadata
|
||||
secret
|
||||
.save()
|
||||
.then(() => {
|
||||
this.saveComplete(successCallback, key);
|
||||
})
|
||||
.catch(e => {
|
||||
this.set(e, e.errors.join(' '));
|
||||
});
|
||||
} else {
|
||||
this.saveComplete(successCallback, key);
|
||||
}
|
||||
successCallback(key);
|
||||
}
|
||||
});
|
||||
},
|
||||
saveComplete(callback, key) {
|
||||
if (this.wizard.featureState === 'secret') {
|
||||
this.wizard.transitionFeatureMachine('secret', 'CONTINUE');
|
||||
}
|
||||
callback(key);
|
||||
},
|
||||
|
||||
checkRows() {
|
||||
if (this.secretData.length === 0) {
|
||||
@ -203,14 +232,11 @@ export default Component.extend(FocusOnInsertMixin, {
|
||||
|
||||
handleChange() {
|
||||
this.set('codemirrorString', this.secretData.toJSONString(true));
|
||||
this.modelForData.set('secretData', this.secretData.toJSON());
|
||||
},
|
||||
|
||||
createOrUpdateKey(type, event) {
|
||||
event.preventDefault();
|
||||
const newData = this.secretData.toJSON();
|
||||
let model = this.modelForData;
|
||||
model.set('secretData', newData);
|
||||
|
||||
// prevent from submitting if there's no key
|
||||
// maybe do something fancier later
|
||||
if (type === 'create' && isBlank(model.get('path') || model.id)) {
|
||||
@ -241,7 +267,7 @@ export default Component.extend(FocusOnInsertMixin, {
|
||||
const data = this.secretData;
|
||||
if (isNone(data.findBy('name', ''))) {
|
||||
data.pushObject({ name: '', value: '' });
|
||||
this.set('codemirrorString', data.toJSONString(true));
|
||||
this.send('handleChange');
|
||||
}
|
||||
this.checkRows();
|
||||
},
|
||||
@ -254,7 +280,7 @@ export default Component.extend(FocusOnInsertMixin, {
|
||||
}
|
||||
data.removeObject(item);
|
||||
this.checkRows();
|
||||
this.set('codemirrorString', data.toJSONString(true));
|
||||
this.send('handleChange');
|
||||
},
|
||||
|
||||
toggleAdvanced(bool) {
|
||||
|
@ -12,9 +12,5 @@ export default Controller.extend(BackendCrumbMixin, {
|
||||
// so we have to manually bubble here
|
||||
this.send('refreshModel');
|
||||
},
|
||||
|
||||
hasChanges(hasChanges) {
|
||||
this.send('hasDataChanges', hasChanges);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -11,9 +11,6 @@ export default Controller.extend(BackendCrumbMixin, {
|
||||
refresh: function() {
|
||||
this.send('refreshModel');
|
||||
},
|
||||
hasChanges(hasChanges) {
|
||||
this.send('hasDataChanges', hasChanges);
|
||||
},
|
||||
toggleAdvancedEdit(bool) {
|
||||
this.set('preferAdvancedEdit', bool);
|
||||
this.get('backendController').set('preferAdvancedEdit', bool);
|
||||
|
@ -15,10 +15,6 @@ export default Controller.extend(BackendCrumbMixin, {
|
||||
this.send('refreshModel');
|
||||
},
|
||||
|
||||
hasChanges(hasChanges) {
|
||||
this.send('hasDataChanges', hasChanges);
|
||||
},
|
||||
|
||||
toggleAdvancedEdit(bool) {
|
||||
this.set('preferAdvancedEdit', bool);
|
||||
this.get('backendController').set('preferAdvancedEdit', bool);
|
||||
|
@ -17,10 +17,6 @@ export default Controller.extend(BackendCrumbMixin, {
|
||||
this.send('refreshModel');
|
||||
},
|
||||
|
||||
hasChanges(hasChanges) {
|
||||
this.send('hasDataChanges', hasChanges);
|
||||
},
|
||||
|
||||
toggleAdvancedEdit(bool) {
|
||||
this.set('preferAdvancedEdit', bool);
|
||||
this.get('backendController').set('preferAdvancedEdit', bool);
|
||||
|
@ -1,6 +1,6 @@
|
||||
import Secret from './secret';
|
||||
import DS from 'ember-data';
|
||||
import { bool } from '@ember/object/computed';
|
||||
import { alias, bool } from '@ember/object/computed';
|
||||
|
||||
const { attr, belongsTo } = DS;
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
import DS from 'ember-data';
|
||||
import { computed } from '@ember/object';
|
||||
import { match } from '@ember/object/computed';
|
||||
import { expandAttributeMeta } from 'vault/utils/field-to-attrs';
|
||||
|
||||
const { attr, hasMany, belongsTo, Model } = DS;
|
||||
|
||||
@ -11,7 +13,18 @@ export default Model.extend({
|
||||
updatedTime: attr(),
|
||||
currentVersion: attr('number'),
|
||||
oldestVersion: attr('number'),
|
||||
maxVersions: attr('number'),
|
||||
casRequired: attr('boolean'),
|
||||
maxVersions: attr('number', {
|
||||
defaultValue: 10,
|
||||
label: 'Maximum Number of Versions',
|
||||
}),
|
||||
casRequired: attr('boolean', {
|
||||
defaultValue: false,
|
||||
label: 'Require Check and Set',
|
||||
helpText:
|
||||
'Writes will only be allowed if the key’s current version matches the version specified in the cas parameter',
|
||||
}),
|
||||
isFolder: match('id', /\/$/),
|
||||
fields: computed(function() {
|
||||
return expandAttributeMeta(this, ['maxVersions', 'casRequired']);
|
||||
}),
|
||||
});
|
||||
|
@ -73,6 +73,7 @@ export default Route.extend(UnloadModelRoute, {
|
||||
return hash({
|
||||
secret: this.store.queryRecord(modelType, { id: secret, backend }).then(resp => {
|
||||
if (modelType === 'secret-v2') {
|
||||
let backendModel = this.modelFor('vault.cluster.secrets.backend', backend);
|
||||
let targetVersion = parseInt(params.version || resp.currentVersion, 10);
|
||||
let version = resp.versions.findBy('version', targetVersion);
|
||||
// 404 if there's no version
|
||||
@ -81,6 +82,7 @@ export default Route.extend(UnloadModelRoute, {
|
||||
set(error, 'httpStatus', 404);
|
||||
throw error;
|
||||
}
|
||||
resp.set('engine', backendModel);
|
||||
|
||||
return version.reload().then(() => {
|
||||
resp.set('selectedVersion', version);
|
||||
@ -136,14 +138,17 @@ export default Route.extend(UnloadModelRoute, {
|
||||
},
|
||||
|
||||
willTransition(transition) {
|
||||
if (this.get('hasChanges')) {
|
||||
let model = this.controller.model;
|
||||
let version = model.get('selectedVersion');
|
||||
debugger; //eslint-disable-line
|
||||
if (model.hasDirtyAttributes || (version && version.hasDirtyAttributes)) {
|
||||
if (
|
||||
window.confirm(
|
||||
'You have unsaved changes. Navigating away will discard these changes. Are you sure you want to discard your changes?'
|
||||
)
|
||||
) {
|
||||
version && version.rollbackAttributes();
|
||||
this.unloadModel();
|
||||
this.set('hasChanges', false);
|
||||
return true;
|
||||
} else {
|
||||
transition.abort();
|
||||
@ -152,9 +157,5 @@ export default Route.extend(UnloadModelRoute, {
|
||||
}
|
||||
return this._super(...arguments);
|
||||
},
|
||||
|
||||
hasDataChanges(hasChanges) {
|
||||
this.set('hasChanges', hasChanges);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -5,7 +5,6 @@
|
||||
mode=mode
|
||||
root=backendCrumb
|
||||
capabilities=capabilities
|
||||
onDataChange=(action "hasChanges")
|
||||
onRefresh=(action "refresh")
|
||||
onToggleAdvancedEdit=(action "toggleAdvancedEdit")
|
||||
initialKey=initialKey
|
||||
|
Loading…
Reference in New Issue
Block a user