New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

mobiletto

Package Overview
Dependencies
Maintainers
1
Versions
97
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

mobiletto - npm Package Compare versions

Comparing version 1.0.4 to 1.0.6

35

drivers/local/index.js

@@ -12,2 +12,12 @@ const { dirname } = require('path')

const isENOENT = (err) => err.code && err.code === 'ENOENT'
const ioError = (err, path, method) => isENOENT(err)
? err instanceof MobilettoNotFoundError
? err
: new MobilettoNotFoundError(path)
: err instanceof MobilettoError || err instanceof MobilettoNotFoundError
? err
: new MobilettoError(`${method}(${path}) error: ${err}`, err)
class StorageClient {

@@ -78,3 +88,3 @@ baseDir

} catch (err) {
throw new MobilettoError(`list(${path}) error: ${err}`, err)
throw ioError(err, path, 'list')
}

@@ -87,7 +97,14 @@ }

if (!lstat) {
throw new MobilettoError(`metadata: lstat error`)
throw new MobilettoError('metadata: lstat error')
}
const type = this.fileType(lstat)
if (type === M_DIR && path !== '') {
const contents = await this.list(path)
if (contents.length === 0) {
throw new MobilettoNotFoundError(path)
}
}
return {
name: file.startsWith(this.baseDir) ? file.substring(this.baseDir.length) : file,
type: this.fileType(lstat),
type,
size: lstat.size,

@@ -97,6 +114,3 @@ mtime: lstat.mtimeMs

} catch (err) {
if (err.code && err.code === 'ENOENT') {
throw new MobilettoNotFoundError(path)
}
throw new MobilettoError(`metadata(${path}) error: ${err}`, err)
throw ioError(err, path, 'metadata')
}

@@ -157,6 +171,3 @@ }

} catch (err) {
if (err.code && err.code === 'ENOENT') {
throw new MobilettoNotFoundError(path)
}
throw new MobilettoError(`read(${path}) error: ${err}`, err)
throw ioError(err, path, 'read')
}

