import Backbone from 'backbone'; import kdbxweb from 'kdbxweb'; import { SettingsStore } from 'comp/settings/settings-store'; import { Links } from 'const/links'; import { SignatureVerifier } from 'util/data/signature-verifier'; import { Logger } from 'util/logger'; const PluginGallery = { logger: new Logger('plugin-gallery'), gallery: null, loading: false, loadError: null, loadPlugins() { if (this.gallery) { return Promise.resolve(this.gallery); } this.loading = true; this.loadError = false; const ts = this.logger.ts(); return new Promise(resolve => { this.logger.debug('Loading plugins...'); const xhr = new XMLHttpRequest(); xhr.open('GET', Links.Plugins + '/plugins.json?_=' + Date.now()); xhr.responseType = 'json'; xhr.send(); xhr.addEventListener('load', () => { const data = xhr.response; resolve(data); }); xhr.addEventListener('error', () => { this.logger.error('Network error loading plugins'); resolve(); }); }).then(data => { return this.verifySignature(data).then(gallery => { this.loading = false; this.loadError = !gallery; if (gallery) { this.logger.debug( `Loaded ${gallery.plugins.length} plugins`, this.logger.ts(ts) ); this.gallery = gallery; this.saveGallery(gallery); } Backbone.trigger('plugin-gallery-load-complete'); return gallery; }); }); }, verifySignature(gallery) { const dataToVerify = JSON.stringify(gallery, null, 2).replace(gallery.signature, ''); return SignatureVerifier.verify( kdbxweb.ByteUtils.stringToBytes(dataToVerify), gallery.signature ) .then(isValid => { if (isValid) { return gallery; } this.logger.error('JSON signature invalid'); }) .catch(e => { this.logger.error('Error verifying plugins signature', e); }); }, getCachedGallery() { const ts = this.logger.ts(); return SettingsStore.load('plugin-gallery').then(data => { if (data) { return this.verifySignature(data).then(gallery => { this.logger.debug(`Loaded cached plugin gallery`, this.logger.ts(ts)); return gallery; }); } }); }, saveGallery(data) { SettingsStore.save('plugin-gallery', data); } }; export { PluginGallery };