import Ember from 'ember'; import DS from 'ember-data'; import clamp from 'vault/utils/clamp'; import { queryRecord } from 'ember-computed-query'; const { attr } = DS; const { computed, get, set } = Ember; const ACTION_VALUES = { encrypt: 'supportsEncryption', decrypt: 'supportsDecryption', datakey: 'supportsEncryption', rewrap: 'supportsEncryption', sign: 'supportsSigning', hmac: true, verify: true, export: 'exportable', }; export default DS.Model.extend({ type: attr('string', { defaultValue: 'aes256-gcm96', }), name: attr('string'), deletionAllowed: attr('boolean'), derived: attr('boolean'), exportable: attr('boolean'), minDecryptionVersion: attr('number', { defaultValue: 1, }), minEncryptionVersion: attr('number', { defaultValue: 0, }), latestVersion: attr('number'), keys: attr('object'), convergentEncryption: attr('boolean'), convergentEncryptionVersion: attr('number'), supportsSigning: attr('boolean'), supportsEncryption: attr('boolean'), supportsDecryption: attr('boolean'), supportsDerivation: attr('boolean'), setConvergentEncryption(val) { if (val === true) { set(this, 'derived', val); } set(this, 'convergentEncryption', val); }, setDerived(val) { if (val === false) { set(this, 'convergentEncryption', val); } set(this, 'derived', val); }, supportedActions: computed('type', function() { return Object.keys(ACTION_VALUES).filter(name => { const isSupported = ACTION_VALUES[name]; if (typeof isSupported === 'boolean') { return isSupported; } return get(this, isSupported); }); }), canDelete: computed('deletionAllowed', 'lastLoadTS', function() { const deleteAttrChanged = Boolean(this.changedAttributes().deletionAllowed); return get(this, 'deletionAllowed') && deleteAttrChanged === false; }), keyVersions: computed('validKeyVersions', function() { let maxVersion = Math.max(...get(this, 'validKeyVersions')); let versions = []; while (maxVersion > 0) { versions.unshift(maxVersion); maxVersion--; } return versions; }), encryptionKeyVersions: computed('keyVerisons', 'minDecryptionVersion', 'latestVersion', function() { const { keyVersions, minDecryptionVersion } = this.getProperties('keyVersions', 'minDecryptionVersion'); return keyVersions .filter(version => { return version >= minDecryptionVersion; }) .reverse(); }), keysForEncryption: computed('minEncryptionVersion', 'latestVersion', function() { let { minEncryptionVersion, latestVersion } = this.getProperties('minEncryptionVersion', 'latestVersion'); let minVersion = clamp(minEncryptionVersion - 1, 0, latestVersion); let versions = []; while (latestVersion > minVersion) { versions.push(latestVersion); latestVersion--; } return versions; }), validKeyVersions: computed('keys', function() { return Object.keys(get(this, 'keys')); }), exportKeyTypes: computed('exportable', 'type', function() { let types = ['hmac']; if (this.get('supportsSigning')) { types.unshift('signing'); } if (this.get('supportsEncryption')) { types.unshift('encryption'); } return types; }), backend: attr('string', { readOnly: true, }), rotatePath: queryRecord( 'capabilities', context => { const { backend, id } = context.getProperties('backend', 'id'); if (!backend && id) { return; } return { id: `${backend}/keys/${id}/rotate`, }; }, 'id', 'backend' ), canRotate: computed.alias('rotatePath.canUpdate'), });