Source: encrypt/sqlite3-producer-db.js

  1. /**
  2. * Copyright (C) 2015-2016 Regents of the University of California.
  3. * @author: Jeff Thompson <jefft0@remap.ucla.edu>
  4. * @author: From ndn-group-encrypt src/producer-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 Blob = require('../util/blob.js').Blob; /** @ignore */
  22. var Sqlite3Promise = require('../util/sqlite3-promise.js').Sqlite3Promise; /** @ignore */
  23. var TlvWireFormat = require('../encoding/tlv-wire-format').TlvWireFormat; /** @ignore */
  24. var SyncPromise = require('../util/sync-promise.js').SyncPromise; /** @ignore */
  25. var ProducerDb = require('./producer-db.js').ProducerDb;
  26. /**
  27. * Sqlite3ProducerDb extends ProducerDb to implement storage of keys for the
  28. * producer using SQLite3. It contains one table that maps time slots (to the
  29. * nearest hour) to the content key created for that time slot.
  30. * Create a Sqlite3ProducerDb to use the given SQLite3 file.
  31. * @param {string} databaseFilePath The path of the SQLite file.
  32. * @throws ProducerDb.Error for a database error.
  33. * @note This class is an experimental feature. The API may change.
  34. * @constructor
  35. */
  36. var Sqlite3ProducerDb = function Sqlite3ProducerDb(databaseFilePath)
  37. {
  38. // Call the base constructor.
  39. ProducerDb.call(this);
  40. this.database_ = new Sqlite3Promise
  41. (databaseFilePath, Sqlite3ProducerDb.initializeDatabasePromise_);
  42. };
  43. Sqlite3ProducerDb.prototype = new ProducerDb();
  44. Sqlite3ProducerDb.prototype.name = "Sqlite3ProducerDb";
  45. exports.Sqlite3ProducerDb = Sqlite3ProducerDb;
  46. /**
  47. * Check if a content key exists for the hour covering timeSlot.
  48. * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
  49. * @param {boolean} useSync (optional) If true then return a rejected promise
  50. * since this only supports async code.
  51. * @return {Promise} A promise that returns true if there is a content key for
  52. * timeSlot (else false), or that is rejected with ProducerDb.Error for a
  53. * database error.
  54. */
  55. Sqlite3ProducerDb.prototype.hasContentKeyPromise = function(timeSlot, useSync)
  56. {
  57. if (useSync)
  58. return Promise.reject(new ProducerDb.Error(new Error
  59. ("Sqlite3ProducerDb.hasContentKeyPromise is only supported for async")));
  60. var fixedTimeSlot = ProducerDb.getFixedTimeSlot(timeSlot);
  61. return this.getPromise_
  62. ("SELECT key FROM contentkeys where timeslot=?", fixedTimeSlot)
  63. .then(function(row) {
  64. if (row)
  65. return Promise.resolve(true);
  66. else
  67. return Promise.resolve(false);
  68. });
  69. };
  70. /**
  71. * Get the content key for the hour covering timeSlot.
  72. * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
  73. * @param {boolean} useSync (optional) If true then return a rejected promise
  74. * since this only supports async code.
  75. * @return {Promise} A promise that returns a Blob with the encoded key, or that
  76. * is rejected with ProducerDb.Error if there is no key covering timeSlot, or
  77. * other database error
  78. */
  79. Sqlite3ProducerDb.prototype.getContentKeyPromise = function(timeSlot, useSync)
  80. {
  81. if (useSync)
  82. return Promise.reject(new ProducerDb.Error(new Error
  83. ("Sqlite3ProducerDb.getContentKeyPromise is only supported for async")));
  84. var fixedTimeSlot = ProducerDb.getFixedTimeSlot(timeSlot);
  85. return this.getPromise_
  86. ("SELECT key FROM contentkeys where timeslot=?", fixedTimeSlot)
  87. .then(function(row) {
  88. if (row)
  89. return Promise.resolve(new Blob(row.key, false));
  90. else
  91. return Promise.reject(new ProducerDb.Error(new Error
  92. ("Sqlite3ProducerDb.getContentKeyPromise: Cannot get the key from the database")));
  93. });
  94. };
  95. /**
  96. * Add key as the content key for the hour covering timeSlot.
  97. * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
  98. * @param {Blob} key The encoded key.
  99. * @param {boolean} useSync (optional) If true then return a rejected promise
  100. * since this only supports async code.
  101. * @return {Promise} A promise that fulfills when the key is added, or that
  102. * is rejected with ProducerDb.Error if a key for the same hour already exists
  103. * in the database, or other database error.
  104. */
  105. Sqlite3ProducerDb.prototype.addContentKeyPromise = function
  106. (timeSlot, key, useSync)
  107. {
  108. if (useSync)
  109. return Promise.reject(new ProducerDb.Error(new Error
  110. ("Sqlite3ProducerDb.addContentKeyPromise is only supported for async")));
  111. var fixedTimeSlot = ProducerDb.getFixedTimeSlot(timeSlot);
  112. return this.runPromise_
  113. ("INSERT INTO contentkeys (timeslot, key) values (?, ?)",
  114. [fixedTimeSlot, key.buf()]);
  115. };
  116. /**
  117. * Delete the content key for the hour covering timeSlot. If there is no key for
  118. * the time slot, do nothing.
  119. * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
  120. * @param {boolean} useSync (optional) If true then return a rejected promise
  121. * since this only supports async code.
  122. * @return {Promise} A promise that fulfills when the key is deleted (or there
  123. * is no such key), or that is rejected with ProducerDb.Error for a database
  124. * error.
  125. */
  126. Sqlite3ProducerDb.prototype.deleteContentKeyPromise = function(timeSlot, useSync)
  127. {
  128. if (useSync)
  129. return Promise.reject(new ProducerDb.Error(new Error
  130. ("Sqlite3ProducerDb.deleteContentKeyPromise is only supported for async")));
  131. var fixedTimeSlot = ProducerDb.getFixedTimeSlot(timeSlot);
  132. return this.runPromise_
  133. ("DELETE FROM contentkeys WHERE timeslot=?", fixedTimeSlot);
  134. };
  135. /**
  136. * Call Sqlite3Promise.runPromise, wrapping an Error in ProducerDb.Error.
  137. */
  138. Sqlite3ProducerDb.prototype.runPromise_ = function(sql, params)
  139. {
  140. return this.database_.runPromise(sql, params)
  141. .catch(function(error) {
  142. return Promise.reject(new ProducerDb.Error(error));
  143. });
  144. };
  145. /**
  146. * Call Sqlite3Promise.getPromise, wrapping an Error in ProducerDb.Error.
  147. */
  148. Sqlite3ProducerDb.prototype.getPromise_ = function(sql, params)
  149. {
  150. return this.database_.getPromise(sql, params)
  151. .catch(function(error) {
  152. return Promise.reject(new ProducerDb.Error(error));
  153. });
  154. };
  155. Sqlite3ProducerDb.initializeDatabasePromise_ = function(database)
  156. {
  157. return database.runPromise(Sqlite3ProducerDb.INITIALIZATION1)
  158. .then(function() {
  159. return database.runPromise(Sqlite3ProducerDb.INITIALIZATION2);
  160. });
  161. };
  162. Sqlite3ProducerDb.INITIALIZATION1 =
  163. "CREATE TABLE IF NOT EXISTS \n" +
  164. " contentkeys( \n" +
  165. " rowId INTEGER PRIMARY KEY, \n" +
  166. " timeSlot INTEGER, \n" +
  167. " key BLOB NOT NULL \n" +
  168. " ); \n";
  169. Sqlite3ProducerDb.INITIALIZATION2 =
  170. "CREATE UNIQUE INDEX IF NOT EXISTS \n" +
  171. " timeSlotIndex ON contentkeys(timeSlot); \n";