const db = require('../database.js'); const TABLE_NAME = "accountConfig"; function AccountConfigManager() { } AccountConfigManager.prototype.defaultForAccount = function(id, cb) { var self = this; db.database.queryFirst(TABLE_NAME, { accountId: id, serviceId: null, deviceId: null }, (err, result) => { cb(result ? self.fromDb(result) : null); }); }; AccountConfigManager.prototype.fromAccountId = function(id, cb) { var self = this; db.database.query(TABLE_NAME, { accountId: id }, (err, result) => { if (!result) cb(null); let accConfigs = []; result.forEach((res) => { accConfigs.push(self.fromDb(res)); }); cb(accConfigs); }); }; AccountConfigManager.prototype.addToConfig = function(accountId, service, device, newConfig, now, cb) { var self = this; db.database.query(TABLE_NAME, { accountId: accountId }, (err, result) => { // Lazy create config for [ service, device ] if (result) for (var i =0, nbResults = result.length; i < nbResults; i++) { if (result[i].serviceId === service && result[i].deviceId === device) { let conf = self.fromDb(result[i]); conf.merge(newConfig, now); self.save(conf, cb); return; } } let conf = new AccountConfigWrapper(); conf.accountId = accountId; conf.serviceId = service; conf.deviceId = device; conf.merge(newConfig, now); self.save(conf, cb); }); }; AccountConfigManager.prototype.fromAccountIdAndVersion = function(id, v, cb) { var self = this; db.database.query(TABLE_NAME, { accountId: id }, (err, result) => { if (!result) cb(null); for (var i =0, nbConfig = result.length; i < nbConfig; i++) { if (result[i].modified > v) { var configs = []; for (i =0; i < nbConfig; i++) { configs.push(self.fromDb(result[i])); } cb(configs); return; } } cb(null); }); }; AccountConfigManager.prototype.newConfigFor = function(account) { var conf = new AccountConfigWrapper(); conf.dirty = true; conf.accountId = account.id; return conf; }; AccountConfig.prototype.addService = function(serviceType, serviceName, serviceId) { if (!this.services[serviceType]) this.services[serviceType] = {}; this.services[serviceType][serviceId] = serviceName; }; AccountConfig.prototype.merge = function(configBlob) { let modified = false; if (configBlob["emojiProvider"] !== undefined && configBlob["emojiProvider"] !== this.emojiProvider) { this.emojiProvider = configBlob["emojiProvider"]; modified = true; } if (configBlob["displayAvatar"] !== undefined && configBlob["displayAvatar"] !== this.displayAvatar) { this.displayAvatar = configBlob["displayAvatar"]; modified = true; } return modified; }; AccountConfigManager.prototype.fromId = function(id, cb) { var self = this; db.database.queryFirst(TABLE_NAME, { id: id }, (err, result) => { cb(self.fromDb(result)); }); }; AccountConfigManager.prototype.fromDb = function(dbResult) { if (!dbResult) return null; return new AccountConfigWrapper(dbResult); }; function AccountConfigWrapper(dbResult) { this.id; this.accountId; this.serviceId; // Can be null, or a serviceId this.deviceId; // Can be null, or a deviceId this.config = new AccountConfig(); this.modified; // modified ts if (dbResult) { this.id = dbResult.id; this.accountId = dbResult.accountId; this.serviceId = dbResult.serviceId; this.deviceId = dbResult.deviceId; this.config.fromDb(dbResult.config); this.modified = dbResult.modified; this.dirty = false; } else { this.id = null; this.accountId = null; this.serviceId = null; this.deviceId = null; this.modified = Date.now(); this.dirty = true; } } AccountConfigWrapper.prototype.toDb = function() { return { accountId: this.accountId, serviceId: this.serviceId, deviceId: this.deviceId, config: this.config.toDb(), modified: this.modified }; }; AccountConfigWrapper.prototype.merge = function(configBlob, now) { if (this.config.merge(configBlob)) { this.edit(now); return true; } return false; }; AccountConfigManager.prototype.save = function(account, cb) { if (!account.id) { // insert and save id var data = account.toDb(); data.id = null; db.database.insert(TABLE_NAME, data, (newId) => { account.id = newId; account.dirty = false; if (cb) cb(account); }); } else if (account.dirty) { // update db.database.update(TABLE_NAME, account.id, account.toDb(), () => { account.dirty = false; if (cb) cb(account); }); } else { // not changed if (cb) cb(account); } }; AccountConfigWrapper.prototype.expose = function() { return { service: this.serviceId, device: this.deviceId, config: this.config.toDb() }; }; AccountConfigWrapper.prototype.edit = function(now) { this.dirty = true; this.modified = Math.max(this.modified, now || Date.now()); return this; }; function AccountConfig() { this.services = {}; } AccountConfig.prototype.toDb = function() { return JSON.stringify({ services: this.services, emojiProvider: this.emojiProvider, displayAvatar: this.displayAvatar }); }; AccountConfig.prototype.fromDb = function(dbObj) { dbObj = JSON.parse(dbObj); this.services = dbObj.services || []; this.emojiProvider = dbObj.emojiProvider; this.displayAvatar = dbObj.displayAvatar; }; module.exports.accountConfigManager = new AccountConfigManager(); module.exports.updateTable = function(dbObject, currentVersion, cb) { if (!currentVersion) { console.info("Creating table " +TABLE_NAME); dbObject.run('CREATE TABLE IF NOT EXISTS `' +TABLE_NAME +'` (' +"`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," +"`accountId` STRING NOT NULL," +"`serviceId` STRING," +"`deviceId` STRING," +"`config` STRING NOT NULL," +"`modified` INT NOT NULL" +');CREATE INDEX accconfigbyaccount ON ' +TABLE_NAME +'(accountId); CREATE UNIQUE INDEX accconfigUniq ON ' +TABLE_NAME +'(accountId, serviceId, deviceId)', cb); //TODO permanent login token array } else { cb(null); } };