diff --git a/ui/app/adapters/secret-v2-version.js b/ui/app/adapters/secret-v2-version.js index 4f77992cdfec..1c9236470a9c 100644 --- a/ui/app/adapters/secret-v2-version.js +++ b/ui/app/adapters/secret-v2-version.js @@ -16,12 +16,12 @@ export default ApplicationAdapter.extend({ urlForFindRecord(id) { let [backend, path, version] = JSON.parse(id); - return this._url(backend, path) + `?version=${version}`; + let base = this._url(backend, path); + return version ? base + `?version=${version}` : base; }, urlForQueryRecord(id) { - let [backend, path, version] = JSON.parse(id); - return this._url(backend, path) + `?version=${version}`; + return this.urlForFindRecord(id); }, findRecord() { diff --git a/ui/app/components/secret-edit.js b/ui/app/components/secret-edit.js index 59b5be8788fb..fcb816f98553 100644 --- a/ui/app/components/secret-edit.js +++ b/ui/app/components/secret-edit.js @@ -109,7 +109,7 @@ export default Component.extend(FocusOnInsertMixin, { 'model.id', 'mode' ), - canDelete: alias('updatePath.canDelete'), + canDelete: alias('model.canDelete'), canEdit: alias('updatePath.canUpdate'), v2UpdatePath: maybeQueryRecord( @@ -181,19 +181,21 @@ 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 secretData = this.modelForData; let isV2 = this.isV2; - let key = model.get('path') || model.id; + let key = secretData.get('path') || secret.id; if (key.startsWith('/')) { key = key.replace(/^\/+/g, ''); - model.set(model.pathAttr, key); + secretData.set(secretData.pathAttr, key); } - return model.save().then(() => { - if (!model.isError) { - if (isV2 && Object.keys(secret.changedAttributes()).length) { + return secretData.save().then(() => { + if (!secretData.isError) { + if (isV2) { secret.set('id', key); + } + if (isV2 && Object.keys(secret.changedAttributes()).length) { // save secret metadata secret .save() @@ -296,8 +298,8 @@ export default Component.extend(FocusOnInsertMixin, { return; } - this.persistKey(key => { - this.transitionToRoute(SHOW_ROUTE, key); + this.persistKey(() => { + this.transitionToRoute(SHOW_ROUTE, this.model.id); }); }, diff --git a/ui/app/models/secret-v2.js b/ui/app/models/secret-v2.js index d68f9e43535e..5a37b4eb8876 100644 --- a/ui/app/models/secret-v2.js +++ b/ui/app/models/secret-v2.js @@ -33,6 +33,6 @@ export default Model.extend(KeyMixin, { secretPath: lazyCapabilities(apiPath`${'engineId'}/metadata/${'id'}`, 'engineId', 'id'), canEdit: alias('versionPath.canUpdate'), - canDelete: alias('secretPath.canUpdate'), + canDelete: alias('secretPath.canDelete'), canRead: alias('secretPath.canRead'), }); diff --git a/ui/app/models/secret.js b/ui/app/models/secret.js index 36fc8eeeafc9..02d5a61c4ad4 100644 --- a/ui/app/models/secret.js +++ b/ui/app/models/secret.js @@ -27,6 +27,6 @@ export default DS.Model.extend(KeyMixin, { backend: attr('string'), secretPath: lazyCapabilities(apiPath`${'backend'}/${'id'}`, 'backend', 'id'), canEdit: alias('secretPath.canUpdate'), - canDelete: alias('secretPath.canUpdate'), + canDelete: alias('secretPath.canDelete'), canRead: alias('secretPath.canRead'), }); diff --git a/ui/app/routes/vault/cluster/secrets/backend/secret-edit.js b/ui/app/routes/vault/cluster/secrets/backend/secret-edit.js index 873fc305f6bb..943ad2a54a0a 100644 --- a/ui/app/routes/vault/cluster/secrets/backend/secret-edit.js +++ b/ui/app/routes/vault/cluster/secrets/backend/secret-edit.js @@ -64,6 +64,7 @@ export default Route.extend(UnloadModelRoute, { model(params) { let { secret } = params; const { backend } = this.paramsFor('vault.cluster.secrets.backend'); + let backendModel = this.modelFor('vault.cluster.secrets.backend', backend); const modelType = this.modelType(backend, secret); if (!secret) { @@ -73,26 +74,50 @@ export default Route.extend(UnloadModelRoute, { secret = secret.replace('cert/', ''); } 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 - if (!version) { - let error = new DS.AdapterError(); - set(error, 'httpStatus', 404); - throw error; - } - resp.set('engine', backendModel); + secret: this.store + .queryRecord(modelType, { id: secret, backend }) + .then(secretModel => { + if (modelType === 'secret-v2') { + let targetVersion = parseInt(params.version || secretModel.currentVersion, 10); + let version = secretModel.versions.findBy('version', targetVersion); + // 404 if there's no version + if (!version) { + let error = new DS.AdapterError(); + set(error, 'httpStatus', 404); + throw error; + } + secretModel.set('engine', backendModel); - return version.reload().then(() => { - resp.set('selectedVersion', version); - return resp; - }); - } - return resp; - }), + return version.reload().then(() => { + secretModel.set('selectedVersion', version); + return secretModel; + }); + } + return secretModel; + }) + .catch(err => { + //don't have access to the metadata, so we'll make + //a stub metadata model and try to load the version + if (modelType === 'secret-v2' && err.httpStatus === 403) { + let secretModel = this.store.createRecord('secret-v2'); + secretModel.setProperties({ + engine: backendModel, + id: secret, + // so we know it's a stub model and won't be saving it + // because we don't have access to that endpoint + isStub: true, + }); + let targetVersion = params.version ? parseInt(params.version, 10) : null; + let versionId = targetVersion ? [backend, secret, targetVersion] : [backend, secret]; + return this.store + .findRecord('secret-v2-version', JSON.stringify(versionId), { reload: true }) + .then(versionModel => { + secretModel.set('selectedVersion', versionModel); + return secretModel; + }); + } + throw err; + }), capabilities: this.capabilities(secret), }); }, diff --git a/ui/app/serializers/secret-v2-version.js b/ui/app/serializers/secret-v2-version.js index 61a001821ff6..18e23c44dfd9 100644 --- a/ui/app/serializers/secret-v2-version.js +++ b/ui/app/serializers/secret-v2-version.js @@ -17,7 +17,8 @@ export default ApplicationSerializer.extend({ }, serialize(snapshot) { let secret = snapshot.belongsTo('secret'); - let version = secret.attr('currentVersion') || 0; + let version = secret.record.isStub ? snapshot.attr('version') : secret.attr('currentVersion'); + version = version || 0; return { data: snapshot.attr('secretData'), options: { diff --git a/ui/app/templates/components/secret-edit-display.hbs b/ui/app/templates/components/secret-edit-display.hbs index 627982c55ef1..e6c4ebfe1a81 100644 --- a/ui/app/templates/components/secret-edit-display.hbs +++ b/ui/app/templates/components/secret-edit-display.hbs @@ -1,5 +1,5 @@ - {{#if (and (or @model.isNew @canEditV2Secret) @isV2)}} -
+ {{#if (and (or @model.isNew @canEditV2Secret) @isV2 (not @model.isStub))}} +
diff --git a/ui/app/templates/partials/secret-form-edit.hbs b/ui/app/templates/partials/secret-form-edit.hbs index c8b7cda98a4c..7c4c0511213f 100644 --- a/ui/app/templates/partials/secret-form-edit.hbs +++ b/ui/app/templates/partials/secret-form-edit.hbs @@ -2,7 +2,7 @@
- {{#if (not-eq model.selectedVersion.version model.currentVersion)}} + {{#if (and (not model.isStub) (not-eq model.selectedVersion.version model.currentVersion))}}