@@ -173,3 +184,3 @@ }

} catch (err) {
if (err.code && err.code === 'ENOENT') {
if (isENOENT(err)) {
if (!quiet) {

@@ -176,0 +187,0 @@ throw new MobilettoNotFoundError(path)

@@ -83,3 +83,4 @@ const {

const response = await this.client.send(new ListObjectsCommand(bucketParams))
if (typeof response.Contents !== 'undefined') {
const hasContents = typeof response.Contents !== 'undefined'
if (hasContents) {
response.Contents.forEach((item) => {

@@ -89,3 +90,4 @@ objects.push(item.Key) // todo: transform into standard object

}
if (typeof response.CommonPrefixes !== 'undefined') {
const hasCommonPrefixes = typeof response.CommonPrefixes !== 'undefined'
if (hasCommonPrefixes) {
response.CommonPrefixes.forEach((item) => {

@@ -99,9 +101,18 @@ objects.push(item.Prefix) // todo: transform into standard object

bucketParams.Marker = response.NextMarker
} else if (!hasContents && !hasCommonPrefixes) {
if (path === '') {
break
}
throw new MobilettoNotFoundError(path)
}
// At end of the list, response.truncated is false, and the function exits the while loop.
} catch (err) {
console.log(`${logPrefix} Error: ${err}`)
truncated = false
if (err instanceof MobilettoNotFoundError) {
throw err
}
throw new MobilettoError(`${logPrefix} Error: ${err}`)
}
}
if (recursive && objects.length === 0) {
throw new MobilettoNotFoundError(path)
}
return objects

@@ -219,3 +230,10 @@ }

}
objects = await this._list(path, {MaxKeys: DELETE_OBJECTS_MAX_KEYS})
try {
objects = await this._list(path, {MaxKeys: DELETE_OBJECTS_MAX_KEYS})
} catch (e) {
if (!(e instanceof MobilettoNotFoundError)) {
throw e instanceof MobilettoError ? e : new MobilettoError(`remove(${path}): error listing: ${e}`)
}
objects = null
}
}

@@ -222,0 +240,0 @@ } else {

@@ -0,4 +1,12 @@

const { basename, dirname } = require('path')
const shasum = require('shasum')
const randomstring = require('randomstring')
const crypt = require('./util/crypt')
const {DEFAULT_CRYPT_ALGO, normalizeKey, normalizeIV} = require("./util/crypt");
const {DEFAULT_CRYPT_ALGO, normalizeKey, normalizeIV, encrypt, decrypt} = require("./util/crypt");
const DIR_ENT_DIR_SUFFIX = '__.dirent'
const DIR_ENT_FILE_PREFIX = 'dirent__'
const ENC_PAD_SEP = ' ~ '
// adapted from https://stackoverflow.com/a/27724419

@@ -27,2 +35,27 @@ function MobilettoError (message, err) {

const reader = (chunks) => (chunk) => {
if (chunk) {
chunks.push(chunk)
}
}
const UTILITY_FUNCTIONS = {
readFile: (client) => async (path) => {
const chunks = []
await client.read(path, reader(chunks))
return Buffer.concat(chunks)
}
}
function addUtilityFunctions (client) {
for (const func of Object.keys(UTILITY_FUNCTIONS)) {
client[func] = UTILITY_FUNCTIONS[func](client)
}
return client
}
async function connect (driverPath, key, secret, opts, encryption = null) {
return await mobiletto(driverPath, key, secret, opts, encryption)
}
async function mobiletto (driverPath, key, secret, opts, encryption = null) {

@@ -35,3 +68,3 @@ const driver = require(driverPath.includes('/') ? driverPath : `./drivers/${driverPath}/index.js`)

if (encryption === null) {
return client
return addUtilityFunctions(client)
}

@@ -46,13 +79,91 @@ const encKey = normalizeKey(encryption.key)

}
const encryptPaths = encryption.encryptPaths || true;
const enc = {
key: encKey,
iv,
algo: encryption.algo || DEFAULT_CRYPT_ALGO
algo: encryption.algo || DEFAULT_CRYPT_ALGO,
encryptPaths,
dirLevels: encryption.dirLevels || 4,
encPathPadding: () => ENC_PAD_SEP + randomstring.generate(1 + Math.floor(2*Math.random()))
}
return {
list: async (path) => client.list(path),
metadata: async (path) => client.metadata(path),
function encryptPath (path) {
const encrypted = shasum(enc.key + ' ' + path)
let newPath = ''
for (let i = 0; i <= enc.dirLevels; i++) {
if (newPath.length > 0) newPath += '/'
newPath += encrypted.substring(i*2, (i*2)+2)
}
return newPath + encrypted
}
const direntDir = dir => encryptPaths ? encryptPath(dir + DIR_ENT_DIR_SUFFIX) : null
const direntFile = (dirent, path) => dirent + '/' + shasum(DIR_ENT_FILE_PREFIX + ' ' + path)
const _metadata = (client) => async (path) => {
if (!encryptPaths) {
return client.metadata(path)
}
let meta
try {
meta = await client.metadata(encryptPath(path))
} catch (e) {
if (e instanceof MobilettoNotFoundError) {
const dd = direntDir(path);
try {
meta = await client.metadata(dd)
} catch (err) {
if (err instanceof MobilettoNotFoundError) {
const contents = await client.list(dd)
if (Array.isArray(contents) && contents.length > 0) {
return { name: path, type: M_DIR }
} else {
throw err
}
} else {
throw err
}
}
} else {
throw e
}
}
meta.name = path // rewrite name back to plaintext name
return meta
}
const _loadMeta = async (dirent, entries) => {
const files = []
for (const entry of entries) {
const cipherText = []
await client.read(dirent + '/' + basename(entry.name), reader(cipherText))
const plain = decrypt(cipherText.toString(), enc)
const realPath = plain.split(ENC_PAD_SEP)[0]
const meta = await _metadata(client)(realPath)
files.push(meta)
}
return files
}
async function removeDirentFile(path) {
const df = direntFile(direntDir(dirname(path)), path);
await client.remove(df, {recursive: false, quiet: true})
await client.remove(encryptPath(path), {recursive: false, quiet: true})
}
const encClient = {
list: async (path) => {
if (!encryptPaths) {
return await client.list(path)
}
const dirent = direntDir(path)
const entries = await client.list(dirent)
if (!entries || entries.length === 0) {
return []
}
return _loadMeta(dirent, entries)
},
metadata: _metadata(client),
read: async (path, callback) => {
const realPath = encryptPaths ? encryptPath(path) : path
const cipher = crypt.startDecryptStream(enc)
return client.read(path,
return client.read(realPath,
(chunk) => {

@@ -65,2 +176,21 @@ return callback(crypt.updateCryptStream(cipher, chunk))

write: async (path, readFunc) => {
// if encrypting paths, write dirent file(s) for all parent directories
if (encryptPaths) {
let p = path
while (true) {
const direntGenerator = function* () {
yield encrypt(p + enc.encPathPadding(), enc)
}
const dir = direntDir(dirname(p))
const df = direntFile(dir, p);
if (!(await client.write(df, direntGenerator()))) {
throw new MobilettoError('write: error writing dirent file')
}
p = dirname(p)
if (p === '.' || p === '') {
break
}
}
}
function* cryptGenerator(plaintextGenerator) {

@@ -75,3 +205,4 @@ let chunk = plaintextGenerator.next().value

const cipher = crypt.startEncryptStream(enc)
return client.write(path, cryptGenerator(readFunc))
const realPath = encryptPath(path)
return client.write(realPath, cryptGenerator(readFunc))
},

@@ -81,5 +212,61 @@ remove: async (path, options) => {

const quiet = (options && options.quiet) || false
return client.remove(path, {recursive, quiet})
if (!encryptPaths) {
return client.remove(path, {recursive, quiet})
}
if (recursive) {
// ugh. we have to iterate over all dirent files, and remove each file/subdir one by one
async function recRm (path) {
const dirent = direntDir(path)
let entries
try {
entries = await client.list(dirent)
} catch (e) {
if (!(e instanceof MobilettoNotFoundError)) {
throw e instanceof MobilettoError
? e
: new MobilettoError('error listing files for recursive deletion', e)
}
}
if (entries && entries.length > 0) {
const files = await _loadMeta(dirent, entries)
for (const f of files) {
await recRm(f.name)
}
}
await removeDirentFile(path);
}
await recRm(path)
}
// remove the single file/dir
await removeDirentFile(path);
// if we were the last dirent file, then also remove dirent directory, and recursively upwards
let parent = path
let dirent = direntDir(parent)
const df = direntFile(dirent, path)
await client.remove(df, {recursive: false, quiet: true})
while (true) {
try {
const entries = await client.list(dirent)
if (entries.length === 0) {
await removeDirentFile(parent)
}
} catch (e) {
if (!(e instanceof MobilettoNotFoundError)) {
throw e
}
}
if (parent === '.' || parent === '/') {
// do not remove dirent for root dir
break
}
parent = dirname(parent)
dirent = direntDir(parent)
}
return true
}
}
return addUtilityFunctions(encClient)
}

@@ -112,3 +299,3 @@

if (err) {
console.log(`writeStream: error writing: ${err}`)
console.error(`writeStream: error writing: ${err}`)
throw err

@@ -124,3 +311,3 @@ }

if (err) {
console.log(`closeStream: error closing: ${err}`)
console.error(`closeStream: error closing: ${err}`)
throw err

@@ -131,29 +318,2 @@ }

async function streamReader (stream, callback, endCallback) {
let count = 0
const streamHandler = async (stream) => {
new Promise((resolve, reject) => {
stream.on('data', (data) => {
count += data ? data.length : 0
callback(data)
})
stream.on('error', reject)
stream.on('end', (resolve) => {
if (typeof endCallback === 'function') {
const endData = endCallback()
if (endData) {
count += endData.length
callback(endData)
}
}
resolve()
})
})
}
await streamHandler(stream).then(() => {
// console.log('streamHandler ended')
})
return count
}
const M_FILE = 'file'

@@ -166,5 +326,5 @@ const M_DIR = 'dir'

M_FILE, M_DIR, M_LINK, M_SPECIAL,
mobiletto,
mobiletto, connect,
MobilettoError, MobilettoNotFoundError,
readStream, writeStream, closeStream, streamReader
readStream, writeStream, closeStream
}
{
"name": "mobiletto",
"version": "1.0.4",
"version": "1.0.6",
"description": "A storage abstraction layer",

@@ -5,0 +5,0 @@ "main": "index.js",

Mobiletto
=========
Mobiletto is a JavaScript storage abstraction layer.
Mobiletto is a JavaScript storage abstraction layer, with optional transparent client-side encryption.
It supports apps that are agnostic to where files are stored.
All drivers are tested for identical behavior with 30 tests for each driver.
# Basic usage
const { mobiletto } = require('mobiletto')
const { mobiletto, readFile } = require('mobiletto')

@@ -28,3 +30,3 @@ // General usage

// * prefix: optional, all read/writes within the S3 bucket will be under this prefix
// * delimiter: optional, directory delimiter, default is '/'
// * delimiter: optional, directory delimiter, default is '/' (note: always '/' when encryption is enabled)
const s3 = await mobiletto('s3', aws_key, aws_secret, {bucket: 'bk', region: 'us-east-1'})

@@ -50,2 +52,6 @@

s3.read(path, callback)
// Read an entire file at once (convenience method)
const localData = await local.readFile(path) // returns a byte Buffer of the file contents
const s3Data = await s3.readFile(path) // returns a byte Buffer of the file contents

@@ -79,5 +85,6 @@ // Write a file

const encryption = {
key: randomstring.generate(128), // required, must be >= 16 chars
iv: randomstring.generate(128), // optional
algo: 'aes-256-cbc' // optional, aes-256-cbc is the default
key: randomstring.generate(128), // required, must be >= 32 chars
iv: randomstring.generate(128), // optional, default is to derive IV from key
algo: 'aes-256-cbc', // optional, aes-256-cbc is the default
encryptPaths: true // optional, default is true
}

@@ -88,4 +95,26 @@ const api = await mobiletto(driverName, key, secret, opts, encryption)

// Subsequent read operations will decrypt data (client side) when reading
// Path names will also be encrypted
// If `encryptPaths` is true, then path names will be hashed using the encrpytion key
Note that when `encryptPaths` is enabled, `list` commands are considerably more inefficient,
especially for directories with a large number of files.
What's happening? A separate "directory entry" directory (encrypted) tracks what files are in that
directory (aka the dirent directory).
* The `list` command reads the directory entry files, decrypts each path listed; then returns metadata for each file
* The `write` command writes dirent files in each parent's dirent directory, recursively; then writes the file
* The `remove` command removes the corresponding dirent file, and its parent if empty, recursively; then removes the file
* Note: Recursive removal on large and deep filesystems can be an expensive operation
Note that even with `encryptPaths` enabled, an adversary with full visibility into your encrypted storage,
even without the key, can still see the total number of directories and how many files are in each, and with some
effort, discover some or all of the overall hierarchical structure. They would not know the names of the
directories/files unless they also knew your encryption key or had otherwise successfully cracked the encryption.
All bets are off then!
# Alternate usage: import fully scoped module and use `connect`
const storage = require('mobiletto')
const s3 = await storage.connect('s3', aws_key, aws_secret, {bucket: 'bk', region: 'us-east-1'})
const objectData = await s3.readFile('some/path')
# Driver Interface

@@ -117,8 +146,10 @@ A driver is any JS file that exports a 'storageClient' function with this signature:

// Read a file
async read (path, callback) // callback receives a chunk of data; a null chunk signals end of data
// callback receives a chunk of data. endCallback is called at end-of-stream
async read (path, callback, endCallback = null)
// Write a file
async write (path, readFunc) // readFunc returns the data you want to write, or null to finish
// readFunc returns the data you want to write
async write (path, readFunc)
// Remove a file, or recursively delete a directory
async remove (path, {recursive = false, quiet = false})

@@ -9,4 +9,4 @@ // To run the tests, you need a .env file one level above this directory

const { mobiletto } = require('../index.js')
const {MobilettoNotFoundError, M_FILE, M_DIR} = require("../index")
const { mobiletto, connect, MobilettoNotFoundError, M_FILE, M_DIR } = require("../index")
const { encrypt, decrypt, normalizeKey, normalizeIV, DEFAULT_CRYPT_ALGO } = require("../util/crypt")

@@ -17,7 +17,11 @@ // chunk size used by generator function, used by driver's 'write' function

const TEMP_SZ_MULTIPLE = 3 // temp file will be ~24k (READ_SZ * 3)
const ENC_SIZE_CLOSE_ENOUGH_PERCENT = 0.05;
// encoded bytes written will differ from actual bytes provided
// likewise, plaintext bytes read will differ from encoded bytes read
// our tests give some leeway when filesize differences
const ENC_SIZE_CLOSE_ENOUGH_PERCENT = 0.10
DRIVER_CONFIG = {
local: {
key: '/tmp'
key: process.env.LOCAL_STORAGE || '/tmp'
},

@@ -35,2 +39,7 @@ s3: {

function closeEnough (expected, actual, percent = ENC_SIZE_CLOSE_ENOUGH_PERCENT) {
expect(Math.abs(expected - actual)).to.be.lessThan(Math.floor(expected * percent),
'expected size within 5% of actual (due to encryption)')
}
async function assertMeta (api, name, expectedSize, closeEnoughPercent = null) {

@@ -41,4 +50,3 @@ const meta = await api.metadata(name)

if (closeEnoughPercent) {
expect(Math.abs(expectedSize - meta.size)).to.be.lessThan(Math.floor(meta.size * ENC_SIZE_CLOSE_ENOUGH_PERCENT),
'expected write API to return within 5% of bytes written (due to encryption)')
closeEnough(expectedSize, meta.size, closeEnoughPercent)
} else {

@@ -75,14 +83,17 @@ expect(meta.size).equals(expectedSize, 'expected size of written file to equal size of randomData')

async function readFile(fixture) {
const chunks = []
function reader(chunk) {
if (chunk) {
chunks.push(chunk)
describe('crypto test', () => {
it("should encrypt and decrypt successfully", async () => {
const enc = {
key: normalizeKey(randomstring.generate(32)),
iv: normalizeIV(randomstring.generate(16)),
algo: DEFAULT_CRYPT_ALGO
}
}
const response = await fixture.api.read(fixture.name, reader)
const data = Buffer.concat(chunks)
return { response, data }
}
const plaintext = randomstring.generate(1024 + Math.floor(1024*Math.random()))
const ciphertext = encrypt(plaintext, enc)
const decrypted = decrypt(ciphertext, enc)
expect(decrypted).to.equal(plaintext, 'decrypted data did not match plaintext')
})
})
// To test a single driver:

@@ -128,3 +139,3 @@ // - Uncomment one of the lines below to set driverName to the one you want to test

const name = `test_file_${fileSuffix}`
mobiletto(driverName, config.key, config.secret, config.opts)
connect(driverName, config.key, config.secret, config.opts)
.then(api => { fixture = {api, name, randomData} })

@@ -138,4 +149,4 @@ .finally(done)

it("should read the file we just wrote", async () => {
const { response, data } = await readFile(fixture);
expect(response).is.equal(data.length, 'expected read API to return correct number of bytes read')
const data = await fixture.api.readFile(fixture.name);
expect(data.length).is.equal(size, 'expected read API to return correct number of bytes read')
expect(data.toString('utf8')).to.equal(fixture.randomData, 'expected to read back the same data we wrote')

@@ -171,9 +182,8 @@ })

encryptedByteCount = await writeRandomFile(fixture, size);
expect(Math.abs(encryptedByteCount - size)).to.be.lessThan(Math.floor(size * ENC_SIZE_CLOSE_ENOUGH_PERCENT),
'expected write API to return within 5% of bytes written (due to encryption)')
closeEnough(size, encryptedByteCount)
})
it("should read the encrypted file we just wrote", async () => {
const { response, data } = await readFile(fixture);
expect(response).is.equal(encryptedByteCount, 'expected read API to return correct number of bytes read')
expect(data.toString('utf8')).to.equal(fixture.randomData, 'expected to read back the same data we wrote')
const data = await fixture.api.readFile(fixture.name);
expect(data.length).is.equal(size, 'expected read API to return correct number of bytes read')
expect(data.toString()).to.equal(fixture.randomData, 'expected to read back the same data we wrote')
})

@@ -192,54 +202,67 @@ it("should load metadata on the encrypted file we just wrote", async () => {

describe(`${driverName} - write files in a new dir, read metadata, recursively delete`, () => {
// a random directory and file within it
const randomParent = `random_dir_${rand(10)}`
const subdirName = `subdir_` + Date.now()
const randomPath = `${randomParent}/${subdirName}/random_file_${Date.now()}`
const fileCount = 3 + Math.floor(Math.random() * 10)
let fixture
beforeEach((done) => {
mobiletto(driverName, config.key, config.secret, config.opts)
.then(api => { fixture = {api, name: randomPath} })
.finally(done)
for (const encryption of [null, {key: rand(32)}]) {
const encDesc = encryption ? '(with encryption)' : '(without encryption)'
describe(`${driverName} - ${encDesc} write files in a new dir, read metadata, recursively delete`, () => {
// describe(`${driverName} - ENCRYPTION write files in a new dir, read metadata, recursively delete`, () => {
// const encryption = {key: rand(32)}
// const encryption = null
// a random directory and file within it
const randomParent = `testRPD_${rand(2)}/rand_${rand(4)}`
const subdirName = `subdir_` + Date.now()
const randomPath = `${randomParent}/${subdirName}/random_file_${Date.now()}`
//const fileCount = 3 + Math.floor(Math.random() * 10)
const fileCount = 2
let fixture
beforeEach((done) => {
mobiletto(driverName, config.key, config.secret, config.opts, encryption)
.then(api => { fixture = {api, name: randomPath} })
.catch((err) => { throw err })
.finally(done)
})
it(`should write ${fileCount} files in a new directory`, async () => {
function* dataGenerator() {
// return one chunk of random data
yield rand(READ_SZ)
}
for (let i = 0; i < fileCount; i++) {
const bytesWritten = await fixture.api.write(tempFilename(fixture.name, i), dataGenerator())
if (encryption) {
closeEnough(READ_SZ, bytesWritten)
} else {
expect(bytesWritten).to.equal(READ_SZ, 'expected write API to return correct number of bytes written')
}
}
})
it("should load metadata for one of the new files", async () => {
await assertMeta(fixture.api, fixture.name, READ_SZ, encryption ? ENC_SIZE_CLOSE_ENOUGH_PERCENT : null)
})
it("should see correct types on objects returned from a listing of the new directory", async () => {
const objects = await fixture.api.list(randomParent)
expect(objects).to.have.lengthOf(1)
expect(objects[0]).to.have.property('type', M_DIR, `subdir should have type ${M_DIR}`)
})
it("should see correct types on objects returned from a listing of the subdirectory", async () => {
const objects = await fixture.api.list(`${randomParent}/${subdirName}`)
expect(objects).to.have.lengthOf(fileCount)
for (let i = 0; i < fileCount; i++) {
// we should find all the files, and they should all have the correct type
expect(objects
.find(o => (o.type === M_FILE && o.name === tempFilename(fixture.name, i)))
).to.not.be.null
}
})
it("should recursively delete the directory and file we just created", async () => {
const recursive = true
const removed = await fixture.api.remove(randomParent, {recursive})
expect(removed).to.be.true
})
it("loading metadata on the file we wrote now fails", async () => {
await assertMetaFail(fixture.api, fixture.name)
})
it("loading metadata on the parent dir we wrote now fails", async () => {
await assertMetaFail(fixture.api, randomParent)
})
})
it(`should write ${fileCount} files in a new directory`, async () => {
function* dataGenerator() {
// return one chunk of random data
yield rand(READ_SZ)
}
for (let i = 0; i < fileCount; i++) {
const response = await fixture.api.write(tempFilename(fixture.name, i), dataGenerator())
expect(response).to.equal(READ_SZ, 'expected write API to return correct number of bytes written')
}
})
it("should load metadata for one of the new files", async () => {
await assertMeta (fixture.api, fixture.name, READ_SZ)
})
it("should see correct types on objects returned from a listing of the new directory", async () => {
const objects = await fixture.api.list(randomParent)
expect(objects).to.have.lengthOf(1)
expect(objects[0]).to.have.property('type', M_DIR, `subdir should have type ${M_DIR}`)
})
it("should see correct types on objects returned from a listing of the subdirectory", async () => {
const objects = await fixture.api.list(`${randomParent}/${subdirName}`)
expect(objects).to.have.lengthOf(fileCount)
for (let i = 0; i < fileCount; i++) {
// we should find all the files, and they should all have the correct type
expect(objects
.find(o => (o.type === M_FILE && o.name === tempFilename(fixture.name, i)))
).to.not.be.null
}
})
it("should recursively delete the directory and file we just created", async () => {
const recursive = true
const removed = await fixture.api.remove(randomParent, {recursive})
expect(removed).to.be.true
})
it("loading metadata on the file we wrote now fails", async () => {
await assertMetaFail(fixture.api, fixture.name)
})
it("loading metadata on the parent dir we wrote now fails", async () => {
await assertMetaFail(fixture.api, randomParent)
})
})
}

@@ -246,0 +269,0 @@ describe(`${driverName} - expect MobilettoNotFoundError when reading nonexistent file `, () => {

@@ -39,11 +39,12 @@ // adapted from https://stackoverflow.com/a/64136185

function encrypt (plainText, key = KEY, iv = CRYPTO_IV, outputEncoding = 'base64') {
if (!key) {
function encrypt (plainText, encryption, outputEncoding = 'base64') {
if (!encryption || !encryption.key) {
if (WARN_PLAINTEXT) {
console.warn(` ****** key is undefined, encryption of user-data is DISABLED`)
console.warn(` ****** encryption.key is undefined, encryption is DISABLED`)
}
return plainText
}
const cipher = getCipher(key, iv)
return Buffer.concat([cipher.update(plainText), cipher.final()]).toString(outputEncoding)
const cipher = getCipher(encryption)
const encoded = Buffer.concat([cipher.update(plainText), cipher.final()])
return encoded.toString(outputEncoding)
}

@@ -55,8 +56,8 @@

function decrypt (cipherText, key = KEY, iv = CRYPTO_IV, outputEncoding = 'utf8') {
if (!key) {
function decrypt (cipherText, encryption, outputEncoding = 'utf8', inputEncoding = 'base64') {
if (!encryption || !encryption.key) {
return cipherText
}
const cipher = getDecipher(key, iv)
const data = Buffer.from(cipherText, 'base64')
const cipher = getDecipher(encryption)
const data = Buffer.from(cipherText, inputEncoding)
return Buffer.concat([cipher.update(data), cipher.final()]).toString(outputEncoding)

@@ -63,0 +64,0 @@ }

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc