Source: encrypt/sqlite3-group-manager-db.js

  1. /**
  2. * Copyright (C) 2015-2018 Regents of the University of California.
  3. * @author: Jeff Thompson <jefft0@remap.ucla.edu>
  4. * @author: From ndn-group-encrypt src/group-manager-db https://github.com/named-data/ndn-group-encrypt
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Lesser General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. * A copy of the GNU Lesser General Public License is in the file COPYING.
  19. */
  20. /** @ignore */
  21. var Schedule = require('./schedule.js').Schedule; /** @ignore */
  22. var Blob = require('../util/blob.js').Blob; /** @ignore */
  23. var Sqlite3Promise = require('../util/sqlite3-promise.js').Sqlite3Promise; /** @ignore */
  24. var Name = require('../name.js').Name; /** @ignore */
  25. var TlvWireFormat = require('../encoding/tlv-wire-format').TlvWireFormat; /** @ignore */
  26. var GroupManagerDb = require('./group-manager-db.js').GroupManagerDb;
  27. /**
  28. * Sqlite3GroupManagerDb extends GroupManagerDb to implement the storage of
  29. * data used by the GroupManager using the Node.js sqlite3 module.
  30. * Create a Sqlite3GroupManagerDb to use the given SQLite3 file.
  31. * @param {string} databaseFilePath The path of the SQLite file.
  32. * @throws GroupManagerDb.Error for a database error.
  33. * @note This class is an experimental feature. The API may change.
  34. * @constructor
  35. */
  36. var Sqlite3GroupManagerDb = function Sqlite3GroupManagerDb(databaseFilePath)
  37. {
  38. // Call the base constructor.
  39. GroupManagerDb.call(this);
  40. this.database_ = new Sqlite3Promise
  41. (databaseFilePath, Sqlite3GroupManagerDb.initializeDatabasePromise_);
  42. // The map key is the E-KEY name URI string. The value is the private key Blob.
  43. // (Use a string because we can't use the Name object as the key in JavaScript.)
  44. this.privateKeyBase_ = {};
  45. };
  46. Sqlite3GroupManagerDb.prototype = new GroupManagerDb();
  47. Sqlite3GroupManagerDb.prototype.name = "Sqlite3GroupManagerDb";
  48. exports.Sqlite3GroupManagerDb = Sqlite3GroupManagerDb;
  49. ////////////////////////////////////////////////////// Schedule management.
  50. /**
  51. * Check if there is a schedule with the given name.
  52. * @param {string} name The name of the schedule.
  53. * @param {boolean} useSync (optional) If true then return a rejected promise
  54. * since this only supports async code.
  55. * @return {Promise} A promise that returns true if there is a schedule (else
  56. * false), or that is rejected with GroupManagerDb.Error for a database error.
  57. */
  58. Sqlite3GroupManagerDb.prototype.hasSchedulePromise = function(name, useSync)
  59. {
  60. if (useSync)
  61. return Promise.reject(new GroupManagerDb.Error(new Error
  62. ("Sqlite3GroupManagerDb.hasSchedulePromise is only supported for async")));
  63. return this.getPromise_
  64. ("SELECT schedule_id FROM schedules where schedule_name=?", name)
  65. .then(function(row) {
  66. if (row)
  67. return Promise.resolve(true);
  68. else
  69. return Promise.resolve(false);
  70. });
  71. };
  72. /**
  73. * List all the names of the schedules.
  74. * @param {boolean} useSync (optional) If true then return a rejected promise
  75. * since this only supports async code.
  76. * @return {Promise} A promise that returns a new array of string with the names
  77. * of all schedules, or that is rejected with GroupManagerDb.Error for a
  78. * database error.
  79. */
  80. Sqlite3GroupManagerDb.prototype.listAllScheduleNamesPromise = function(useSync)
  81. {
  82. if (useSync)
  83. return Promise.reject(new GroupManagerDb.Error(new Error
  84. ("Sqlite3GroupManagerDb.listAllScheduleNamesPromise is only supported for async")));
  85. var list = [];
  86. return this.eachPromise_
  87. ("SELECT schedule_name FROM schedules", [], function(err, row) {
  88. list.push(row.schedule_name);
  89. })
  90. .then(function() {
  91. return Promise.resolve(list);
  92. });
  93. };
  94. /**
  95. * Get a schedule with the given name.
  96. * @param {string} name The name of the schedule.
  97. * @param {boolean} useSync (optional) If true then return a rejected promise
  98. * since this only supports async code.
  99. * @return {Promise} A promise that returns a new Schedule object, or that is
  100. * rejected with GroupManagerDb.Error if the schedule does not exist or other
  101. * database error.
  102. */
  103. Sqlite3GroupManagerDb.prototype.getSchedulePromise = function(name, useSync)
  104. {
  105. if (useSync)
  106. return Promise.reject(new GroupManagerDb.Error(new Error
  107. ("Sqlite3GroupManagerDb.getSchedulePromise is only supported for async")));
  108. return this.getPromise_
  109. ("SELECT schedule FROM schedules WHERE schedule_name=?", name)
  110. .then(function(row) {
  111. if (row) {
  112. try {
  113. var schedule = new Schedule();
  114. schedule.wireDecode(new Blob(row.schedule, false));
  115. return Promise.resolve(schedule);
  116. } catch (ex) {
  117. // We don't expect this to happen.
  118. return Promise.reject(new GroupManagerDb.Error(new Error
  119. ("Sqlite3GroupManagerDb.getSchedulePromise: Error decoding schedule: " + ex)));
  120. }
  121. }
  122. else
  123. return Promise.reject(new GroupManagerDb.Error(new Error
  124. ("Sqlite3GroupManagerDb.getSchedulePromise: Cannot get the result from the database")));
  125. });
  126. };
  127. /**
  128. * For each member using the given schedule, get the name and public key DER
  129. * of the member's key.
  130. * @param {string} name The name of the schedule.
  131. * @param {boolean} useSync (optional) If true then return a rejected promise
  132. * since this only supports async code.
  133. * @return {Promise} A promise that returns a new array of object (where
  134. * "keyName" is the Name of the public key and "publicKey" is the Blob of the
  135. * public key DER), or that is rejected with GroupManagerDb.Error for a database
  136. * error. Note that the member's identity name is keyName.getPrefix(-1). If the
  137. * schedule name is not found, the list is empty.
  138. */
  139. Sqlite3GroupManagerDb.prototype.getScheduleMembersPromise = function
  140. (name, useSync)
  141. {
  142. if (useSync)
  143. return Promise.reject(new GroupManagerDb.Error(new Error
  144. ("Sqlite3GroupManagerDb.getScheduleMembersPromise is only supported for async")));
  145. var list = [];
  146. var onRowError = null;
  147. return this.eachPromise_
  148. ("SELECT key_name, pubkey " +
  149. "FROM members JOIN schedules " +
  150. "ON members.schedule_id=schedules.schedule_id " +
  151. "WHERE schedule_name=?", name, function(err, row) {
  152. try {
  153. var keyName = new Name();
  154. keyName.wireDecode(new Blob(row.key_name, false), TlvWireFormat.get());
  155. list.push({ keyName: keyName, publicKey: new Blob(row.pubkey, false) });
  156. } catch (ex) {
  157. // We don't expect this to happen.
  158. onRowError = new GroupManagerDb.Error(new Error
  159. ("Sqlite3GroupManagerDb.getScheduleMembersPromise: Error decoding name: " + ex));
  160. }
  161. })
  162. .then(function() {
  163. if (onRowError)
  164. return Promise.reject(onRowError);
  165. else
  166. return Promise.resolve(list);
  167. });
  168. };
  169. /**
  170. * Add a schedule with the given name.
  171. * @param {string} name The name of the schedule. The name cannot be empty.
  172. * @param {Schedule} schedule The Schedule to add.
  173. * @param {boolean} useSync (optional) If true then return a rejected promise
  174. * since this only supports async code.
  175. * @return {Promise} A promise that fulfills when the schedule is added, or that
  176. * is rejected with GroupManagerDb.Error if a schedule with the same name
  177. * already exists, if the name is empty, or other database error.
  178. */
  179. Sqlite3GroupManagerDb.prototype.addSchedulePromise = function
  180. (name, schedule, useSync)
  181. {
  182. if (useSync)
  183. return Promise.reject(new GroupManagerDb.Error(new Error
  184. ("Sqlite3GroupManagerDb.addSchedulePromise is only supported for async")));
  185. if (name.length == 0)
  186. return Promise.reject(new GroupManagerDb.Error
  187. ("Sqlite3GroupManagerDb.addSchedulePromise: The schedule name cannot be empty"));
  188. return this.runPromise_
  189. ("INSERT INTO schedules (schedule_name, schedule) values (?, ?)",
  190. [name, schedule.wireEncode().buf()]);
  191. };
  192. /**
  193. * Delete the schedule with the given name. Also delete members which use this
  194. * schedule. If there is no schedule with the name, then do nothing.
  195. * @param {string} name The name of the schedule.
  196. * @param {boolean} useSync (optional) If true then return a rejected promise
  197. * since this only supports async code.
  198. * @return {Promise} A promise that fulfills when the schedule is deleted (or
  199. * there is no such schedule), or that is rejected with GroupManagerDb.Error for
  200. * a database error.
  201. */
  202. Sqlite3GroupManagerDb.prototype.deleteSchedulePromise = function
  203. (name, useSync)
  204. {
  205. if (useSync)
  206. return Promise.reject(new GroupManagerDb.Error(new Error
  207. ("Sqlite3GroupManagerDb.deleteSchedulePromise is only supported for async")));
  208. return this.runPromise_
  209. ("DELETE FROM schedules WHERE schedule_name=?", name);
  210. };
  211. /**
  212. * Rename a schedule with oldName to newName.
  213. * @param {string} oldName The name of the schedule to be renamed.
  214. * @param {string} newName The new name of the schedule. The name cannot be empty.
  215. * @param {boolean} useSync (optional) If true then return a rejected promise
  216. * since this only supports async code.
  217. * @return {Promise} A promise that fulfills when the schedule is renamed, or
  218. * that is rejected with GroupManagerDb.Error if a schedule with newName already
  219. * exists, if the schedule with oldName does not exist, if newName is empty, or
  220. * other database error.
  221. */
  222. Sqlite3GroupManagerDb.prototype.renameSchedulePromise = function
  223. (oldName, newName, useSync)
  224. {
  225. if (useSync)
  226. return Promise.reject(new GroupManagerDb.Error(new Error
  227. ("Sqlite3GroupManagerDb.renameSchedulePromise is only supported for async")));
  228. if (newName.length == 0)
  229. return Promise.reject(new GroupManagerDb.Error(new Error
  230. ("Sqlite3GroupManagerDb.renameSchedule: The schedule newName cannot be empty")));
  231. return this.runPromise_
  232. ("UPDATE schedules SET schedule_name=? WHERE schedule_name=?",
  233. [newName, oldName]);
  234. };
  235. /**
  236. * Update the schedule with name and replace the old object with the given
  237. * schedule. Otherwise, if no schedule with name exists, a new schedule
  238. * with name and the given schedule will be added to database.
  239. * @param {string} name The name of the schedule. The name cannot be empty.
  240. * @param {Schedule} schedule The Schedule to update or add.
  241. * @param {boolean} useSync (optional) If true then return a rejected promise
  242. * since this only supports async code.
  243. * @return {Promise} A promise that fulfills when the schedule is updated, or
  244. * that is rejected with GroupManagerDb.Error if the name is empty, or other
  245. * database error.
  246. */
  247. Sqlite3GroupManagerDb.prototype.updateSchedulePromise = function
  248. (name, schedule, useSync)
  249. {
  250. if (useSync)
  251. return Promise.reject(new GroupManagerDb.Error(new Error
  252. ("Sqlite3GroupManagerDb.updateSchedulePromise is only supported for async")));
  253. var thisManager = this;
  254. return this.hasSchedulePromise(name)
  255. .then(function(hasSchedule) {
  256. if (!hasSchedule)
  257. return thisManager.addSchedulePromise(name, schedule);
  258. return thisManager.runPromise_
  259. ("UPDATE schedules SET schedule=? WHERE schedule_name=?",
  260. [schedule.wireEncode().buf(), name]);
  261. });
  262. };
  263. ////////////////////////////////////////////////////// Member management.
  264. /**
  265. * Check if there is a member with the given identity name.
  266. * @param {Name} identity The member's identity name.
  267. * @param {boolean} useSync (optional) If true then return a rejected promise
  268. * since this only supports async code.
  269. * @return {Promise} A promise that returns true if there is a member (else
  270. * false), or that is rejected with GroupManagerDb.Error for a database error.
  271. */
  272. Sqlite3GroupManagerDb.prototype.hasMemberPromise = function(identity, useSync)
  273. {
  274. if (useSync)
  275. return Promise.reject(new GroupManagerDb.Error(new Error
  276. ("Sqlite3GroupManagerDb.hasMemberPromise is only supported for async")));
  277. return this.getPromise_
  278. ("SELECT member_id FROM members WHERE member_name=?",
  279. identity.wireEncode(TlvWireFormat.get()).buf())
  280. .then(function(row) {
  281. if (row)
  282. return Promise.resolve(true);
  283. else
  284. return Promise.resolve(false);
  285. });
  286. };
  287. /**
  288. * List all the members.
  289. * @param {boolean} useSync (optional) If true then return a rejected promise
  290. * since this only supports async code.
  291. * @return {Promise} A promise that returns a new array of Name with the names
  292. * of all members, or that is rejected with GroupManagerDb.Error for a
  293. * database error.
  294. */
  295. Sqlite3GroupManagerDb.prototype.listAllMembersPromise = function(useSync)
  296. {
  297. if (useSync)
  298. return Promise.reject(new GroupManagerDb.Error(new Error
  299. ("Sqlite3GroupManagerDb.listAllMembersPromise is only supported for async")));
  300. var list = [];
  301. var onRowError = null;
  302. return this.eachPromise_
  303. ("SELECT member_name FROM members", [], function(err, row) {
  304. try {
  305. var identity = new Name();
  306. identity.wireDecode(new Blob(row.member_name, false), TlvWireFormat.get());
  307. list.push(identity);
  308. } catch (ex) {
  309. // We don't expect this to happen.
  310. onRowError = new GroupManagerDb.Error(new Error
  311. ("Sqlite3GroupManagerDb.listAllMembersPromise: Error decoding name: " + ex));
  312. }
  313. })
  314. .then(function() {
  315. if (onRowError)
  316. return Promise.reject(onRowError);
  317. else
  318. return Promise.resolve(list);
  319. });
  320. };
  321. /**
  322. * Get the name of the schedule for the given member's identity name.
  323. * @param {Name} identity The member's identity name.
  324. * @param {boolean} useSync (optional) If true then return a rejected promise
  325. * since this only supports async code.
  326. * @return {Promise} A promise that returns the string schedule name, or that is
  327. * rejected with GroupManagerDb.Error if there's no member with the given
  328. * identity name in the database, or other database error.
  329. */
  330. Sqlite3GroupManagerDb.prototype.getMemberSchedulePromise = function
  331. (identity, useSync)
  332. {
  333. if (useSync)
  334. return Promise.reject(new GroupManagerDb.Error(new Error
  335. ("Sqlite3GroupManagerDb.getMemberSchedulePromise is only supported for async")));
  336. return this.getPromise_
  337. ("SELECT schedule_name " +
  338. "FROM schedules JOIN members " +
  339. "ON schedules.schedule_id = members.schedule_id " +
  340. "WHERE member_name=?",
  341. identity.wireEncode(TlvWireFormat.get()).buf())
  342. .then(function(row) {
  343. if (row)
  344. return Promise.resolve(row.schedule_name);
  345. else
  346. return Promise.reject(new GroupManagerDb.Error(new Error
  347. ("Sqlite3GroupManagerDb.getMemberSchedulePromise: Cannot get the result from the database")));
  348. });
  349. };
  350. /**
  351. * Add a new member with the given key named keyName into a schedule named
  352. * scheduleName. The member's identity name is keyName.getPrefix(-1).
  353. * @param {string} scheduleName The schedule name.
  354. * @param {Name} keyName The name of the key.
  355. * @param {Blob} key A Blob of the public key DER.
  356. * @param {boolean} useSync (optional) If true then return a rejected promise
  357. * since this only supports async code.
  358. * @return {Promise} A promise that fulfills when the member is added, or that
  359. * is rejected with GroupManagerDb.Error if there's no schedule named
  360. * scheduleName, if the member's identity name already exists, or other database
  361. * error.
  362. */
  363. Sqlite3GroupManagerDb.prototype.addMemberPromise = function
  364. (scheduleName, keyName, key, useSync)
  365. {
  366. if (useSync)
  367. return Promise.reject(new GroupManagerDb.Error(new Error
  368. ("Sqlite3GroupManagerDb.addMemberPromise is only supported for async")));
  369. var thisManager = this;
  370. return this.getScheduleIdPromise_(scheduleName)
  371. .then(function(scheduleId) {
  372. if (scheduleId == -1)
  373. return Promise.reject(new GroupManagerDb.Error(new Error
  374. ("Sqlite3GroupManagerDb.addMemberPromise: The schedule does not exist")));
  375. // Needs to be changed in the future.
  376. var memberName = keyName.getPrefix(-1);
  377. return thisManager.runPromise_
  378. ("INSERT INTO members(schedule_id, member_name, key_name, pubkey) " +
  379. "values (?, ?, ?, ?)",
  380. [scheduleId, memberName.wireEncode(TlvWireFormat.get()).buf(),
  381. keyName.wireEncode(TlvWireFormat.get()).buf(), key.buf()]);
  382. });
  383. };
  384. /**
  385. * Change the name of the schedule for the given member's identity name.
  386. * @param {Name} identity The member's identity name.
  387. * @param {string} scheduleName The new schedule name.
  388. * @param {boolean} useSync (optional) If true then return a rejected promise
  389. * since this only supports async code.
  390. * @return {Promise} A promise that fulfills when the member is updated, or that
  391. * is rejected with GroupManagerDb.Error if there's no member with the given
  392. * identity name in the database, or there's no schedule named scheduleName, or
  393. * other database error.
  394. */
  395. Sqlite3GroupManagerDb.prototype.updateMemberSchedulePromise = function
  396. (identity, scheduleName, useSync)
  397. {
  398. if (useSync)
  399. return Promise.reject(new GroupManagerDb.Error(new Error
  400. ("Sqlite3GroupManagerDb.updateMemberSchedulePromise is only supported for async")));
  401. var thisManager = this;
  402. return this.getScheduleIdPromise_(scheduleName)
  403. .then(function(scheduleId) {
  404. if (scheduleId == -1)
  405. return Promise.reject(new GroupManagerDb.Error(new Error
  406. ("Sqlite3GroupManagerDb.updateMemberSchedulePromise: The schedule does not exist")));
  407. return thisManager.runPromise_
  408. ("UPDATE members SET schedule_id=? WHERE member_name=?",
  409. [scheduleId, identity.wireEncode(TlvWireFormat.get()).buf()]);
  410. });
  411. };
  412. /**
  413. * Delete a member with the given identity name. If there is no member with
  414. * the identity name, then do nothing.
  415. * @param {Name} identity The member's identity name.
  416. * @param {boolean} useSync (optional) If true then return a rejected promise
  417. * since this only supports async code.
  418. * @return {Promise} A promise that fulfills when the member is deleted (or
  419. * there is no such member), or that is rejected with GroupManagerDb.Error for a
  420. * database error.
  421. */
  422. Sqlite3GroupManagerDb.prototype.deleteMemberPromise = function
  423. (identity, useSync)
  424. {
  425. if (useSync)
  426. return Promise.reject(new GroupManagerDb.Error(new Error
  427. ("Sqlite3GroupManagerDb.deleteMemberPromise is only supported for async")));
  428. return this.runPromise_
  429. ("DELETE FROM members WHERE member_name=?",
  430. identity.wireEncode(TlvWireFormat.get()).buf());
  431. };
  432. /**
  433. * Check if there is an EKey with the name eKeyName in the database.
  434. * @param {Name} eKeyName The name of the EKey.
  435. * @param {boolean} useSync (optional) If true then return a rejected promise
  436. * since this only supports async code.
  437. * @return {Promise|SyncPromise} A promise that returns true if the EKey exists
  438. * (else false), or that is rejected with GroupManagerDb.Error for a database
  439. * error.
  440. */
  441. GroupManagerDb.prototype.hasEKeyPromise = function(eKeyName, useSync)
  442. {
  443. if (useSync)
  444. return Promise.reject(new GroupManagerDb.Error(new Error
  445. ("Sqlite3GroupManagerDb.hasEKeyPromise is only supported for async")));
  446. return this.getPromise_
  447. ("SELECT ekey_id FROM ekeys where ekey_name=?",
  448. eKeyName.wireEncode(TlvWireFormat.get()).buf())
  449. .then(function(row) {
  450. if (row)
  451. return Promise.resolve(true);
  452. else
  453. return Promise.resolve(false);
  454. });
  455. };
  456. /**
  457. * Add the EKey with name eKeyName to the database.
  458. * Add the EKey with name eKeyName to the database.
  459. * @param {Name} eKeyName The name of the EKey. This copies the Name.
  460. * @param {Blob} publicKey The encoded public Key of the group key pair.
  461. * @param {Blob} privateKey The encoded private Key of the group key pair.
  462. * @param {boolean} useSync (optional) If true then return a rejected promise
  463. * since this only supports async code.
  464. * @return {Promise|SyncPromise} A promise that fulfills when the EKey is added,
  465. * or that is rejected with GroupManagerDb.Error if a key with name eKeyName
  466. * already exists in the database, or other database error.
  467. */
  468. Sqlite3GroupManagerDb.prototype.addEKeyPromise = function
  469. (eKeyName, publicKey, privateKey, useSync)
  470. {
  471. if (useSync)
  472. return Promise.reject(new GroupManagerDb.Error(new Error
  473. ("Sqlite3GroupManagerDb.addEKeyPromise is only supported for async")));
  474. var thisManager = this;
  475. return this.runPromise_
  476. ("INSERT INTO ekeys(ekey_name, pub_key) values (?, ?)",
  477. [eKeyName.wireEncode(TlvWireFormat.get()).buf(), publicKey.buf()])
  478. .then(function() {
  479. thisManager.privateKeyBase_[eKeyName.toUri()] = privateKey;
  480. return Promise.resolve();
  481. });
  482. };
  483. /**
  484. * Get the group key pair with the name eKeyName from the database.
  485. * @param {Name} eKeyName The name of the EKey.
  486. * @param {boolean} useSync (optional) If true then return a rejected promise
  487. * since this only supports async code.
  488. * @return {Promise|SyncPromise} A promise that returns an object (where
  489. * "publicKey" is the public key Blob and "privateKey" is the private key Blob),
  490. * or that is rejected with GroupManagerDb.Error for a database error.
  491. */
  492. Sqlite3GroupManagerDb.prototype.getEKeyPromise = function(eKeyName, useSync)
  493. {
  494. if (useSync)
  495. return Promise.reject(new GroupManagerDb.Error(new Error
  496. ("Sqlite3GroupManagerDb.getEKeyPromise is only supported for async")));
  497. var thisManager = this;
  498. return this.getPromise_
  499. ("SELECT pub_key FROM ekeys where ekey_name=?",
  500. eKeyName.wireEncode(TlvWireFormat.get()).buf())
  501. .then(function(row) {
  502. if (row)
  503. return Promise.resolve({
  504. publicKey: new Blob(row.pub_key, false),
  505. privateKey: thisManager.privateKeyBase_[eKeyName.toUri()] });
  506. else
  507. return Promise.reject(new GroupManagerDb.Error(new Error
  508. ("Sqlite3GroupManagerDb.getEKeyPromise: Cannot get the result from the database")));
  509. });
  510. };
  511. /**
  512. * Delete all the EKeys in the database. The database will keep growing because
  513. * EKeys will keep being added, so this method should be called periodically.
  514. * @param {boolean} useSync (optional) If true then return a rejected promise
  515. * since this only supports async code.
  516. * @return {Promise|SyncPromise} A promise that fulfills when the EKeys are
  517. * deleted, or that is rejected with GroupManagerDb.Error for a database error.
  518. */
  519. GroupManagerDb.prototype.cleanEKeysPromise = function(useSync)
  520. {
  521. return Promise.reject(new Error
  522. ("GroupManagerDb.cleanEKeysPromise is not implemented"));
  523. var thisManager = this;
  524. return this.runPromise_("DELETE FROM ekeys")
  525. .then(function() {
  526. thisManager.privateKeyBase_ = {};
  527. return Promise.resolve();
  528. });
  529. };
  530. /**
  531. * Delete the EKey with name eKeyName from the database. If no key with the
  532. * name exists in the database, do nothing.
  533. * @param {Name} eKeyName The name of the EKey.
  534. * @param {boolean} useSync (optional) If true then return a rejected promise
  535. * since this only supports async code.
  536. * @return {Promise|SyncPromise} A promise that fulfills when the EKey is
  537. * deleted (or there is no such key), or that is rejected with
  538. * GroupManagerDb.Error for a database error.
  539. */
  540. Sqlite3GroupManagerDb.prototype.deleteEKeyPromise = function(eKeyName, useSync)
  541. {
  542. if (useSync)
  543. return Promise.reject(new GroupManagerDb.Error(new Error
  544. ("Sqlite3GroupManagerDb.deleteEKeyPromise is only supported for async")));
  545. var thisManager = this;
  546. return this.runPromise_
  547. ("DELETE FROM ekeys WHERE ekey_name=?",
  548. [eKeyName.wireEncode(TlvWireFormat.get()).buf()])
  549. .then(function() {
  550. delete thisManager.privateKeyBase_[eKeyName.toUri()];
  551. return Promise.resolve();
  552. });
  553. };
  554. /**
  555. * Get the ID for the schedule.
  556. * @param {string} name The schedule name.
  557. * @return {Promise} A promise that returns the ID (or -1 if not found), or that
  558. * is rejected with GroupManagerDb.Error for a database error.
  559. */
  560. Sqlite3GroupManagerDb.prototype.getScheduleIdPromise_ = function(name)
  561. {
  562. return this.getPromise_
  563. ("SELECT schedule_id FROM schedules WHERE schedule_name=?", name)
  564. .then(function(row) {
  565. if (row)
  566. return Promise.resolve(row.schedule_id);
  567. else
  568. return Promise.resolve(-1);
  569. });
  570. };
  571. /**
  572. * Call Sqlite3Promise.runPromise, wrapping an Error in GroupManagerDb.Error.
  573. */
  574. Sqlite3GroupManagerDb.prototype.runPromise_ = function(sql, params)
  575. {
  576. return this.database_.runPromise(sql, params)
  577. .catch(function(error) {
  578. return Promise.reject(new GroupManagerDb.Error(error));
  579. });
  580. };
  581. /**
  582. * Call Sqlite3Promise.getPromise, wrapping an Error in GroupManagerDb.Error.
  583. */
  584. Sqlite3GroupManagerDb.prototype.getPromise_ = function(sql, params)
  585. {
  586. return this.database_.getPromise(sql, params)
  587. .catch(function(error) {
  588. return Promise.reject(new GroupManagerDb.Error(error));
  589. });
  590. };
  591. /**
  592. * Call Sqlite3Promise.eachPromise, wrapping an Error in GroupManagerDb.Error.
  593. */
  594. Sqlite3GroupManagerDb.prototype.eachPromise_ = function(sql, params, onRow)
  595. {
  596. return this.database_.eachPromise(sql, params, onRow)
  597. .catch(function(error) {
  598. return Promise.reject(new GroupManagerDb.Error(error));
  599. });
  600. };
  601. Sqlite3GroupManagerDb.initializeDatabasePromise_ = function(database)
  602. {
  603. // Enable foreign keys.
  604. return database.runPromise("PRAGMA foreign_keys = ON")
  605. .then(function() {
  606. return database.runPromise(Sqlite3GroupManagerDb.INITIALIZATION1);
  607. })
  608. .then(function() {
  609. return database.runPromise(Sqlite3GroupManagerDb.INITIALIZATION2);
  610. })
  611. .then(function() {
  612. return database.runPromise(Sqlite3GroupManagerDb.INITIALIZATION3);
  613. })
  614. .then(function() {
  615. return database.runPromise(Sqlite3GroupManagerDb.INITIALIZATION4);
  616. })
  617. .then(function() {
  618. return database.runPromise(Sqlite3GroupManagerDb.INITIALIZATION5);
  619. })
  620. .then(function() {
  621. return database.runPromise(Sqlite3GroupManagerDb.INITIALIZATION6);
  622. });
  623. };
  624. Sqlite3GroupManagerDb.INITIALIZATION1 =
  625. "CREATE TABLE IF NOT EXISTS \n" +
  626. " schedules( \n" +
  627. " schedule_id INTEGER PRIMARY KEY, \n" +
  628. " schedule_name TEXT NOT NULL, \n" +
  629. " schedule BLOB NOT NULL \n" +
  630. " ); \n";
  631. Sqlite3GroupManagerDb.INITIALIZATION2 =
  632. "CREATE UNIQUE INDEX IF NOT EXISTS \n" +
  633. " scheduleNameIndex ON schedules(schedule_name); \n";
  634. Sqlite3GroupManagerDb.INITIALIZATION3 =
  635. "CREATE TABLE IF NOT EXISTS \n" +
  636. " members( \n" +
  637. " member_id INTEGER PRIMARY KEY, \n" +
  638. " schedule_id INTEGER NOT NULL, \n" +
  639. " member_name BLOB NOT NULL, \n" +
  640. " key_name BLOB NOT NULL, \n" +
  641. " pubkey BLOB NOT NULL, \n" +
  642. " FOREIGN KEY(schedule_id) \n" +
  643. " REFERENCES schedules(schedule_id) \n" +
  644. " ON DELETE CASCADE \n" +
  645. " ON UPDATE CASCADE \n" +
  646. " ); \n";
  647. Sqlite3GroupManagerDb.INITIALIZATION4 =
  648. "CREATE UNIQUE INDEX IF NOT EXISTS \n" +
  649. " memNameIndex ON members(member_name); \n";
  650. Sqlite3GroupManagerDb.INITIALIZATION5 =
  651. "CREATE TABLE IF NOT EXISTS \n" +
  652. " ekeys( \n" +
  653. " ekey_id INTEGER PRIMARY KEY, \n" +
  654. " ekey_name BLOB NOT NULL, \n" +
  655. " pub_key BLOB NOT NULL \n" +
  656. " ); \n";
  657. Sqlite3GroupManagerDb.INITIALIZATION6 =
  658. "CREATE UNIQUE INDEX IF NOT EXISTS \n" +
  659. " ekeyNameIndex ON ekeys(ekey_name); \n";