@iobroker/js-controller-common 4.0.0-alpha.9-20211115-5dac659e → 4.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +1 -1
- package/index.js +1 -1
- package/lib/common/exitCodes.js +5 -1
- package/lib/common/logger.js +152 -126
- package/lib/common/password.js +7 -9
- package/lib/common/tools.js +1075 -501
- package/package.json +8 -7
package/LICENSE
CHANGED
package/README.md
CHANGED
package/index.js
CHANGED
package/lib/common/exitCodes.js
CHANGED
|
@@ -45,13 +45,17 @@ const EXIT_CODES = {
|
|
|
45
45
|
CANNOT_UPDATE_VENDOR: 44,
|
|
46
46
|
INVALID_REPO: 45,
|
|
47
47
|
CANNOT_UPDATE_LICENSE: 46,
|
|
48
|
+
CANNOT_DELETE_DEPENDENCY: 47,
|
|
48
49
|
CANNOT_GET_STATES: 50,
|
|
49
50
|
ADAPTER_ALREADY_INSTALLED: 51,
|
|
51
|
+
CANNOT_RESTORE_BACKUP: 52,
|
|
52
|
+
MIGRATION_ERROR: 78,
|
|
50
53
|
CONTROLLER_RUNNING: 99,
|
|
51
54
|
CONTROLLER_NOT_RUNNING: 100,
|
|
52
55
|
CANNOT_GET_UUID: 101,
|
|
53
56
|
CANNOT_GET_REPO_LIST: 102,
|
|
54
|
-
START_IMMEDIATELY_AFTER_STOP: 156
|
|
57
|
+
START_IMMEDIATELY_AFTER_STOP: 156,
|
|
58
|
+
FILE_NOT_FOUND: 404
|
|
55
59
|
};
|
|
56
60
|
// Allow reverse lookup (exit code -> error name)
|
|
57
61
|
for (const [name, code] of Object.entries(EXIT_CODES)) {
|
package/lib/common/logger.js
CHANGED
|
@@ -4,16 +4,16 @@
|
|
|
4
4
|
/* jslint esversion: 6 */
|
|
5
5
|
'use strict';
|
|
6
6
|
|
|
7
|
-
const winston
|
|
7
|
+
const winston = require('winston');
|
|
8
8
|
const DailyRotateFile = require('winston-daily-rotate-file');
|
|
9
|
-
const fs
|
|
10
|
-
const path
|
|
11
|
-
const os
|
|
12
|
-
const tools
|
|
13
|
-
const hostname
|
|
14
|
-
const Transport
|
|
15
|
-
const {LEVEL}
|
|
16
|
-
const deepClone
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
const os = require('os');
|
|
12
|
+
const tools = require('./tools');
|
|
13
|
+
const hostname = tools.getHostName();
|
|
14
|
+
const Transport = require('winston-transport');
|
|
15
|
+
const { LEVEL } = require('triple-beam');
|
|
16
|
+
const deepClone = require('deep-clone');
|
|
17
17
|
|
|
18
18
|
let SysLog;
|
|
19
19
|
try {
|
|
@@ -24,77 +24,76 @@ try {
|
|
|
24
24
|
|
|
25
25
|
let Seq;
|
|
26
26
|
try {
|
|
27
|
-
Seq = require('winston-seq
|
|
27
|
+
Seq = require('@datalust/winston-seq').SeqTransport;
|
|
28
28
|
} catch {
|
|
29
29
|
//console.log('No seq support');
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
// We must check if SysLog is defined before extending it
|
|
33
|
-
const IoSysLog =
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
log(info, callback) {
|
|
39
|
-
// we need to map the ioBroker loglevels to the Syslog ones
|
|
40
|
-
const ioInfo = info;
|
|
41
|
-
if (ioInfo[LEVEL] === 'warn') {
|
|
42
|
-
ioInfo[LEVEL] = 'warning';
|
|
43
|
-
}
|
|
44
|
-
if (ioInfo[LEVEL] === 'info') {
|
|
45
|
-
ioInfo[LEVEL] = 'notice';
|
|
46
|
-
}
|
|
47
|
-
if (ioInfo[LEVEL] === 'debug') {
|
|
48
|
-
ioInfo[LEVEL] = 'info';
|
|
33
|
+
const IoSysLog =
|
|
34
|
+
SysLog &&
|
|
35
|
+
class extends SysLog {
|
|
36
|
+
constructor(options) {
|
|
37
|
+
super(options);
|
|
49
38
|
}
|
|
50
|
-
if (ioInfo[LEVEL] === 'silly') {
|
|
51
|
-
ioInfo[LEVEL] = 'debug';
|
|
52
|
-
}
|
|
53
|
-
super.log(ioInfo, callback);
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
39
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
if (level.includes('error')) {
|
|
63
|
-
return 'Error';
|
|
40
|
+
log(info, callback) {
|
|
41
|
+
// we need to map the ioBroker loglevels to the Syslog ones
|
|
42
|
+
const ioInfo = info;
|
|
43
|
+
if (ioInfo[LEVEL] === 'warn') {
|
|
44
|
+
ioInfo[LEVEL] = 'warning';
|
|
64
45
|
}
|
|
65
|
-
if (
|
|
66
|
-
|
|
46
|
+
if (ioInfo[LEVEL] === 'info') {
|
|
47
|
+
ioInfo[LEVEL] = 'notice';
|
|
67
48
|
}
|
|
68
|
-
if (
|
|
69
|
-
|
|
49
|
+
if (ioInfo[LEVEL] === 'debug') {
|
|
50
|
+
ioInfo[LEVEL] = 'info';
|
|
70
51
|
}
|
|
71
|
-
if (
|
|
72
|
-
|
|
52
|
+
if (ioInfo[LEVEL] === 'silly') {
|
|
53
|
+
ioInfo[LEVEL] = 'debug';
|
|
73
54
|
}
|
|
74
|
-
|
|
75
|
-
|
|
55
|
+
super.log(ioInfo, callback);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// We want to enhance some data for Seq
|
|
60
|
+
const IoSeq =
|
|
61
|
+
Seq &&
|
|
62
|
+
class extends Seq {
|
|
63
|
+
log(info, callback) {
|
|
64
|
+
const ioInfo = info;
|
|
65
|
+
ioInfo.props = ioInfo.props || {};
|
|
66
|
+
|
|
67
|
+
// map our log levels to Seq levels
|
|
68
|
+
const level = (ioInfo.level || '').toLowerCase();
|
|
69
|
+
if (level.includes('error')) {
|
|
70
|
+
ioInfo.level = 'Error';
|
|
71
|
+
} else if (level.includes('warn')) {
|
|
72
|
+
ioInfo.level = 'Warning';
|
|
73
|
+
} else if (level.includes('info')) {
|
|
74
|
+
ioInfo.level = 'Information';
|
|
75
|
+
} else if (level.includes('debug')) {
|
|
76
|
+
ioInfo.level = 'Debug';
|
|
77
|
+
} else if (level.includes('silly')) {
|
|
78
|
+
ioInfo.level = 'Verbose';
|
|
79
|
+
} else {
|
|
80
|
+
ioInfo.level = 'Information';
|
|
76
81
|
}
|
|
77
|
-
return 'Information';
|
|
78
|
-
};
|
|
79
|
-
super(options);
|
|
80
|
-
}
|
|
81
82
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
ioInfo
|
|
83
|
+
// we add own properties
|
|
84
|
+
ioInfo.props.Hostname = tools.getHostName();
|
|
85
|
+
if (ioInfo.message) {
|
|
86
|
+
const msgParts = ioInfo.message.match(/^([^.]+\.[0-9]+) \(([^)]+)\) (.*)$/);
|
|
87
|
+
if (msgParts) {
|
|
88
|
+
ioInfo.props.Source = msgParts[1];
|
|
89
|
+
ioInfo.props.Pid = msgParts[2];
|
|
90
|
+
} else {
|
|
91
|
+
ioInfo.props.Source = 'js-controller';
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
super.log(ioInfo, callback);
|
|
94
95
|
}
|
|
95
|
-
|
|
96
|
-
}
|
|
97
|
-
};
|
|
96
|
+
};
|
|
98
97
|
|
|
99
98
|
// Class used to inform adapter about new log entry
|
|
100
99
|
class NotifierTransport extends Transport {
|
|
@@ -126,23 +125,25 @@ const logger = function (level, files, noStdout, prefix) {
|
|
|
126
125
|
files = [files];
|
|
127
126
|
}
|
|
128
127
|
|
|
129
|
-
const formatter = info =>
|
|
130
|
-
`${timestamp(info.timestamp)} - ${info.level}: ${info.message}`;
|
|
128
|
+
const formatter = info => `${timestamp(info.timestamp)} - ${info.level}: ${info.message}`;
|
|
131
129
|
|
|
132
130
|
files = files || [];
|
|
133
131
|
|
|
134
132
|
// indicator which is used to determine the log dir for developing, where it should be inside the repository
|
|
135
|
-
const isNpm = !__dirname
|
|
133
|
+
const isNpm = !__dirname
|
|
134
|
+
.replace(/\\/g, '/')
|
|
135
|
+
.toLowerCase()
|
|
136
|
+
.includes(tools.appName.toLowerCase() + `.js-controller/packages/`);
|
|
136
137
|
|
|
137
138
|
if (typeof level === 'object') {
|
|
138
139
|
userOptions = deepClone(level);
|
|
139
140
|
|
|
140
|
-
level
|
|
141
|
-
prefix
|
|
141
|
+
level = userOptions.level;
|
|
142
|
+
prefix = userOptions.prefix;
|
|
142
143
|
noStdout = userOptions.noStdout;
|
|
143
144
|
|
|
144
145
|
const winstonFormats = [];
|
|
145
|
-
winstonFormats.push(winston.format.timestamp({format: timestamp}));
|
|
146
|
+
winstonFormats.push(winston.format.timestamp({ format: timestamp }));
|
|
146
147
|
if (userOptions.json === undefined || userOptions.json) {
|
|
147
148
|
winstonFormats.push(winston.format.json());
|
|
148
149
|
}
|
|
@@ -160,12 +161,15 @@ const logger = function (level, files, noStdout, prefix) {
|
|
|
160
161
|
|
|
161
162
|
if (userOptions.transport) {
|
|
162
163
|
let fName = 0;
|
|
163
|
-
const isWindows = os.platform().
|
|
164
|
+
const isWindows = os.platform().startsWith('win');
|
|
164
165
|
Object.keys(userOptions.transport).forEach(f => {
|
|
165
166
|
const transport = userOptions.transport[f];
|
|
166
|
-
if (transport.type === 'file' && transport.enabled !== false) {
|
|
167
167
|
|
|
168
|
-
|
|
168
|
+
transport._defaultConfigLoglevel = transport.level; // remember Loglevel if set
|
|
169
|
+
transport.level = transport.level || level;
|
|
170
|
+
|
|
171
|
+
if (transport.type === 'file' && transport.enabled !== false) {
|
|
172
|
+
transport.filename = transport.filename || 'log/' + tools.appName;
|
|
169
173
|
|
|
170
174
|
if (!transport.fileext && transport.filename.indexOf('.log') === -1) {
|
|
171
175
|
transport.fileext = '.log';
|
|
@@ -176,39 +180,46 @@ const logger = function (level, files, noStdout, prefix) {
|
|
|
176
180
|
}
|
|
177
181
|
|
|
178
182
|
transport.handleExceptions = false;
|
|
179
|
-
transport.name
|
|
183
|
+
transport.name = !fName ? tools.appName : 'dailyRotateFile' + fName;
|
|
180
184
|
fName++;
|
|
181
|
-
transport.filename
|
|
185
|
+
transport.filename = transport.filename.replace(/\\/g, '/');
|
|
182
186
|
if (transport.filename.match(/^\w:\/|^\//)) {
|
|
183
187
|
transport.filename = path.normalize(transport.filename);
|
|
184
188
|
} else {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
_path = path.normalize(`${__dirname}/../../${transport.filename}`);
|
|
189
|
-
}
|
|
190
|
-
*/
|
|
191
|
-
|
|
192
|
-
transport.filename = _path;
|
|
189
|
+
transport.filename = path.normalize(
|
|
190
|
+
`${tools.getControllerDir()}${isNpm ? '/../../' : '/'}${transport.filename}`
|
|
191
|
+
);
|
|
193
192
|
}
|
|
194
|
-
transport.auditFile
|
|
193
|
+
transport.auditFile = transport.filename + '-audit.json';
|
|
195
194
|
|
|
196
|
-
transport.createSymlink =
|
|
197
|
-
|
|
195
|
+
transport.createSymlink =
|
|
196
|
+
transport.createSymlink !== undefined ? transport.createSymlink : !isWindows;
|
|
197
|
+
transport.symlinkName =
|
|
198
|
+
transport.symlinkName !== undefined
|
|
199
|
+
? transport.symlinkName
|
|
200
|
+
: path.basename(transport.filename + '.current.log');
|
|
198
201
|
|
|
199
|
-
transport.filename
|
|
202
|
+
transport.filename += '.%DATE%' + (transport.fileext || '');
|
|
200
203
|
//transport.label = prefix || ''; //TODO format.label()
|
|
201
|
-
transport.level = transport.level || level;
|
|
202
204
|
// transport.json = (transport.json !== undefined) ? transport.json : false; // TODO format.json(), new Default!!
|
|
203
|
-
transport.silent
|
|
205
|
+
transport.silent = transport.silent !== undefined ? transport.silent : false;
|
|
204
206
|
// transport.colorize = (transport.colorize !== undefined) ? transport.colorize : ((userOptions.colorize === undefined) ? true : userOptions.colorize); //TODO format.colorize()
|
|
205
|
-
transport.localTime
|
|
206
|
-
|
|
207
|
-
|
|
207
|
+
transport.localTime =
|
|
208
|
+
transport.localTime !== undefined
|
|
209
|
+
? transport.localTime
|
|
210
|
+
: userOptions.localTime === undefined
|
|
211
|
+
? true
|
|
212
|
+
: userOptions.localTime;
|
|
213
|
+
transport.datePattern = 'YYYY-MM-DD';
|
|
214
|
+
transport.format = winston.format.combine(winston.format.printf(formatter));
|
|
208
215
|
/*transport.logException = function (message, info, next, err) {
|
|
209
216
|
console.error(message);
|
|
210
217
|
};*/
|
|
211
|
-
transport.zippedArchive = isWindows
|
|
218
|
+
transport.zippedArchive = isWindows
|
|
219
|
+
? false
|
|
220
|
+
: transport.zippedArchive !== undefined
|
|
221
|
+
? transport.zippedArchive
|
|
222
|
+
: true;
|
|
212
223
|
|
|
213
224
|
if (transport.maxFiles === null && userOptions.maxDays) {
|
|
214
225
|
transport.maxFiles = userOptions.maxDays + 'd';
|
|
@@ -253,7 +264,7 @@ const logger = function (level, files, noStdout, prefix) {
|
|
|
253
264
|
try {
|
|
254
265
|
options.transports.push(new IoSysLog(transport));
|
|
255
266
|
} catch (err) {
|
|
256
|
-
console.log(`Cannot activate Syslog: ${err}`);
|
|
267
|
+
console.log(`Cannot activate Syslog: ${err.message}`);
|
|
257
268
|
}
|
|
258
269
|
} else if (transport.type === 'http' && transport.enabled !== false) {
|
|
259
270
|
// host: (Default: localhost) Remote host of the HTTP logging endpoint
|
|
@@ -268,7 +279,7 @@ const logger = function (level, files, noStdout, prefix) {
|
|
|
268
279
|
try {
|
|
269
280
|
options.transports.push(new winston.transports.Http(transport));
|
|
270
281
|
} catch (err) {
|
|
271
|
-
console.log(
|
|
282
|
+
console.log(`Cannot activate HTTP: ${err.message}`);
|
|
272
283
|
}
|
|
273
284
|
} else if (transport.type === 'stream' && transport.enabled !== false) {
|
|
274
285
|
// stream: any Node.js stream. If an objectMode stream is provided then the entire info object will be written. Otherwise info[MESSAGE] will be written.
|
|
@@ -283,7 +294,7 @@ const logger = function (level, files, noStdout, prefix) {
|
|
|
283
294
|
if (typeof transport.stream === 'string') {
|
|
284
295
|
transport.stream = fs.createWriteStream(transport.stream);
|
|
285
296
|
transport.stream.on('error', err => {
|
|
286
|
-
console.log(
|
|
297
|
+
console.log(`Error in Stream: ${err}`);
|
|
287
298
|
});
|
|
288
299
|
}
|
|
289
300
|
|
|
@@ -301,13 +312,13 @@ const logger = function (level, files, noStdout, prefix) {
|
|
|
301
312
|
// Add only if serverUrl is configured at least
|
|
302
313
|
if (transport.serverUrl) {
|
|
303
314
|
try {
|
|
315
|
+
transport.onError = e => {
|
|
316
|
+
console.log(`SEQ error: ${e}`);
|
|
317
|
+
};
|
|
304
318
|
const seqLogger = new IoSeq(transport);
|
|
305
|
-
seqLogger.on('error', error => {
|
|
306
|
-
console.log(`SEQ error: ${error}`);
|
|
307
|
-
});
|
|
308
319
|
options.transports.push(seqLogger);
|
|
309
320
|
} catch (err) {
|
|
310
|
-
console.log(`Cannot activate SEQ: ${err}`);
|
|
321
|
+
console.log(`Cannot activate SEQ: ${err.message}`);
|
|
311
322
|
}
|
|
312
323
|
} else {
|
|
313
324
|
console.log('Cannot activate SEQ: No serverUrl specified');
|
|
@@ -318,14 +329,16 @@ const logger = function (level, files, noStdout, prefix) {
|
|
|
318
329
|
} else {
|
|
319
330
|
for (let i = 0; i < files.length; i++) {
|
|
320
331
|
const opt = {
|
|
321
|
-
name:
|
|
322
|
-
filename:
|
|
323
|
-
|
|
324
|
-
|
|
332
|
+
name: i ? 'dailyRotateFile' + i : tools.appName,
|
|
333
|
+
filename: path.normalize(
|
|
334
|
+
isNpm ? `${__dirname}/../../../log/${files[i]}` : `${__dirname}/../log/${files[i]}`
|
|
335
|
+
),
|
|
336
|
+
extension: '.log',
|
|
337
|
+
datePattern: 'YYYY-MM-DD',
|
|
325
338
|
//json: false, // If true, messages will be logged as JSON (default true). TODO format.json()
|
|
326
339
|
level,
|
|
327
|
-
silent:
|
|
328
|
-
localTime:
|
|
340
|
+
silent: false,
|
|
341
|
+
localTime: true,
|
|
329
342
|
//colorize: (userOptions.colorize === undefined) ? true : userOptions.colorize, // TODO format.colorize()
|
|
330
343
|
//timestamp: timestamp, // TODO: format.timestamp()
|
|
331
344
|
//label: prefix || '', // TODO format.label()
|
|
@@ -338,21 +351,25 @@ const logger = function (level, files, noStdout, prefix) {
|
|
|
338
351
|
}
|
|
339
352
|
|
|
340
353
|
if (!noStdout) {
|
|
341
|
-
options.transports.push(
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
354
|
+
options.transports.push(
|
|
355
|
+
new winston.transports.Console({
|
|
356
|
+
level,
|
|
357
|
+
silent: false,
|
|
358
|
+
format: winston.format.combine(winston.format.printf(formatter))
|
|
359
|
+
//colorize: (userOptions.colorize === undefined) ? true : userOptions.colorize, // TODO format.colorize()
|
|
360
|
+
//timestamp: timestamp, // TODO: format.timestamp()
|
|
361
|
+
//label: prefix || '' // TODO format.label()
|
|
362
|
+
})
|
|
363
|
+
);
|
|
349
364
|
}
|
|
350
365
|
|
|
351
366
|
// Must be registered, for adapter.js notification about new logs
|
|
352
|
-
options.transports.push(
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
367
|
+
options.transports.push(
|
|
368
|
+
new NotifierTransport({
|
|
369
|
+
level,
|
|
370
|
+
silent: false
|
|
371
|
+
})
|
|
372
|
+
);
|
|
356
373
|
|
|
357
374
|
const log = winston.createLogger(options);
|
|
358
375
|
|
|
@@ -383,7 +400,11 @@ const logger = function (level, files, noStdout, prefix) {
|
|
|
383
400
|
// Check every hour
|
|
384
401
|
this._fileChecker = setInterval(() => {
|
|
385
402
|
this.transports.forEach(transport => {
|
|
386
|
-
if (
|
|
403
|
+
if (
|
|
404
|
+
transport.name !== 'dailyRotateFile' ||
|
|
405
|
+
!transport.options ||
|
|
406
|
+
transport.options.name !== tools.appName
|
|
407
|
+
) {
|
|
387
408
|
return;
|
|
388
409
|
}
|
|
389
410
|
|
|
@@ -414,10 +435,16 @@ const logger = function (level, files, noStdout, prefix) {
|
|
|
414
435
|
} catch (e) {
|
|
415
436
|
// there is a bug under windows, that file stays opened and cannot be deleted
|
|
416
437
|
this.log({
|
|
417
|
-
level: os.platform().
|
|
418
|
-
message: `host.${hostname} Cannot delete file "${path.normalize(
|
|
438
|
+
level: os.platform().startsWith('win') ? 'info' : 'error',
|
|
439
|
+
message: `host.${hostname} Cannot delete file "${path.normalize(
|
|
440
|
+
transport.dirname + '/' + files[i]
|
|
441
|
+
)}": ${e}`
|
|
419
442
|
});
|
|
420
|
-
console.log(
|
|
443
|
+
console.log(
|
|
444
|
+
`host.${hostname} Cannot delete file "${path.normalize(
|
|
445
|
+
transport.dirname + '/' + files[i]
|
|
446
|
+
)}": ${e}`
|
|
447
|
+
);
|
|
421
448
|
}
|
|
422
449
|
}
|
|
423
450
|
}
|
|
@@ -490,8 +517,7 @@ function timestamp(date) {
|
|
|
490
517
|
value = ts.getMilliseconds();
|
|
491
518
|
if (value < 10) {
|
|
492
519
|
value = '00' + value;
|
|
493
|
-
} else
|
|
494
|
-
if (value < 100) {
|
|
520
|
+
} else if (value < 100) {
|
|
495
521
|
value = '0' + value;
|
|
496
522
|
}
|
|
497
523
|
|
package/lib/common/password.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
*
|
|
3
3
|
* password hash and check
|
|
4
4
|
*
|
|
5
|
-
* 7'2014-
|
|
5
|
+
* 7'2014-2022 Bluefox <dogafox@gmail.com>
|
|
6
6
|
* 2014 hobbyquaker <hq@ccu.io>
|
|
7
7
|
*
|
|
8
8
|
* derived from https://github.com/florianheinemann/password-hash-and-salt/ (MIT License)
|
|
@@ -34,20 +34,19 @@
|
|
|
34
34
|
/* jslint node: true */
|
|
35
35
|
'use strict';
|
|
36
36
|
|
|
37
|
-
const crypto
|
|
38
|
-
let
|
|
37
|
+
const crypto = require('crypto');
|
|
38
|
+
let version = null;
|
|
39
39
|
|
|
40
40
|
const password = pw => {
|
|
41
41
|
return {
|
|
42
42
|
hash: (salt, iterations, callback) => {
|
|
43
|
-
|
|
44
43
|
salt = salt || crypto.randomBytes(16).toString('hex');
|
|
45
44
|
iterations = iterations || 10000;
|
|
46
45
|
|
|
47
46
|
// version 0.10 has no 'sha256' and this option must be ignored
|
|
48
47
|
if (version === null) {
|
|
49
48
|
version = process.version.replace('v', '');
|
|
50
|
-
version = !version.
|
|
49
|
+
version = !version.startsWith('0.10.');
|
|
51
50
|
}
|
|
52
51
|
|
|
53
52
|
if (version) {
|
|
@@ -66,7 +65,6 @@ const password = pw => {
|
|
|
66
65
|
|
|
67
66
|
callback(null, `pbkdf2$${iterations}$${key.toString('hex')}$${salt}`);
|
|
68
67
|
});
|
|
69
|
-
|
|
70
68
|
}
|
|
71
69
|
},
|
|
72
70
|
check: function (hashedPassword, callback) {
|
|
@@ -93,10 +91,10 @@ const password = pw => {
|
|
|
93
91
|
let result = false;
|
|
94
92
|
if (typeof password === 'string') {
|
|
95
93
|
result =
|
|
96
|
-
password.length >= 8 &&
|
|
97
|
-
password.match(/\d/) &&
|
|
94
|
+
password.length >= 8 && // minimum length is 8
|
|
95
|
+
password.match(/\d/) && // contains at least one digit
|
|
98
96
|
password.match(/[a-z]/) && // contains at least one lower case letter
|
|
99
|
-
password.match(/[A-Z]/);
|
|
97
|
+
password.match(/[A-Z]/); // contains at least one upper case letter
|
|
100
98
|
}
|
|
101
99
|
typeof callback === 'function' && callback(result);
|
|
102
100
|
return result; // true if the complexity OK
|