From 3a18e969eb6914c5720cb73166175f2970383371 Mon Sep 17 00:00:00 2001 From: Brandon Edens Date: Thu, 8 Mar 2018 20:29:04 -0800 Subject: [PATCH] Add software that allows for specification of both the dat directory as well as the directory for the dat secrets. --- index.js | 1 + lib/storage.js | 41 +++++++++++++++++++++------------- readme.md | 11 ++++++++-- test/download.js | 57 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 93 insertions(+), 17 deletions(-) diff --git a/index.js b/index.js index fcb8d7e..74ee14e 100644 --- a/index.js +++ b/index.js @@ -18,6 +18,7 @@ module.exports = createDat * @param {Boolean} [opts.createIfMissing = true] - Create storage if it does not exit. * @param {Boolean} [opts.errorIfExists = false] - Error if storage exists. * @param {Boolean} [opts.temp = false] - Use random-access-memory for temporary storage + * @param {string} [opts.secretDir] - Directory for storage of secrets * @param {function(err, dat)} cb - callback that returns `Dat` instance * @see defaultStorage for storage information */ diff --git a/lib/storage.js b/lib/storage.js index a0d8a60..e0f7989 100644 --- a/lib/storage.js +++ b/lib/storage.js @@ -16,6 +16,7 @@ module.exports = defaultStorage * Object is a hyperdrive storage object `{metadata: fn, content: fn}`. * @param {object} [opts] - options * @param {Boolean} [opts.temp] - Use temporary storage (random-access-memory) + * @param {string} [opts.secretDir] - Directory for storage of secrets. * @returns {object} hyperdrive storage object */ function defaultStorage (storage, opts) { @@ -23,7 +24,7 @@ function defaultStorage (storage, opts) { if (typeof storage !== 'string') return storage if (opts.temp) return ram if (opts.latest === false) { - // Store as SLEEP files inluding content.data + // Store as SLEEP files including content.data return { metadata: function (name, opts) { // I don't think we want this, we may get multiple 'ogd' sources @@ -37,24 +38,34 @@ function defaultStorage (storage, opts) { } try { - // Store in .dat with secret in ~/.dat - if (fs.statSync(storage).isDirectory()) { - return datStore(storage) + makeDirectoryIfNotExist(storage) + + if (typeof opts.secretDir !== 'undefined') { + try { + makeDirectoryIfNotExist(opts.secretDir) + } catch (e) { + throw new Error('Secret dir must be dir') + } } + return datStore(storage, opts) } catch (e) { - // Does not exist, make dir + throw new Error('Storage must be dir or opts.temp') + } + + function makeDirectoryIfNotExist (path) { try { - fs.mkdirSync(storage) + if (fs.statSync(path).isDirectory()) { + return true + } } catch (e) { - // Invalid path - throw new Error('Invalid storage path') + // Path does not exist, make dir. + try { + fs.mkdirSync(storage) + return true + } catch (e) { + throw new Error('Invalid path ' + path) + } } - return datStore(storage) - } - error() - - function error () { - // TODO: single file sleep storage - throw new Error('Storage must be dir or opts.temp') + return false } } diff --git a/readme.md b/readme.md index b19c5d3..2e3a5da 100644 --- a/readme.md +++ b/readme.md @@ -102,10 +102,12 @@ We'll go through what these are for and a few of the common usages of each eleme ### Storage -Every dat archive has **storage**, this is the required first argument for dat-node. By default, we use [dat-storage](http://github.com/datproject/dat-storage) which stores the secret key in `~/.dat/` and the rest of the ddata in `dir/.dat`. Other common options are: +Every dat archive has **storage**, this is the required first argument for dat-node. By default, we use [dat-storage](http://github.com/datproject/dat-storage) which stores the secret key in `~/.dat/` and the rest of the data in `dir/.dat`. Other common options are: * **Persistent storage**: Stored files in `/my-dir` and metadata in `my-dir/.dat` by passing `/my-dir` as the first argument. * **Temporary Storage**: Use the `temp: true` option to keep metadata stored in memory. +* **Secret Key Dir**: Specify secretDir in the second opts argument in the form of {secretDir: '/my-secrets'} to store files + in /my-dir and secrets in /my-secrets respectively. ```js // Permanent Storage @@ -113,13 +115,18 @@ Dat('/my-dir', function (err, dat) { // Do Dat Stuff }) +// Secret Storage +Dat('/my-dir', {secretDir: '/my-secrets'}, function (err, dat) { + // Do Dat Stuff +}) + // Temporary Storage Dat('/my-dir', {temp: true}, function (err, dat) { // Do Dat Stuff }) ``` -Both of these will import files from `/my-dir` when doing `dat.importFiles()` but only the first will make a `.dat` folder and keep the metadata on disk. +All of these will import files from `/my-dir` when doing `dat.importFiles()` but only the first two will make a `.dat` folder and keep the metadata on disk. The storage argument can also be passed through to hyperdrive for more advanced storage use cases. diff --git a/test/download.js b/test/download.js index 7e9855d..286e3dd 100644 --- a/test/download.js +++ b/test/download.js @@ -62,6 +62,63 @@ test('download: Download with default opts', function (t) { }) }) +test('download: Download with secretDir opt', function (t) { + shareFixtures(function (err, shareKey, closeShare) { + t.error(err, 'error') + + tmpDir(function (err, downDir, cleanup) { + t.error(err, 'error') + + tmpDir(function (err, downSecretDir, cleanupSecret) { + t.error(err, 'error') + + Dat(downDir, {secretDir: downSecretDir, key: shareKey}, function (err, dat) { + t.error(err, 'error') + t.ok(dat, 'callsback with dat object') + t.ok(dat.key, 'has key') + t.ok(dat.archive, 'has archive') + t.notOk(dat.writable, 'archive not writable') + + var stats = dat.trackStats() + var network = dat.joinNetwork(function () { + t.pass('joinNetwork calls back okay') + }) + network.once('connection', function () { + t.pass('connects via network') + }) + var archive = dat.archive + archive.once('content', function () { + t.pass('gets content') + archive.content.on('sync', done) + }) + + function done () { + var st = stats.get() + t.ok(st.version === archive.version, 'stats version correct') + t.ok(st.downloaded === st.length, 'all blocks downloaded') + helpers.verifyFixtures(t, archive, function (err) { + t.error(err, 'error') + dat.close(function (err) { + t.error(err, 'error') + cleanup(function (err) { + t.error(err, 'error') + cleanupSecret(function (err) { + t.error(err, 'error') + closeShare(function (err) { + t.error(err, 'error') + t.end() + }) + }) + }) + }) + }) + } + }) + }) + }) + }) +}) + // TODO: // rest of download tests // tests will be a lot better with some download-finished type check