Refactors most controllers and directives into classes for more organized and maintainable code
This commit is contained in:
241
app/assets/javascripts/services/storageManager.js
Normal file
241
app/assets/javascripts/services/storageManager.js
Normal file
@@ -0,0 +1,241 @@
|
||||
import { protocolManager, SNEncryptedStorage, SFStorageManager , SFItemParams } from 'snjs';
|
||||
|
||||
export class MemoryStorage {
|
||||
constructor() {
|
||||
this.memory = {};
|
||||
}
|
||||
|
||||
getItem(key) {
|
||||
return this.memory[key] || null;
|
||||
}
|
||||
|
||||
getItemSync(key) {
|
||||
return this.getItem(key);
|
||||
}
|
||||
|
||||
get length() {
|
||||
return Object.keys(this.memory).length;
|
||||
}
|
||||
|
||||
setItem(key, value) {
|
||||
this.memory[key] = value;
|
||||
}
|
||||
|
||||
removeItem(key) {
|
||||
delete this.memory[key];
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.memory = {};
|
||||
}
|
||||
|
||||
keys() {
|
||||
return Object.keys(this.memory);
|
||||
}
|
||||
|
||||
key(index) {
|
||||
return Object.keys(this.memory)[index];
|
||||
}
|
||||
}
|
||||
|
||||
export class StorageManager extends SFStorageManager {
|
||||
|
||||
/* @ngInject */
|
||||
constructor(dbManager, alertManager) {
|
||||
super();
|
||||
this.dbManager = dbManager;
|
||||
this.alertManager = alertManager;
|
||||
}
|
||||
|
||||
initialize(hasPasscode, ephemeral) {
|
||||
if(hasPasscode) {
|
||||
// We don't want to save anything in fixed storage except for actual item data (in IndexedDB)
|
||||
this.storage = this.memoryStorage;
|
||||
this.itemsStorageMode = StorageManager.FixedEncrypted;
|
||||
} else if(ephemeral) {
|
||||
// We don't want to save anything in fixed storage as well as IndexedDB
|
||||
this.storage = this.memoryStorage;
|
||||
this.itemsStorageMode = StorageManager.Ephemeral;
|
||||
} else {
|
||||
this.storage = localStorage;
|
||||
this.itemsStorageMode = StorageManager.Fixed;
|
||||
}
|
||||
|
||||
this.modelStorageMode = ephemeral ? StorageManager.Ephemeral : StorageManager.Fixed;
|
||||
}
|
||||
|
||||
get memoryStorage() {
|
||||
if(!this._memoryStorage) {
|
||||
this._memoryStorage = new MemoryStorage();
|
||||
}
|
||||
return this._memoryStorage;
|
||||
}
|
||||
|
||||
setItemsMode(mode, force) {
|
||||
var newStorage = this.getVault(mode);
|
||||
if(newStorage !== this.storage || mode !== this.itemsStorageMode || force) {
|
||||
// transfer storages
|
||||
var length = this.storage.length;
|
||||
for(var i = 0; i < length; i++) {
|
||||
var key = this.storage.key(i);
|
||||
newStorage.setItem(key, this.storage.getItem(key));
|
||||
}
|
||||
|
||||
this.itemsStorageMode = mode;
|
||||
if(newStorage !== this.storage) {
|
||||
// Only clear if this.storage isn't the same reference as newStorage
|
||||
this.storage.clear();
|
||||
}
|
||||
this.storage = newStorage;
|
||||
|
||||
if(mode == StorageManager.FixedEncrypted) {
|
||||
this.writeEncryptedStorageToDisk();
|
||||
} else if(mode == StorageManager.Fixed) {
|
||||
// Remove encrypted storage
|
||||
this.removeItem("encryptedStorage", StorageManager.Fixed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getVault(vaultKey) {
|
||||
if(vaultKey) {
|
||||
if(vaultKey == StorageManager.Ephemeral || vaultKey == StorageManager.FixedEncrypted) {
|
||||
return this.memoryStorage;
|
||||
} else {
|
||||
return localStorage;
|
||||
}
|
||||
} else {
|
||||
return this.storage;
|
||||
}
|
||||
}
|
||||
|
||||
async setItem(key, value, vaultKey) {
|
||||
var storage = this.getVault(vaultKey);
|
||||
try {
|
||||
storage.setItem(key, value);
|
||||
} catch (e) {
|
||||
console.error("Exception while trying to setItem in StorageManager:", e);
|
||||
this.alertManager.alert({text: "The application's local storage is out of space. If you have Session History save-to-disk enabled, please disable it, and try again."});
|
||||
}
|
||||
|
||||
if(vaultKey === StorageManager.FixedEncrypted || (!vaultKey && this.itemsStorageMode === StorageManager.FixedEncrypted)) {
|
||||
return this.writeEncryptedStorageToDisk();
|
||||
}
|
||||
}
|
||||
|
||||
async getItem(key, vault) {
|
||||
return this.getItemSync(key, vault);
|
||||
}
|
||||
|
||||
getItemSync(key, vault) {
|
||||
var storage = this.getVault(vault);
|
||||
return storage.getItem(key);
|
||||
}
|
||||
|
||||
async removeItem(key, vault) {
|
||||
var storage = this.getVault(vault);
|
||||
return storage.removeItem(key);
|
||||
}
|
||||
|
||||
async clear() {
|
||||
this.memoryStorage.clear();
|
||||
localStorage.clear();
|
||||
}
|
||||
|
||||
storageAsHash() {
|
||||
var hash = {};
|
||||
var length = this.storage.length;
|
||||
for(var i = 0; i < length; i++) {
|
||||
var key = this.storage.key(i);
|
||||
hash[key] = this.storage.getItem(key)
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
setKeys(keys, authParams) {
|
||||
this.encryptedStorageKeys = keys;
|
||||
this.encryptedStorageAuthParams = authParams;
|
||||
}
|
||||
|
||||
async writeEncryptedStorageToDisk() {
|
||||
var encryptedStorage = new SNEncryptedStorage();
|
||||
// Copy over totality of current storage
|
||||
encryptedStorage.content.storage = this.storageAsHash();
|
||||
|
||||
// Save new encrypted storage in Fixed storage
|
||||
var params = new SFItemParams(encryptedStorage, this.encryptedStorageKeys, this.encryptedStorageAuthParams);
|
||||
const syncParams = await params.paramsForSync();
|
||||
this.setItem("encryptedStorage", JSON.stringify(syncParams), StorageManager.Fixed);
|
||||
}
|
||||
|
||||
async decryptStorage() {
|
||||
var stored = JSON.parse(this.getItemSync("encryptedStorage", StorageManager.Fixed));
|
||||
await protocolManager.decryptItem(stored, this.encryptedStorageKeys);
|
||||
var encryptedStorage = new SNEncryptedStorage(stored);
|
||||
|
||||
for(var key of Object.keys(encryptedStorage.content.storage)) {
|
||||
this.setItem(key, encryptedStorage.storage[key]);
|
||||
}
|
||||
}
|
||||
|
||||
hasPasscode() {
|
||||
return this.getItemSync("encryptedStorage", StorageManager.Fixed) !== null;
|
||||
}
|
||||
|
||||
bestStorageMode() {
|
||||
return this.hasPasscode() ? StorageManager.FixedEncrypted : StorageManager.Fixed;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Model Storage
|
||||
|
||||
If using ephemeral storage, we don't need to write it to anything as references will be held already by controllers
|
||||
and the global modelManager service.
|
||||
*/
|
||||
|
||||
setModelStorageMode(mode) {
|
||||
if(mode == this.modelStorageMode) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(mode == StorageManager.Ephemeral) {
|
||||
// Clear IndexedDB
|
||||
this.dbManager.clearAllModels(null);
|
||||
} else {
|
||||
// Fixed
|
||||
}
|
||||
|
||||
this.modelStorageMode = mode;
|
||||
}
|
||||
|
||||
async getAllModels() {
|
||||
if(this.modelStorageMode == StorageManager.Fixed) {
|
||||
return this.dbManager.getAllModels();
|
||||
}
|
||||
}
|
||||
|
||||
async saveModel(item) {
|
||||
return this.saveModels([item]);
|
||||
}
|
||||
|
||||
async saveModels(items, onsuccess, onerror) {
|
||||
if(this.modelStorageMode == StorageManager.Fixed) {
|
||||
return this.dbManager.saveModels(items);
|
||||
}
|
||||
}
|
||||
|
||||
async deleteModel(item) {
|
||||
if(this.modelStorageMode == StorageManager.Fixed) {
|
||||
return this.dbManager.deleteModel(item);
|
||||
}
|
||||
}
|
||||
|
||||
async clearAllModels() {
|
||||
return this.dbManager.clearAllModels();
|
||||
}
|
||||
}
|
||||
|
||||
StorageManager.FixedEncrypted = "FixedEncrypted"; // encrypted memoryStorage + localStorage persistence
|
||||
StorageManager.Ephemeral = "Ephemeral"; // memoryStorage
|
||||
StorageManager.Fixed = "Fixed"; // localStorage
|
||||
Reference in New Issue
Block a user