4
4
// Stores files in local file system
5
5
// Requires write access to the server's file system.
6
6
7
- var fs = require ( 'fs' ) ;
8
- var path = require ( 'path' ) ;
9
- var pathSep = require ( 'path' ) . sep ;
7
+ const fs = require ( 'fs' ) ;
8
+ const path = require ( 'path' ) ;
9
+ const pathSep = require ( 'path' ) . sep ;
10
10
const crypto = require ( "crypto" ) ;
11
11
const algorithm = 'aes-256-gcm' ;
12
12
13
13
function FileSystemAdapter ( options ) {
14
14
options = options || { } ;
15
15
this . _encryptionKey = null ;
16
16
17
- if ( options . encryptionKey !== undefined ) {
18
- this . _encryptionKey = crypto . createHash ( 'sha256' ) . update ( String ( options . encryptionKey ) ) . digest ( 'base64' ) . substr ( 0 , 32 ) ;
17
+ if ( options . encryptionKey !== undefined ) {
18
+ this . _encryptionKey = crypto . createHash ( 'sha256' ) . update ( String ( options . encryptionKey ) ) . digest ( 'base64' ) . substring ( 0 , 32 ) ;
19
19
}
20
- let filesSubDirectory = options . filesSubDirectory || '' ;
20
+ const filesSubDirectory = options . filesSubDirectory || '' ;
21
21
this . _filesDir = filesSubDirectory ;
22
22
this . _mkdir ( this . _getApplicationDir ( ) ) ;
23
23
if ( ! this . _applicationDirExist ( ) ) {
@@ -26,11 +26,11 @@ function FileSystemAdapter(options) {
26
26
}
27
27
28
28
FileSystemAdapter . prototype . createFile = function ( filename , data ) {
29
- let filepath = this . _getLocalFilePath ( filename ) ;
29
+ const filepath = this . _getLocalFilePath ( filename ) ;
30
30
const stream = fs . createWriteStream ( filepath ) ;
31
31
return new Promise ( ( resolve , reject ) => {
32
- try {
33
- if ( this . _encryptionKey !== null ) {
32
+ try {
33
+ if ( this . _encryptionKey !== null ) {
34
34
const iv = crypto . randomBytes ( 16 ) ;
35
35
const cipher = crypto . createCipheriv (
36
36
algorithm ,
@@ -48,21 +48,21 @@ FileSystemAdapter.prototype.createFile = function(filename, data) {
48
48
stream . on ( 'finish' , function ( ) {
49
49
resolve ( data ) ;
50
50
} ) ;
51
- } else {
51
+ } else {
52
52
stream . write ( data ) ;
53
53
stream . end ( ) ;
54
54
stream . on ( 'finish' , function ( ) {
55
55
resolve ( data ) ;
56
56
} ) ;
57
- }
58
- } catch ( err ) {
57
+ }
58
+ } catch ( err ) {
59
59
return reject ( err ) ;
60
60
}
61
61
} ) ;
62
62
}
63
63
64
64
FileSystemAdapter . prototype . deleteFile = function ( filename ) {
65
- let filepath = this . _getLocalFilePath ( filename ) ;
65
+ const filepath = this . _getLocalFilePath ( filename ) ;
66
66
const chunks = [ ] ;
67
67
const stream = fs . createReadStream ( filepath ) ;
68
68
return new Promise ( ( resolve , reject ) => {
@@ -86,7 +86,7 @@ FileSystemAdapter.prototype.deleteFile = function(filename) {
86
86
}
87
87
88
88
FileSystemAdapter . prototype . getFileData = function ( filename ) {
89
- let filepath = this . _getLocalFilePath ( filename ) ;
89
+ const filepath = this . _getLocalFilePath ( filename ) ;
90
90
const stream = fs . createReadStream ( filepath ) ;
91
91
stream . read ( ) ;
92
92
return new Promise ( ( resolve , reject ) => {
@@ -96,18 +96,18 @@ FileSystemAdapter.prototype.getFileData = function(filename) {
96
96
} ) ;
97
97
stream . on ( 'end' , ( ) => {
98
98
const data = Buffer . concat ( chunks ) ;
99
- if ( this . _encryptionKey !== null ) {
99
+ if ( this . _encryptionKey !== null ) {
100
100
const authTagLocation = data . length - 16 ;
101
101
const ivLocation = data . length - 32 ;
102
102
const authTag = data . slice ( authTagLocation ) ;
103
103
const iv = data . slice ( ivLocation , authTagLocation ) ;
104
104
const encrypted = data . slice ( 0 , ivLocation ) ;
105
- try {
105
+ try {
106
106
const decipher = crypto . createDecipheriv ( algorithm , this . _encryptionKey , iv ) ;
107
107
decipher . setAuthTag ( authTag ) ;
108
- const decrypted = Buffer . concat ( [ decipher . update ( encrypted ) , decipher . final ( ) ] ) ;
108
+ const decrypted = Buffer . concat ( [ decipher . update ( encrypted ) , decipher . final ( ) ] ) ;
109
109
return resolve ( decrypted ) ;
110
- } catch ( err ) {
110
+ } catch ( err ) {
111
111
return reject ( err ) ;
112
112
}
113
113
}
@@ -119,55 +119,36 @@ FileSystemAdapter.prototype.getFileData = function(filename) {
119
119
} ) ;
120
120
}
121
121
122
- FileSystemAdapter . prototype . rotateEncryptionKey = function ( options = { } ) {
122
+ FileSystemAdapter . prototype . rotateEncryptionKey = async function ( options = { } ) {
123
123
const applicationDir = this . _getApplicationDir ( ) ;
124
- var fileNames = [ ] ;
125
- var oldKeyFileAdapter = { } ;
124
+ let fileNames = [ ] ;
125
+ let oldKeyFileAdapter = { } ;
126
126
if ( options . oldKey !== undefined ) {
127
- oldKeyFileAdapter = new FileSystemAdapter ( { filesSubDirectory : this . _filesDir , encryptionKey : options . oldKey } ) ;
128
- } else {
129
- oldKeyFileAdapter = new FileSystemAdapter ( { filesSubDirectory : this . _filesDir } ) ;
127
+ oldKeyFileAdapter = new FileSystemAdapter ( { filesSubDirectory : this . _filesDir , encryptionKey : options . oldKey } ) ;
128
+ } else {
129
+ oldKeyFileAdapter = new FileSystemAdapter ( { filesSubDirectory : this . _filesDir } ) ;
130
130
}
131
- if ( options . fileNames !== undefined ) {
131
+ if ( options . fileNames !== undefined ) {
132
132
fileNames = options . fileNames ;
133
- } else {
134
- fileNames = fs . readdirSync ( applicationDir ) ;
135
- fileNames = fileNames . filter ( fileName => fileName . indexOf ( '.' ) !== 0 ) ;
133
+ } else {
134
+ fileNames = fs . readdirSync ( applicationDir ) ;
135
+ fileNames = fileNames . filter ( fileName => fileName . indexOf ( '.' ) !== 0 ) ;
136
136
}
137
- return new Promise ( ( resolve , _reject ) => {
138
- var fileNamesNotRotated = fileNames ;
139
- var fileNamesRotated = [ ] ;
140
- var fileNameTotal = fileNames . length ;
141
- var fileNameIndex = 0 ;
142
- fileNames . forEach ( fileName => {
143
- oldKeyFileAdapter
144
- . getFileData ( fileName )
145
- . then ( plainTextData => {
146
- //Overwrite file with data encrypted with new key
147
- this . createFile ( fileName , plainTextData )
148
- . then ( ( ) => {
149
- fileNamesRotated . push ( fileName ) ;
150
- fileNamesNotRotated = fileNamesNotRotated . filter ( function ( value ) { return value !== fileName ; } )
151
- fileNameIndex += 1 ;
152
- if ( fileNameIndex == fileNameTotal ) {
153
- resolve ( { rotated : fileNamesRotated , notRotated : fileNamesNotRotated } ) ;
154
- }
155
- } )
156
- . catch ( ( ) => {
157
- fileNameIndex += 1 ;
158
- if ( fileNameIndex == fileNameTotal ) {
159
- resolve ( { rotated : fileNamesRotated , notRotated : fileNamesNotRotated } ) ;
160
- }
161
- } )
162
- } )
163
- . catch ( ( ) => {
164
- fileNameIndex += 1 ;
165
- if ( fileNameIndex == fileNameTotal ) {
166
- resolve ( { rotated : fileNamesRotated , notRotated : fileNamesNotRotated } ) ;
167
- }
168
- } ) ;
169
- } ) ;
170
- } ) ;
137
+
138
+ let fileNamesNotRotated = fileNames ;
139
+ const fileNamesRotated = [ ] ;
140
+ for ( const fileName of fileNames ) {
141
+ try {
142
+ const plainTextData = await oldKeyFileAdapter . getFileData ( fileName )
143
+ // Overwrite file with data encrypted with new key
144
+ await this . createFile ( fileName , plainTextData )
145
+ fileNamesRotated . push ( fileName ) ;
146
+ fileNamesNotRotated = fileNamesNotRotated . filter ( function ( value ) { return value !== fileName ; } ) ;
147
+ } catch ( err ) {
148
+ continue ;
149
+ }
150
+ }
151
+ return { rotated : fileNamesRotated , notRotated : fileNamesNotRotated } ;
171
152
}
172
153
173
154
FileSystemAdapter . prototype . getFileLocation = function ( config , filename ) {
@@ -177,20 +158,20 @@ FileSystemAdapter.prototype.getFileLocation = function(config, filename) {
177
158
/*
178
159
Helpers
179
160
--------------- */
180
- FileSystemAdapter . prototype . _getApplicationDir = function ( ) {
161
+ FileSystemAdapter . prototype . _getApplicationDir = function ( ) {
181
162
if ( this . _filesDir ) {
182
163
return path . join ( 'files' , this . _filesDir ) ;
183
164
} else {
184
165
return 'files' ;
185
166
}
186
- }
167
+ }
187
168
188
169
FileSystemAdapter . prototype . _applicationDirExist = function ( ) {
189
170
return fs . existsSync ( this . _getApplicationDir ( ) ) ;
190
171
}
191
172
192
173
FileSystemAdapter . prototype . _getLocalFilePath = function ( filename ) {
193
- let applicationDir = this . _getApplicationDir ( ) ;
174
+ const applicationDir = this . _getApplicationDir ( ) ;
194
175
if ( ! fs . existsSync ( applicationDir ) ) {
195
176
this . _mkdir ( applicationDir ) ;
196
177
}
@@ -199,20 +180,19 @@ FileSystemAdapter.prototype._getLocalFilePath = function(filename) {
199
180
200
181
FileSystemAdapter . prototype . _mkdir = function ( dirPath ) {
201
182
// snippet found on -> https://gist.github.com/danherbert-epam/3960169
202
- let dirs = dirPath . split ( pathSep ) ;
203
- var root = "" ;
183
+ const dirs = dirPath . split ( pathSep ) ;
184
+ let root = "" ;
204
185
205
186
while ( dirs . length > 0 ) {
206
- var dir = dirs . shift ( ) ;
187
+ const dir = dirs . shift ( ) ;
207
188
if ( dir === "" ) { // If directory starts with a /, the first path will be an empty string.
208
189
root = pathSep ;
209
190
}
210
191
if ( ! fs . existsSync ( path . join ( root , dir ) ) ) {
211
192
try {
212
193
fs . mkdirSync ( path . join ( root , dir ) ) ;
213
- }
214
- catch ( e ) {
215
- if ( e . code == 'EACCES' ) {
194
+ } catch ( err ) {
195
+ if ( err . code == 'EACCES' ) {
216
196
throw new Error ( "PERMISSION ERROR: In order to use the FileSystemAdapter, write access to the server's file system is required." ) ;
217
197
}
218
198
}
0 commit comments