@parse/fs-files-adapter
Advanced tools
Comparing version 2.0.1 to 3.0.0
@@ -0,1 +1,13 @@ | ||
# [3.0.0](https://github.com/parse-community/parse-server-fs-adapter/compare/2.0.1...3.0.0) (2024-02-18) | ||
### Features | ||
* Add Node 20 support; remove Node 14, 16 support ([#60](https://github.com/parse-community/parse-server-fs-adapter/issues/60)) ([a913ae1](https://github.com/parse-community/parse-server-fs-adapter/commit/a913ae18c922bf29477244e4a02888f981984cc0)) | ||
### BREAKING CHANGES | ||
* Removes support for Node 14 and 16 ([a913ae1](a913ae1)) | ||
## [2.0.1](https://github.com/parse-community/parse-server-fs-adapter/compare/2.0.0...2.0.1) (2023-10-18) | ||
@@ -2,0 +14,0 @@ |
122
index.js
@@ -7,5 +7,5 @@ 'use strict'; | ||
var fs = require('fs'); | ||
var path = require('path'); | ||
var pathSep = require('path').sep; | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
const pathSep = require('path').sep; | ||
const crypto = require("crypto"); | ||
@@ -18,6 +18,6 @@ const algorithm = 'aes-256-gcm'; | ||
if (options.encryptionKey !== undefined){ | ||
this._encryptionKey = crypto.createHash('sha256').update(String(options.encryptionKey)).digest('base64').substr(0, 32); | ||
if (options.encryptionKey !== undefined) { | ||
this._encryptionKey = crypto.createHash('sha256').update(String(options.encryptionKey)).digest('base64').substring(0, 32); | ||
} | ||
let filesSubDirectory = options.filesSubDirectory || ''; | ||
const filesSubDirectory = options.filesSubDirectory || ''; | ||
this._filesDir = filesSubDirectory; | ||
@@ -31,7 +31,7 @@ this._mkdir(this._getApplicationDir()); | ||
FileSystemAdapter.prototype.createFile = function(filename, data) { | ||
let filepath = this._getLocalFilePath(filename); | ||
const filepath = this._getLocalFilePath(filename); | ||
const stream = fs.createWriteStream(filepath); | ||
return new Promise((resolve, reject) => { | ||
try{ | ||
if(this._encryptionKey !== null){ | ||
try { | ||
if (this._encryptionKey !== null) { | ||
const iv = crypto.randomBytes(16); | ||
@@ -54,3 +54,3 @@ const cipher = crypto.createCipheriv( | ||
}); | ||
}else{ | ||
} else { | ||
stream.write(data); | ||
@@ -61,4 +61,4 @@ stream.end(); | ||
}); | ||
} | ||
}catch(err){ | ||
} | ||
} catch(err) { | ||
return reject(err); | ||
@@ -70,3 +70,3 @@ } | ||
FileSystemAdapter.prototype.deleteFile = function(filename) { | ||
let filepath = this._getLocalFilePath(filename); | ||
const filepath = this._getLocalFilePath(filename); | ||
const chunks = []; | ||
@@ -95,3 +95,3 @@ const stream = fs.createReadStream(filepath); | ||
FileSystemAdapter.prototype.getFileData = function(filename) { | ||
let filepath = this._getLocalFilePath(filename); | ||
const filepath = this._getLocalFilePath(filename); | ||
const stream = fs.createReadStream(filepath); | ||
@@ -106,3 +106,3 @@ stream.read(); | ||
const data = Buffer.concat(chunks); | ||
if(this._encryptionKey !== null){ | ||
if (this._encryptionKey !== null) { | ||
const authTagLocation = data.length - 16; | ||
@@ -113,8 +113,8 @@ const ivLocation = data.length - 32; | ||
const encrypted = data.slice(0,ivLocation); | ||
try{ | ||
try { | ||
const decipher = crypto.createDecipheriv(algorithm, this._encryptionKey, iv); | ||
decipher.setAuthTag(authTag); | ||
const decrypted = Buffer.concat([decipher.update(encrypted), decipher.final()]); | ||
const decrypted = Buffer.concat([ decipher.update(encrypted), decipher.final() ]); | ||
return resolve(decrypted); | ||
}catch(err){ | ||
} catch(err) { | ||
return reject(err); | ||
@@ -131,51 +131,32 @@ } | ||
FileSystemAdapter.prototype.rotateEncryptionKey = function(options = {}) { | ||
FileSystemAdapter.prototype.rotateEncryptionKey = async function(options = {}) { | ||
const applicationDir = this._getApplicationDir(); | ||
var fileNames = []; | ||
var oldKeyFileAdapter = {}; | ||
let fileNames = []; | ||
let oldKeyFileAdapter = {}; | ||
if (options.oldKey !== undefined) { | ||
oldKeyFileAdapter = new FileSystemAdapter({filesSubDirectory: this._filesDir, encryptionKey: options.oldKey}); | ||
}else{ | ||
oldKeyFileAdapter = new FileSystemAdapter({filesSubDirectory: this._filesDir}); | ||
oldKeyFileAdapter = new FileSystemAdapter({ filesSubDirectory: this._filesDir, encryptionKey: options.oldKey }); | ||
} else { | ||
oldKeyFileAdapter = new FileSystemAdapter({ filesSubDirectory: this._filesDir }); | ||
} | ||
if (options.fileNames !== undefined){ | ||
if (options.fileNames !== undefined) { | ||
fileNames = options.fileNames; | ||
}else{ | ||
fileNames = fs.readdirSync(applicationDir); | ||
fileNames = fileNames.filter(fileName => fileName.indexOf('.') !== 0); | ||
} else { | ||
fileNames = fs.readdirSync(applicationDir); | ||
fileNames = fileNames.filter(fileName => fileName.indexOf('.') !== 0); | ||
} | ||
return new Promise((resolve, _reject) => { | ||
var fileNamesNotRotated = fileNames; | ||
var fileNamesRotated = []; | ||
var fileNameTotal = fileNames.length; | ||
var fileNameIndex = 0; | ||
fileNames.forEach(fileName => { | ||
oldKeyFileAdapter | ||
.getFileData(fileName) | ||
.then(plainTextData => { | ||
//Overwrite file with data encrypted with new key | ||
this.createFile(fileName, plainTextData) | ||
.then(() => { | ||
fileNamesRotated.push(fileName); | ||
fileNamesNotRotated = fileNamesNotRotated.filter(function(value){ return value !== fileName;}) | ||
fileNameIndex += 1; | ||
if (fileNameIndex == fileNameTotal){ | ||
resolve({rotated: fileNamesRotated, notRotated: fileNamesNotRotated}); | ||
} | ||
}) | ||
.catch(() => { | ||
fileNameIndex += 1; | ||
if (fileNameIndex == fileNameTotal){ | ||
resolve({rotated: fileNamesRotated, notRotated: fileNamesNotRotated}); | ||
} | ||
}) | ||
}) | ||
.catch(() => { | ||
fileNameIndex += 1; | ||
if (fileNameIndex == fileNameTotal){ | ||
resolve({rotated: fileNamesRotated, notRotated: fileNamesNotRotated}); | ||
} | ||
}); | ||
}); | ||
}); | ||
let fileNamesNotRotated = fileNames; | ||
const fileNamesRotated = []; | ||
for (const fileName of fileNames) { | ||
try { | ||
const plainTextData = await oldKeyFileAdapter.getFileData(fileName) | ||
// Overwrite file with data encrypted with new key | ||
await this.createFile(fileName, plainTextData) | ||
fileNamesRotated.push(fileName); | ||
fileNamesNotRotated = fileNamesNotRotated.filter(function(value) { return value !== fileName; }); | ||
} catch(err) { | ||
continue; | ||
} | ||
} | ||
return { rotated: fileNamesRotated, notRotated: fileNamesNotRotated }; | ||
} | ||
@@ -190,3 +171,3 @@ | ||
--------------- */ | ||
FileSystemAdapter.prototype._getApplicationDir = function() { | ||
FileSystemAdapter.prototype._getApplicationDir = function() { | ||
if (this._filesDir) { | ||
@@ -197,3 +178,3 @@ return path.join('files', this._filesDir); | ||
} | ||
} | ||
} | ||
@@ -205,3 +186,3 @@ FileSystemAdapter.prototype._applicationDirExist = function() { | ||
FileSystemAdapter.prototype._getLocalFilePath = function(filename) { | ||
let applicationDir = this._getApplicationDir(); | ||
const applicationDir = this._getApplicationDir(); | ||
if (!fs.existsSync(applicationDir)) { | ||
@@ -215,7 +196,7 @@ this._mkdir(applicationDir); | ||
// snippet found on -> https://gist.github.com/danherbert-epam/3960169 | ||
let dirs = dirPath.split(pathSep); | ||
var root = ""; | ||
const dirs = dirPath.split(pathSep); | ||
let root = ""; | ||
while (dirs.length > 0) { | ||
var dir = dirs.shift(); | ||
const dir = dirs.shift(); | ||
if (dir === "") { // If directory starts with a /, the first path will be an empty string. | ||
@@ -227,5 +208,4 @@ root = pathSep; | ||
fs.mkdirSync(path.join(root, dir)); | ||
} | ||
catch (e) { | ||
if ( e.code == 'EACCES' ) { | ||
} catch (err) { | ||
if (err.code == 'EACCES') { | ||
throw new Error("PERMISSION ERROR: In order to use the FileSystemAdapter, write access to the server's file system is required."); | ||
@@ -232,0 +212,0 @@ } |
{ | ||
"name": "@parse/fs-files-adapter", | ||
"version": "2.0.1", | ||
"version": "3.0.0", | ||
"description": "File system adapter for parse-server", | ||
@@ -11,4 +11,4 @@ "main": "index.js", | ||
"scripts": { | ||
"test": "jasmine", | ||
"coverage": "nyc jasmine" | ||
"coverage": "nyc jasmine", | ||
"test": "jasmine" | ||
}, | ||
@@ -30,3 +30,3 @@ "keywords": [ | ||
"@semantic-release/release-notes-generator": "9.0.3", | ||
"jasmine": "4.0.2", | ||
"jasmine": "5.1.0", | ||
"nyc": "15.1.0", | ||
@@ -33,0 +33,0 @@ "parse-server-conformance-tests": "1.0.0", |
@@ -8,2 +8,4 @@ # Parse Server FS Adapter <!-- omit in toc --> | ||
[![Node Version](https://img.shields.io/badge/nodejs-18,_20-green.svg?logo=node.js&style=flat)](https://nodejs.org) | ||
[![npm latest version](https://img.shields.io/npm/v/@parse/fs-files-adapter.svg)](https://www.npmjs.com/package/@parse/fs-files-adapter) | ||
@@ -10,0 +12,0 @@ |
@@ -29,3 +29,3 @@ /** | ||
console.log(`Running on branch: ${branch}`); | ||
// Set changelog file | ||
@@ -112,3 +112,3 @@ //const changelogFile = `./changelogs/CHANGELOG_${branch}.md`; | ||
const url = repositoryUrl + '/releases/tag/${nextRelease.gitTag}'; | ||
let comment = '🎉 This change has been released in version [${nextRelease.version}](' + url + ')'; | ||
const comment = '🎉 This change has been released in version [${nextRelease.version}](' + url + ')'; | ||
return comment; | ||
@@ -115,0 +115,0 @@ } |
'use strict'; | ||
let FileSystemAdapter = require('../index.js'); | ||
var fs = require('fs'); | ||
var path = require('path'); | ||
const FileSystemAdapter = require('../index.js'); | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
describe('File encryption tests', () => { | ||
const directory = 'sub1/sub2'; | ||
const directory = 'sub1/sub2'; | ||
afterEach(function() { | ||
//Use adapter to make directory if needed | ||
var adapter = new FileSystemAdapter({ | ||
filesSubDirectory: directory | ||
}); | ||
const filePath = path.join('files', directory); | ||
var fileNames = fs.readdirSync(filePath); | ||
fileNames.filter(fileName => fileName.indexOf('.') === 0); | ||
fileNames.forEach(fileName => { | ||
fs.unlinkSync(path.join(filePath, fileName)); | ||
}) | ||
}); | ||
afterEach(function() { | ||
const filePath = path.join('files', directory); | ||
const fileNames = fs.readdirSync(filePath); | ||
fileNames.filter(fileName => fileName.indexOf('.') === 0); | ||
fileNames.forEach(fileName => { | ||
fs.unlinkSync(path.join(filePath, fileName)); | ||
}) | ||
}); | ||
it('should create file location based on config', async function () { | ||
var fsAdapter = new FileSystemAdapter(); | ||
var config = {mount: '/parse', applicationId: 'yolo'} | ||
let location = fsAdapter.getFileLocation(config, 'hello.txt') | ||
expect(location).toBe('/parse/files/yolo/hello.txt'); | ||
}, 5000) | ||
it('should create file location based on config', async function () { | ||
const fsAdapter = new FileSystemAdapter(); | ||
const config = {mount: '/parse', applicationId: 'yolo'} | ||
const location = fsAdapter.getFileLocation(config, 'hello.txt') | ||
expect(location).toBe('/parse/files/yolo/hello.txt'); | ||
}, 5000) | ||
it("should save encrypted file in default directory", async function() { | ||
var adapter = new FileSystemAdapter({ | ||
encryptionKey: '89E4AFF1-DFE4-4603-9574-BFA16BB446FD' | ||
}); | ||
var filename = 'file2.txt'; | ||
const filePath = 'files/'+filename; | ||
await adapter.createFile(filename, "hello world", 'text/utf8'); | ||
const result = await adapter.getFileData(filename); | ||
expect(result instanceof Buffer).toBe(true); | ||
expect(result.toString('utf-8')).toEqual("hello world"); | ||
const data = fs.readFileSync(filePath); | ||
expect(data.toString('utf-8')).not.toEqual("hello world"); | ||
}, 5000); | ||
it("should save encrypted file in default directory", async function() { | ||
const adapter = new FileSystemAdapter({ | ||
encryptionKey: '89E4AFF1-DFE4-4603-9574-BFA16BB446FD' | ||
}); | ||
const filename = 'file2.txt'; | ||
const filePath = 'files/' + filename; | ||
await adapter.createFile(filename, "hello world", 'text/utf8'); | ||
const result = await adapter.getFileData(filename); | ||
expect(result instanceof Buffer).toBe(true); | ||
expect(result.toString('utf-8')).toEqual("hello world"); | ||
const data = fs.readFileSync(filePath); | ||
expect(data.toString('utf-8')).not.toEqual("hello world"); | ||
}, 5000); | ||
it("should save encrypted file in specified directory", async function() { | ||
var adapter = new FileSystemAdapter({ | ||
filesSubDirectory: directory, | ||
encryptionKey: '89E4AFF1-DFE4-4603-9574-BFA16BB446FD' | ||
}); | ||
var filename = 'file2.txt'; | ||
const filePath = 'files/'+directory+'/'+filename; | ||
await adapter.createFile(filename, "hello world", 'text/utf8'); | ||
const result = await adapter.getFileData(filename); | ||
expect(result instanceof Buffer).toBe(true); | ||
expect(result.toString('utf-8')).toEqual("hello world"); | ||
const data = fs.readFileSync(filePath); | ||
expect(data.toString('utf-8')).not.toEqual("hello world"); | ||
}, 5000); | ||
it("should save encrypted file in specified directory", async function() { | ||
const adapter = new FileSystemAdapter({ | ||
filesSubDirectory: directory, | ||
encryptionKey: '89E4AFF1-DFE4-4603-9574-BFA16BB446FD' | ||
}); | ||
const filename = 'file2.txt'; | ||
const filePath = 'files/' + directory + '/' + filename; | ||
await adapter.createFile(filename, "hello world", 'text/utf8'); | ||
const result = await adapter.getFileData(filename); | ||
expect(result instanceof Buffer).toBe(true); | ||
expect(result.toString('utf-8')).toEqual("hello world"); | ||
const data = fs.readFileSync(filePath); | ||
expect(data.toString('utf-8')).not.toEqual("hello world"); | ||
}, 5000); | ||
it("should save encrypted file in specified directory when directory starts with /", async function() { | ||
var adapter = new FileSystemAdapter({ | ||
filesSubDirectory: '/sub1/sub2', | ||
encryptionKey: '89E4AFF1-DFE4-4603-9574-BFA16BB446FD' | ||
}); | ||
var filename = 'file2.txt'; | ||
const filePath = 'files/'+directory+'/'+filename; | ||
await adapter.createFile(filename, "hello world", 'text/utf8'); | ||
const result = await adapter.getFileData(filename); | ||
expect(result instanceof Buffer).toBe(true); | ||
expect(result.toString('utf-8')).toEqual("hello world"); | ||
const data = fs.readFileSync(filePath); | ||
expect(data.toString('utf-8')).not.toEqual("hello world"); | ||
}, 5000); | ||
it("should save encrypted file in specified directory when directory starts with /", async function() { | ||
const adapter = new FileSystemAdapter({ | ||
filesSubDirectory: '/sub1/sub2', | ||
encryptionKey: '89E4AFF1-DFE4-4603-9574-BFA16BB446FD' | ||
}); | ||
const filename = 'file2.txt'; | ||
const filePath = 'files/' + directory + '/' + filename; | ||
await adapter.createFile(filename, "hello world", 'text/utf8'); | ||
const result = await adapter.getFileData(filename); | ||
expect(result instanceof Buffer).toBe(true); | ||
expect(result.toString('utf-8')).toEqual("hello world"); | ||
const data = fs.readFileSync(filePath); | ||
expect(data.toString('utf-8')).not.toEqual("hello world"); | ||
}, 5000); | ||
it("should rotate key of all unencrypted files to encrypted files", async function() { | ||
const unEncryptedAdapter = new FileSystemAdapter({ | ||
filesSubDirectory: directory | ||
}); | ||
const encryptedAdapter = new FileSystemAdapter({ | ||
filesSubDirectory: directory, | ||
encryptionKey: '89E4AFF1-DFE4-4603-9574-BFA16BB446FD' | ||
}); | ||
const fileName1 = 'file1.txt'; | ||
const data1 = "hello world"; | ||
const fileName2 = 'file2.txt'; | ||
const data2 = "hello new world"; | ||
const filePath1 = 'files/'+directory+'/'+fileName1; | ||
const filePath2 = 'files/'+directory+'/'+fileName2; | ||
//Store unecrypted files | ||
await unEncryptedAdapter.createFile(fileName1, data1, 'text/utf8'); | ||
var result = await unEncryptedAdapter.getFileData(fileName1); | ||
expect(result instanceof Buffer).toBe(true); | ||
expect(result.toString('utf-8')).toEqual(data1); | ||
const unEncryptedData1 = fs.readFileSync(filePath1); | ||
await unEncryptedAdapter.createFile(fileName2, data2, 'text/utf8'); | ||
result = await unEncryptedAdapter.getFileData(fileName2); | ||
expect(result instanceof Buffer).toBe(true); | ||
expect(result.toString('utf-8')).toEqual(data2); | ||
const unEncryptedData2 = fs.readFileSync(filePath2); | ||
//Check if encrypted adapter can read data and make sure it's not the same as unEncrypted adapter | ||
const {rotated, notRotated} = await encryptedAdapter.rotateEncryptionKey(); | ||
expect(rotated.length).toEqual(2); | ||
expect(rotated.filter(function(value){ return value === fileName1;}).length).toEqual(1); | ||
expect(rotated.filter(function(value){ return value === fileName2;}).length).toEqual(1); | ||
expect(notRotated.length).toEqual(0); | ||
result = await encryptedAdapter.getFileData(fileName1); | ||
expect(result instanceof Buffer).toBe(true); | ||
expect(result.toString('utf-8')).toEqual(data1); | ||
const encryptedData1 = fs.readFileSync(filePath1); | ||
expect(encryptedData1.toString('utf-8')).not.toEqual(unEncryptedData1); | ||
result = await encryptedAdapter.getFileData(fileName2); | ||
expect(result instanceof Buffer).toBe(true); | ||
expect(result.toString('utf-8')).toEqual(data2); | ||
const encryptedData2 = fs.readFileSync(filePath2); | ||
expect(encryptedData2.toString('utf-8')).not.toEqual(unEncryptedData2); | ||
}, 5000); | ||
it("should rotate key of all unencrypted files to encrypted files", async function() { | ||
const unEncryptedAdapter = new FileSystemAdapter({ | ||
filesSubDirectory: directory | ||
}); | ||
const encryptedAdapter = new FileSystemAdapter({ | ||
filesSubDirectory: directory, | ||
encryptionKey: '89E4AFF1-DFE4-4603-9574-BFA16BB446FD' | ||
}); | ||
const fileName1 = 'file1.txt'; | ||
const data1 = "hello world"; | ||
const fileName2 = 'file2.txt'; | ||
const data2 = "hello new world"; | ||
const filePath1 = 'files/' + directory + '/' + fileName1; | ||
const filePath2 = 'files/' + directory + '/' + fileName2; | ||
// Store unecrypted files | ||
await unEncryptedAdapter.createFile(fileName1, data1, 'text/utf8'); | ||
let result = await unEncryptedAdapter.getFileData(fileName1); | ||
expect(result instanceof Buffer).toBe(true); | ||
expect(result.toString('utf-8')).toEqual(data1); | ||
const unEncryptedData1 = fs.readFileSync(filePath1); | ||
await unEncryptedAdapter.createFile(fileName2, data2, 'text/utf8'); | ||
result = await unEncryptedAdapter.getFileData(fileName2); | ||
expect(result instanceof Buffer).toBe(true); | ||
expect(result.toString('utf-8')).toEqual(data2); | ||
const unEncryptedData2 = fs.readFileSync(filePath2); | ||
// Check if encrypted adapter can read data and make sure it's not the same as unEncrypted adapter | ||
const {rotated, notRotated} = await encryptedAdapter.rotateEncryptionKey(); | ||
expect(rotated.length).toEqual(2); | ||
expect(rotated.filter(function(value){ return value === fileName1;}).length).toEqual(1); | ||
expect(rotated.filter(function(value){ return value === fileName2;}).length).toEqual(1); | ||
expect(notRotated.length).toEqual(0); | ||
result = await encryptedAdapter.getFileData(fileName1); | ||
expect(result instanceof Buffer).toBe(true); | ||
expect(result.toString('utf-8')).toEqual(data1); | ||
const encryptedData1 = fs.readFileSync(filePath1); | ||
expect(encryptedData1.toString('utf-8')).not.toEqual(unEncryptedData1); | ||
result = await encryptedAdapter.getFileData(fileName2); | ||
expect(result instanceof Buffer).toBe(true); | ||
expect(result.toString('utf-8')).toEqual(data2); | ||
const encryptedData2 = fs.readFileSync(filePath2); | ||
expect(encryptedData2.toString('utf-8')).not.toEqual(unEncryptedData2); | ||
}, 5000); | ||
it("should rotate key of all old encrypted files to files encrypted with a new key", async function() { | ||
const oldEncryptionKey = 'oldKeyThatILoved'; | ||
const oldEncryptedAdapter = new FileSystemAdapter({ | ||
filesSubDirectory: directory, | ||
encryptionKey: oldEncryptionKey | ||
}); | ||
const encryptedAdapter = new FileSystemAdapter({ | ||
filesSubDirectory: directory, | ||
encryptionKey: 'newKeyThatILove' | ||
}); | ||
const fileName1 = 'file1.txt'; | ||
const data1 = "hello world"; | ||
const fileName2 = 'file2.txt'; | ||
const data2 = "hello new world"; | ||
const filePath1 = 'files/'+directory+'/'+fileName1; | ||
const filePath2 = 'files/'+directory+'/'+fileName2; | ||
//Store original encrypted files | ||
await oldEncryptedAdapter.createFile(fileName1, data1, 'text/utf8'); | ||
var result = await oldEncryptedAdapter.getFileData(fileName1); | ||
expect(result instanceof Buffer).toBe(true); | ||
expect(result.toString('utf-8')).toEqual(data1); | ||
const oldEncryptedData1 = fs.readFileSync(filePath1); | ||
await oldEncryptedAdapter.createFile(fileName2, data2, 'text/utf8'); | ||
result = await oldEncryptedAdapter.getFileData(fileName2); | ||
expect(result instanceof Buffer).toBe(true); | ||
expect(result.toString('utf-8')).toEqual(data2); | ||
const oldEncryptedData2 = fs.readFileSync(filePath2); | ||
//Check if encrypted adapter can read data and make sure it's not the same as unEncrypted adapter | ||
const {rotated, notRotated} = await encryptedAdapter.rotateEncryptionKey({oldKey: oldEncryptionKey}); | ||
expect(rotated.length).toEqual(2); | ||
expect(rotated.filter(function(value){ return value === fileName1;}).length).toEqual(1); | ||
expect(rotated.filter(function(value){ return value === fileName2;}).length).toEqual(1); | ||
expect(notRotated.length).toEqual(0); | ||
var result2 = await encryptedAdapter.getFileData(fileName1); | ||
expect(result2 instanceof Buffer).toBe(true); | ||
expect(result2.toString('utf-8')).toEqual(data1); | ||
const encryptedData1 = fs.readFileSync(filePath1); | ||
expect(encryptedData1.toString('utf-8')).not.toEqual(oldEncryptedData1); | ||
result = await encryptedAdapter.getFileData(fileName2); | ||
expect(result instanceof Buffer).toBe(true); | ||
expect(result.toString('utf-8')).toEqual(data2); | ||
const encryptedData2 = fs.readFileSync(filePath2); | ||
expect(encryptedData2.toString('utf-8')).not.toEqual(oldEncryptedData2); | ||
}, 5000); | ||
it("should rotate key of all old encrypted files to files encrypted with a new key", async function() { | ||
const oldEncryptionKey = 'oldKeyThatILoved'; | ||
const oldEncryptedAdapter = new FileSystemAdapter({ | ||
filesSubDirectory: directory, | ||
encryptionKey: oldEncryptionKey | ||
}); | ||
const encryptedAdapter = new FileSystemAdapter({ | ||
filesSubDirectory: directory, | ||
encryptionKey: 'newKeyThatILove' | ||
}); | ||
const fileName1 = 'file1.txt'; | ||
const data1 = "hello world"; | ||
const fileName2 = 'file2.txt'; | ||
const data2 = "hello new world"; | ||
const filePath1 = 'files/' + directory + '/' + fileName1; | ||
const filePath2 = 'files/' + directory + '/' + fileName2; | ||
// Store original encrypted files | ||
await oldEncryptedAdapter.createFile(fileName1, data1, 'text/utf8'); | ||
let result = await oldEncryptedAdapter.getFileData(fileName1); | ||
expect(result instanceof Buffer).toBe(true); | ||
expect(result.toString('utf-8')).toEqual(data1); | ||
const oldEncryptedData1 = fs.readFileSync(filePath1); | ||
await oldEncryptedAdapter.createFile(fileName2, data2, 'text/utf8'); | ||
result = await oldEncryptedAdapter.getFileData(fileName2); | ||
expect(result instanceof Buffer).toBe(true); | ||
expect(result.toString('utf-8')).toEqual(data2); | ||
const oldEncryptedData2 = fs.readFileSync(filePath2); | ||
// Check if encrypted adapter can read data and make sure it's not the same as unEncrypted adapter | ||
const {rotated, notRotated} = await encryptedAdapter.rotateEncryptionKey({oldKey: oldEncryptionKey}); | ||
expect(rotated.length).toEqual(2); | ||
expect(rotated.filter(function(value){ return value === fileName1;}).length).toEqual(1); | ||
expect(rotated.filter(function(value){ return value === fileName2;}).length).toEqual(1); | ||
expect(notRotated.length).toEqual(0); | ||
const result2 = await encryptedAdapter.getFileData(fileName1); | ||
expect(result2 instanceof Buffer).toBe(true); | ||
expect(result2.toString('utf-8')).toEqual(data1); | ||
const encryptedData1 = fs.readFileSync(filePath1); | ||
expect(encryptedData1.toString('utf-8')).not.toEqual(oldEncryptedData1); | ||
result = await encryptedAdapter.getFileData(fileName2); | ||
expect(result instanceof Buffer).toBe(true); | ||
expect(result.toString('utf-8')).toEqual(data2); | ||
const encryptedData2 = fs.readFileSync(filePath2); | ||
expect(encryptedData2.toString('utf-8')).not.toEqual(oldEncryptedData2); | ||
}, 5000); | ||
it("should rotate key of all old encrypted files to unencrypted files", async function() { | ||
const oldEncryptionKey = 'oldKeyThatILoved'; | ||
const oldEncryptedAdapter = new FileSystemAdapter({ | ||
filesSubDirectory: directory, | ||
encryptionKey: oldEncryptionKey | ||
}); | ||
const unEncryptedAdapter = new FileSystemAdapter({ | ||
filesSubDirectory: directory | ||
}); | ||
const fileName1 = 'file1.txt'; | ||
const data1 = "hello world"; | ||
const fileName2 = 'file2.txt'; | ||
const data2 = "hello new world"; | ||
const filePath1 = 'files/'+directory+'/'+fileName1; | ||
const filePath2 = 'files/'+directory+'/'+fileName2; | ||
//Store original encrypted files | ||
await oldEncryptedAdapter.createFile(fileName1, data1, 'text/utf8'); | ||
var result = await oldEncryptedAdapter.getFileData(fileName1); | ||
expect(result instanceof Buffer).toBe(true); | ||
expect(result.toString('utf-8')).toEqual(data1); | ||
const oldEncryptedData1 = fs.readFileSync(filePath1); | ||
await oldEncryptedAdapter.createFile(fileName2, data2, 'text/utf8'); | ||
result = await oldEncryptedAdapter.getFileData(fileName2); | ||
expect(result instanceof Buffer).toBe(true); | ||
expect(result.toString('utf-8')).toEqual(data2); | ||
const oldEncryptedData2 = fs.readFileSync(filePath2); | ||
//Check if unEncrypted adapter can read data and make sure it's not the same as oldEncrypted adapter | ||
const {rotated, notRotated} = await unEncryptedAdapter.rotateEncryptionKey({oldKey: oldEncryptionKey}); | ||
expect(rotated.length).toEqual(2); | ||
expect(rotated.filter(function(value){ return value === fileName1;}).length).toEqual(1); | ||
expect(rotated.filter(function(value){ return value === fileName2;}).length).toEqual(1); | ||
expect(notRotated.length).toEqual(0); | ||
var result2 = await unEncryptedAdapter.getFileData(fileName1); | ||
expect(result2 instanceof Buffer).toBe(true); | ||
expect(result2.toString('utf-8')).toEqual(data1); | ||
const encryptedData1 = fs.readFileSync(filePath1); | ||
expect(encryptedData1.toString('utf-8')).not.toEqual(oldEncryptedData1); | ||
result = await unEncryptedAdapter.getFileData(fileName2); | ||
expect(result instanceof Buffer).toBe(true); | ||
expect(result.toString('utf-8')).toEqual(data2); | ||
const encryptedData2 = fs.readFileSync(filePath2); | ||
expect(encryptedData2.toString('utf-8')).not.toEqual(oldEncryptedData2); | ||
}, 5000); | ||
it("should rotate key of all old encrypted files to unencrypted files", async function() { | ||
const oldEncryptionKey = 'oldKeyThatILoved'; | ||
const oldEncryptedAdapter = new FileSystemAdapter({ | ||
filesSubDirectory: directory, | ||
encryptionKey: oldEncryptionKey | ||
}); | ||
const unEncryptedAdapter = new FileSystemAdapter({ | ||
filesSubDirectory: directory | ||
}); | ||
const fileName1 = 'file1.txt'; | ||
const data1 = "hello world"; | ||
const fileName2 = 'file2.txt'; | ||
const data2 = "hello new world"; | ||
const filePath1 = 'files/' + directory + '/' + fileName1; | ||
const filePath2 = 'files/' + directory + '/' + fileName2; | ||
// Store original encrypted files | ||
await oldEncryptedAdapter.createFile(fileName1, data1, 'text/utf8'); | ||
let result = await oldEncryptedAdapter.getFileData(fileName1); | ||
expect(result instanceof Buffer).toBe(true); | ||
expect(result.toString('utf-8')).toEqual(data1); | ||
const oldEncryptedData1 = fs.readFileSync(filePath1); | ||
await oldEncryptedAdapter.createFile(fileName2, data2, 'text/utf8'); | ||
result = await oldEncryptedAdapter.getFileData(fileName2); | ||
expect(result instanceof Buffer).toBe(true); | ||
expect(result.toString('utf-8')).toEqual(data2); | ||
const oldEncryptedData2 = fs.readFileSync(filePath2); | ||
// Check if unEncrypted adapter can read data and make sure it's not the same as oldEncrypted adapter | ||
const {rotated, notRotated} = await unEncryptedAdapter.rotateEncryptionKey({oldKey: oldEncryptionKey}); | ||
expect(rotated.length).toEqual(2); | ||
expect(rotated.filter(function(value){ return value === fileName1;}).length).toEqual(1); | ||
expect(rotated.filter(function(value){ return value === fileName2;}).length).toEqual(1); | ||
expect(notRotated.length).toEqual(0); | ||
const result2 = await unEncryptedAdapter.getFileData(fileName1); | ||
expect(result2 instanceof Buffer).toBe(true); | ||
expect(result2.toString('utf-8')).toEqual(data1); | ||
const encryptedData1 = fs.readFileSync(filePath1); | ||
expect(encryptedData1.toString('utf-8')).not.toEqual(oldEncryptedData1); | ||
result = await unEncryptedAdapter.getFileData(fileName2); | ||
expect(result instanceof Buffer).toBe(true); | ||
expect(result.toString('utf-8')).toEqual(data2); | ||
const encryptedData2 = fs.readFileSync(filePath2); | ||
expect(encryptedData2.toString('utf-8')).not.toEqual(oldEncryptedData2); | ||
}, 5000); | ||
it("should only encrypt specified fileNames with the new key", async function() { | ||
const oldEncryptionKey = 'oldKeyThatILoved'; | ||
const oldEncryptedAdapter = new FileSystemAdapter({ | ||
filesSubDirectory: directory, | ||
encryptionKey: oldEncryptionKey | ||
}); | ||
const encryptedAdapter = new FileSystemAdapter({ | ||
filesSubDirectory: directory, | ||
encryptionKey: 'newKeyThatILove' | ||
}); | ||
const unEncryptedAdapter = new FileSystemAdapter({ | ||
filesSubDirectory: directory | ||
}); | ||
const fileName1 = 'file1.txt'; | ||
const data1 = "hello world"; | ||
const fileName2 = 'file2.txt'; | ||
const data2 = "hello new world"; | ||
const filePath1 = 'files/'+directory+'/'+fileName1; | ||
const filePath2 = 'files/'+directory+'/'+fileName2; | ||
//Store original encrypted files | ||
await oldEncryptedAdapter.createFile(fileName1, data1, 'text/utf8'); | ||
var result = await oldEncryptedAdapter.getFileData(fileName1); | ||
expect(result instanceof Buffer).toBe(true); | ||
expect(result.toString('utf-8')).toEqual(data1); | ||
const oldEncryptedData1 = fs.readFileSync(filePath1); | ||
await oldEncryptedAdapter.createFile(fileName2, data2, 'text/utf8'); | ||
result = await oldEncryptedAdapter.getFileData(fileName2); | ||
expect(result instanceof Buffer).toBe(true); | ||
expect(result.toString('utf-8')).toEqual(data2); | ||
const oldEncryptedData2 = fs.readFileSync(filePath2); | ||
//Inject unecrypted file to see if causes an issue | ||
const fileName3 = 'file3.txt'; | ||
const data3 = "hello past world"; | ||
await unEncryptedAdapter.createFile(fileName3, data3, 'text/utf8'); | ||
//Check if encrypted adapter can read data and make sure it's not the same as unEncrypted adapter | ||
const {rotated, notRotated} = await encryptedAdapter.rotateEncryptionKey({oldKey: oldEncryptionKey, fileNames: [fileName1,fileName2]}); | ||
expect(rotated.length).toEqual(2); | ||
expect(rotated.filter(function(value){ return value === fileName1;}).length).toEqual(1); | ||
expect(rotated.filter(function(value){ return value === fileName2;}).length).toEqual(1); | ||
expect(notRotated.length).toEqual(0); | ||
expect(rotated.filter(function(value){ return value === fileName3;}).length).toEqual(0); | ||
var result2 = await encryptedAdapter.getFileData(fileName1); | ||
expect(result2 instanceof Buffer).toBe(true); | ||
expect(result2.toString('utf-8')).toEqual(data1); | ||
const encryptedData1 = fs.readFileSync(filePath1); | ||
expect(encryptedData1.toString('utf-8')).not.toEqual(oldEncryptedData1); | ||
result = await encryptedAdapter.getFileData(fileName2); | ||
expect(result instanceof Buffer).toBe(true); | ||
expect(result.toString('utf-8')).toEqual(data2); | ||
const encryptedData2 = fs.readFileSync(filePath2); | ||
expect(encryptedData2.toString('utf-8')).not.toEqual(oldEncryptedData2); | ||
}, 5000); | ||
it("should only encrypt specified fileNames with the new key", async function() { | ||
const oldEncryptionKey = 'oldKeyThatILoved'; | ||
const oldEncryptedAdapter = new FileSystemAdapter({ | ||
filesSubDirectory: directory, | ||
encryptionKey: oldEncryptionKey | ||
}); | ||
const encryptedAdapter = new FileSystemAdapter({ | ||
filesSubDirectory: directory, | ||
encryptionKey: 'newKeyThatILove' | ||
}); | ||
const unEncryptedAdapter = new FileSystemAdapter({ | ||
filesSubDirectory: directory | ||
}); | ||
const fileName1 = 'file1.txt'; | ||
const data1 = "hello world"; | ||
const fileName2 = 'file2.txt'; | ||
const data2 = "hello new world"; | ||
const filePath1 = 'files/' + directory + '/' + fileName1; | ||
const filePath2 = 'files/' + directory + '/' + fileName2; | ||
// Store original encrypted files | ||
await oldEncryptedAdapter.createFile(fileName1, data1, 'text/utf8'); | ||
let result = await oldEncryptedAdapter.getFileData(fileName1); | ||
expect(result instanceof Buffer).toBe(true); | ||
expect(result.toString('utf-8')).toEqual(data1); | ||
const oldEncryptedData1 = fs.readFileSync(filePath1); | ||
await oldEncryptedAdapter.createFile(fileName2, data2, 'text/utf8'); | ||
result = await oldEncryptedAdapter.getFileData(fileName2); | ||
expect(result instanceof Buffer).toBe(true); | ||
expect(result.toString('utf-8')).toEqual(data2); | ||
const oldEncryptedData2 = fs.readFileSync(filePath2); | ||
// Inject unecrypted file to see if causes an issue | ||
const fileName3 = 'file3.txt'; | ||
const data3 = "hello past world"; | ||
await unEncryptedAdapter.createFile(fileName3, data3, 'text/utf8'); | ||
// Check if encrypted adapter can read data and make sure it's not the same as unEncrypted adapter | ||
const {rotated, notRotated} = await encryptedAdapter.rotateEncryptionKey({oldKey: oldEncryptionKey, fileNames: [fileName1,fileName2]}); | ||
expect(rotated.length).toEqual(2); | ||
expect(rotated.filter(function(value){ return value === fileName1;}).length).toEqual(1); | ||
expect(rotated.filter(function(value){ return value === fileName2;}).length).toEqual(1); | ||
expect(notRotated.length).toEqual(0); | ||
expect(rotated.filter(function(value){ return value === fileName3;}).length).toEqual(0); | ||
const result2 = await encryptedAdapter.getFileData(fileName1); | ||
expect(result2 instanceof Buffer).toBe(true); | ||
expect(result2.toString('utf-8')).toEqual(data1); | ||
const encryptedData1 = fs.readFileSync(filePath1); | ||
expect(encryptedData1.toString('utf-8')).not.toEqual(oldEncryptedData1); | ||
result = await encryptedAdapter.getFileData(fileName2); | ||
expect(result instanceof Buffer).toBe(true); | ||
expect(result.toString('utf-8')).toEqual(data2); | ||
const encryptedData2 = fs.readFileSync(filePath2); | ||
expect(encryptedData2.toString('utf-8')).not.toEqual(oldEncryptedData2); | ||
}, 5000); | ||
it("should return fileNames of those it can't encrypt with the new key", async function() { | ||
const oldEncryptionKey = 'oldKeyThatILoved'; | ||
const oldEncryptedAdapter = new FileSystemAdapter({ | ||
filesSubDirectory: directory, | ||
encryptionKey: oldEncryptionKey | ||
}); | ||
const encryptedAdapter = new FileSystemAdapter({ | ||
filesSubDirectory: directory, | ||
encryptionKey: 'newKeyThatILove' | ||
}); | ||
const unEncryptedAdapter = new FileSystemAdapter({ | ||
filesSubDirectory: directory | ||
}); | ||
const fileName1 = 'file1.txt'; | ||
const data1 = "hello world"; | ||
const fileName2 = 'file2.txt'; | ||
const data2 = "hello new world"; | ||
const filePath1 = 'files/'+directory+'/'+fileName1; | ||
const filePath2 = 'files/'+directory+'/'+fileName2; | ||
//Store original encrypted files | ||
await oldEncryptedAdapter.createFile(fileName1, data1, 'text/utf8'); | ||
var result = await oldEncryptedAdapter.getFileData(fileName1); | ||
expect(result instanceof Buffer).toBe(true); | ||
expect(result.toString('utf-8')).toEqual(data1); | ||
const oldEncryptedData1 = fs.readFileSync(filePath1); | ||
await oldEncryptedAdapter.createFile(fileName2, data2, 'text/utf8'); | ||
result = await oldEncryptedAdapter.getFileData(fileName2); | ||
expect(result instanceof Buffer).toBe(true); | ||
expect(result.toString('utf-8')).toEqual(data2); | ||
const oldEncryptedData2 = fs.readFileSync(filePath2); | ||
//Inject unecrypted file to cause an issue | ||
const fileName3 = 'file3.txt'; | ||
const data3 = "hello past world"; | ||
const filePath3 = 'files/'+directory+'/'+fileName3; | ||
await unEncryptedAdapter.createFile(fileName3, data3, 'text/utf8'); | ||
var result = await unEncryptedAdapter.getFileData(fileName3); | ||
expect(result instanceof Buffer).toBe(true); | ||
expect(result.toString('utf-8')).toEqual(data3); | ||
//Check if encrypted adapter can read data and make sure it's not the same as unEncrypted adapter | ||
const {rotated, notRotated} = await encryptedAdapter.rotateEncryptionKey({oldKey: oldEncryptionKey}); | ||
expect(rotated.length).toEqual(2); | ||
expect(rotated.filter(function(value){ return value === fileName1;}).length).toEqual(1); | ||
expect(rotated.filter(function(value){ return value === fileName2;}).length).toEqual(1); | ||
expect(notRotated.length).toEqual(1); | ||
expect(notRotated.filter(function(value){ return value === fileName3;}).length).toEqual(1); | ||
var result2 = await encryptedAdapter.getFileData(fileName1); | ||
expect(result2 instanceof Buffer).toBe(true); | ||
expect(result2.toString('utf-8')).toEqual(data1); | ||
const encryptedData1 = fs.readFileSync(filePath1); | ||
expect(encryptedData1.toString('utf-8')).not.toEqual(oldEncryptedData1); | ||
result = await encryptedAdapter.getFileData(fileName2); | ||
expect(result instanceof Buffer).toBe(true); | ||
expect(result.toString('utf-8')).toEqual(data2); | ||
const encryptedData2 = fs.readFileSync(filePath2); | ||
expect(encryptedData2.toString('utf-8')).not.toEqual(oldEncryptedData2); | ||
}, 5000); | ||
it("should return fileNames of those it can't encrypt with the new key", async function() { | ||
const oldEncryptionKey = 'oldKeyThatILoved'; | ||
const oldEncryptedAdapter = new FileSystemAdapter({ | ||
filesSubDirectory: directory, | ||
encryptionKey: oldEncryptionKey | ||
}); | ||
const encryptedAdapter = new FileSystemAdapter({ | ||
filesSubDirectory: directory, | ||
encryptionKey: 'newKeyThatILove' | ||
}); | ||
const unEncryptedAdapter = new FileSystemAdapter({ | ||
filesSubDirectory: directory | ||
}); | ||
const fileName1 = 'file1.txt'; | ||
const data1 = "hello world"; | ||
const fileName2 = 'file2.txt'; | ||
const data2 = "hello new world"; | ||
const filePath1 = 'files/' + directory + '/' + fileName1; | ||
const filePath2 = 'files/' + directory + '/' + fileName2; | ||
// Store original encrypted files | ||
await oldEncryptedAdapter.createFile(fileName1, data1, 'text/utf8'); | ||
let result = await oldEncryptedAdapter.getFileData(fileName1); | ||
expect(result instanceof Buffer).toBe(true); | ||
expect(result.toString('utf-8')).toEqual(data1); | ||
const oldEncryptedData1 = fs.readFileSync(filePath1); | ||
await oldEncryptedAdapter.createFile(fileName2, data2, 'text/utf8'); | ||
result = await oldEncryptedAdapter.getFileData(fileName2); | ||
expect(result instanceof Buffer).toBe(true); | ||
expect(result.toString('utf-8')).toEqual(data2); | ||
const oldEncryptedData2 = fs.readFileSync(filePath2); | ||
// Inject unecrypted file to cause an issue | ||
const fileName3 = 'file3.txt'; | ||
const data3 = "hello past world"; | ||
await unEncryptedAdapter.createFile(fileName3, data3, 'text/utf8'); | ||
result = await unEncryptedAdapter.getFileData(fileName3); | ||
expect(result instanceof Buffer).toBe(true); | ||
expect(result.toString('utf-8')).toEqual(data3); | ||
// Check if encrypted adapter can read data and make sure it's not the same as unEncrypted adapter | ||
const {rotated, notRotated} = await encryptedAdapter.rotateEncryptionKey({oldKey: oldEncryptionKey}); | ||
expect(rotated.length).toEqual(2); | ||
expect(rotated.filter(function(value){ return value === fileName1;}).length).toEqual(1); | ||
expect(rotated.filter(function(value){ return value === fileName2;}).length).toEqual(1); | ||
expect(notRotated.length).toEqual(1); | ||
expect(notRotated.filter(function(value){ return value === fileName3;}).length).toEqual(1); | ||
const result2 = await encryptedAdapter.getFileData(fileName1); | ||
expect(result2 instanceof Buffer).toBe(true); | ||
expect(result2.toString('utf-8')).toEqual(data1); | ||
const encryptedData1 = fs.readFileSync(filePath1); | ||
expect(encryptedData1.toString('utf-8')).not.toEqual(oldEncryptedData1); | ||
result = await encryptedAdapter.getFileData(fileName2); | ||
expect(result instanceof Buffer).toBe(true); | ||
expect(result.toString('utf-8')).toEqual(data2); | ||
const encryptedData2 = fs.readFileSync(filePath2); | ||
expect(encryptedData2.toString('utf-8')).not.toEqual(oldEncryptedData2); | ||
}, 5000); | ||
}) |
'use strict'; | ||
let filesAdapterTests = require('parse-server-conformance-tests').files; | ||
const filesAdapterTests = require('parse-server-conformance-tests').files; | ||
const FileSystemAdapter = require('../index.js'); | ||
let FileSystemAdapter = require('../index.js'); | ||
describe('FileSystemAdapter tests', () => { | ||
var fsAdapter = new FileSystemAdapter({ | ||
describe('FileSystemAdapter tests', () => { | ||
const fsAdapter = new FileSystemAdapter({ | ||
filesSubDirectory: 'sub1/sub2' | ||
@@ -14,6 +13,6 @@ }); | ||
describe('FileSystemAdapter tests - no options', () => { | ||
var fsAdapter = new FileSystemAdapter(); | ||
describe('FileSystemAdapter tests - no options', () => { | ||
const fsAdapter = new FileSystemAdapter(); | ||
filesAdapterTests.testAdapter("FileSystemAdapter", fsAdapter); | ||
}) |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
19
120
44155
610