larvituser 0.19.0 → 0.20.4
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/README.md +74 -99
- package/dbmigration/2.js +18 -57
- package/dist/dataWriter.d.ts +27 -0
- package/dist/dataWriter.d.ts.map +1 -0
- package/dist/dataWriter.js +204 -0
- package/dist/dataWriter.js.map +1 -0
- package/dist/helpers.d.ts +19 -0
- package/dist/helpers.d.ts.map +1 -0
- package/dist/helpers.js +60 -0
- package/dist/helpers.js.map +1 -0
- package/dist/index.d.ts +156 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +418 -0
- package/dist/index.js.map +1 -0
- package/dist/userBase.d.ts +53 -0
- package/dist/userBase.d.ts.map +1 -0
- package/dist/userBase.js +120 -0
- package/dist/userBase.js.map +1 -0
- package/dist/users.d.ts +43 -0
- package/dist/users.d.ts.map +1 -0
- package/dist/users.js +186 -0
- package/dist/users.js.map +1 -0
- package/package.json +28 -12
- package/.eslintignore +0 -1
- package/.eslintrc +0 -35
- package/.travis.yml +0 -22
- package/config/db_travis.json +0 -9
- package/dataWriter.js +0 -716
- package/helpers.js +0 -110
- package/index.js +0 -953
- package/renovate.json +0 -9
- package/test/00test.js +0 -850
- package/test/98lint.js +0 -9
- package/users.js +0 -281
package/index.js
DELETED
|
@@ -1,953 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const topLogPrefix = 'larvituser: index.js: ',
|
|
4
|
-
DataWriter = require(__dirname + '/dataWriter.js'),
|
|
5
|
-
Intercom = require('larvitamintercom'),
|
|
6
|
-
uuidLib = require('uuid'),
|
|
7
|
-
Helpers = require(__dirname + '/helpers.js'),
|
|
8
|
-
LUtils = require('larvitutils'),
|
|
9
|
-
bcrypt = require('bcryptjs'),
|
|
10
|
-
async = require('async');
|
|
11
|
-
|
|
12
|
-
function User(options, cb) {
|
|
13
|
-
const logPrefix = topLogPrefix + 'User() - ',
|
|
14
|
-
that = this;
|
|
15
|
-
|
|
16
|
-
if (typeof cb !== 'function') {
|
|
17
|
-
cb = function () {};
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
that.options = options || {};
|
|
21
|
-
|
|
22
|
-
if ( ! options.log) {
|
|
23
|
-
const tmpLUtils = new LUtils();
|
|
24
|
-
options.log = new tmpLUtils.Log();
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
that.options = options;
|
|
28
|
-
|
|
29
|
-
for (const key of Object.keys(options)) {
|
|
30
|
-
that[key] = options[key];
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
that.lUtils = new LUtils({'log': that.log});
|
|
34
|
-
|
|
35
|
-
if ( ! that.db) {
|
|
36
|
-
const err = new Error('Required option db is missing');
|
|
37
|
-
that.log.error(logPrefix + err.message);
|
|
38
|
-
throw err;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
if ( ! that.exchangeName) {
|
|
42
|
-
that.exchangeName = 'larvituser';
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
if ( ! that.mode) {
|
|
46
|
-
that.log.info(logPrefix + 'No "mode" option given, defaulting to "noSync"');
|
|
47
|
-
that.mode = 'noSync';
|
|
48
|
-
} else if (['noSync', 'master', 'slave'].indexOf(that.mode) === - 1) {
|
|
49
|
-
const err = new Error('Invalid "mode" option given: "' + that.mode + '"');
|
|
50
|
-
that.log.error(logPrefix + err.message);
|
|
51
|
-
throw err;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if ( ! that.intercom) {
|
|
55
|
-
that.log.info(logPrefix + 'No "intercom" option given, defaulting to "loopback interface"');
|
|
56
|
-
that.intercom = new Intercom('loopback interface');
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
that.dataWriter = new DataWriter({
|
|
60
|
-
'exchangeName': that.exchangeName,
|
|
61
|
-
'intercom': that.intercom,
|
|
62
|
-
'mode': that.mode,
|
|
63
|
-
'log': that.log,
|
|
64
|
-
'db': that.db,
|
|
65
|
-
'amsync': that.options.amsync,
|
|
66
|
-
}, function (err) {
|
|
67
|
-
if (err) return cb(err);
|
|
68
|
-
|
|
69
|
-
that.helpers = new Helpers({
|
|
70
|
-
'dataWriter': that.dataWriter,
|
|
71
|
-
'log': that.log,
|
|
72
|
-
'db': that.db
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
cb();
|
|
76
|
-
});
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Add a single user field to database
|
|
81
|
-
*
|
|
82
|
-
* @param str userUuid
|
|
83
|
-
* @param str fieldName
|
|
84
|
-
* @param str fieldValue
|
|
85
|
-
* @param func cb(err)
|
|
86
|
-
*/
|
|
87
|
-
User.prototype.addUserDataField = function addUserDataField(userUuid, fieldName, fieldValue, cb) {
|
|
88
|
-
const fields = {},
|
|
89
|
-
that = this;
|
|
90
|
-
|
|
91
|
-
fields[fieldName] = fieldValue;
|
|
92
|
-
|
|
93
|
-
that.addUserDataFields(userUuid, fields, cb);
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Add user fields
|
|
98
|
-
*
|
|
99
|
-
* @param str userUuid
|
|
100
|
-
* @param obj fields - field name as key, field values as array to that key - ex: {'role': ['admin','user']}
|
|
101
|
-
* @param func cb(err)
|
|
102
|
-
*/
|
|
103
|
-
User.prototype.addUserDataFields = function addUserDataFields(userUuid, fields, cb) {
|
|
104
|
-
const options = {'exchange': this.exchangeName},
|
|
105
|
-
sendObj = {},
|
|
106
|
-
that = this;
|
|
107
|
-
|
|
108
|
-
// do not want to broadcast msg on queue for no reason
|
|
109
|
-
if ( ! fields || Object.keys(fields).length === 0) return cb();
|
|
110
|
-
|
|
111
|
-
sendObj.action = 'addUserDataFields';
|
|
112
|
-
sendObj.params = {};
|
|
113
|
-
sendObj.params.userUuid = userUuid;
|
|
114
|
-
sendObj.params.fields = fields;
|
|
115
|
-
|
|
116
|
-
that.intercom.send(sendObj, options, function (err, msgUuid) {
|
|
117
|
-
if (err) return cb(err);
|
|
118
|
-
|
|
119
|
-
that.dataWriter.emitter.once(msgUuid, cb);
|
|
120
|
-
});
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
/**Analyze Optimize Check Repair Truncate Drop * Checks a password for validity
|
|
124
|
-
*
|
|
125
|
-
* @param str password - plain text password
|
|
126
|
-
* @param str hash - hash to check password against
|
|
127
|
-
* @param func cb(err, res) res is boolean
|
|
128
|
-
*/
|
|
129
|
-
User.prototype.checkPassword = function checkPassword(password, hash, cb) {
|
|
130
|
-
const logPrefix = topLogPrefix + 'checkPassword() - ',
|
|
131
|
-
that = this;
|
|
132
|
-
|
|
133
|
-
password = password.trim();
|
|
134
|
-
|
|
135
|
-
bcrypt.compare(password, hash, function (err, result) {
|
|
136
|
-
if (err) {
|
|
137
|
-
that.log.error(logPrefix + err.message);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
cb(err, result);
|
|
141
|
-
});
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* Creates a new user (and adds to it to db)
|
|
146
|
-
*
|
|
147
|
-
* @param str username
|
|
148
|
-
* @param str password (plain text) or false for no password (user will not be able to login at all)
|
|
149
|
-
* @param obj fields - key, value pairs, where value can be an array of values
|
|
150
|
-
* @param uuid custom uuid - if not supplied a random will be generated
|
|
151
|
-
* @param func cb(err, user) - user being an instance of the new user
|
|
152
|
-
*/
|
|
153
|
-
User.prototype.create = function create(username, password, userData, uuid, cb) {
|
|
154
|
-
const logPrefix = topLogPrefix + 'create() - ',
|
|
155
|
-
tasks = [],
|
|
156
|
-
that = this;
|
|
157
|
-
|
|
158
|
-
let hashedPassword;
|
|
159
|
-
|
|
160
|
-
if (typeof uuid === 'function') {
|
|
161
|
-
cb = uuid;
|
|
162
|
-
uuid = uuidLib.v1();
|
|
163
|
-
} else if (typeof userData === 'function') {
|
|
164
|
-
userData = undefined;
|
|
165
|
-
uuid = uuidLib.v1();
|
|
166
|
-
cb = userData;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
if (cb === undefined) {
|
|
170
|
-
cb = function () {};
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
if (uuid === undefined) {
|
|
174
|
-
uuid = uuidLib.v1();
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
username = username.trim();
|
|
178
|
-
|
|
179
|
-
if (password) {
|
|
180
|
-
password = password.trim();
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
if (username.length === 0) {
|
|
184
|
-
const err = new Error('Trying to create user with empty username');
|
|
185
|
-
that.log.warn(logPrefix + err.message);
|
|
186
|
-
return cb(err);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// Check for username availability
|
|
190
|
-
tasks.push(function (cb) {
|
|
191
|
-
that.usernameAvailable(username, function (err, result) {
|
|
192
|
-
if (err) return cb(err);
|
|
193
|
-
|
|
194
|
-
if (result === true) {
|
|
195
|
-
that.log.debug(logPrefix + 'Username available: "' + username + '"');
|
|
196
|
-
cb();
|
|
197
|
-
} else {
|
|
198
|
-
const err = new Error('Trying to create user with taken username: "' + username + '"');
|
|
199
|
-
|
|
200
|
-
that.log.info(logPrefix + err.message);
|
|
201
|
-
cb(err);
|
|
202
|
-
}
|
|
203
|
-
});
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
// Hash Password
|
|
207
|
-
tasks.push(function (cb) {
|
|
208
|
-
if (password === false) {
|
|
209
|
-
that.log.debug(logPrefix + 'Password set to empty string for no-login, username: "' + username + '"');
|
|
210
|
-
hashedPassword = '';
|
|
211
|
-
return cb();
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
that.hashPassword(password, function (err, hash) {
|
|
215
|
-
if (err) return cb(err);
|
|
216
|
-
|
|
217
|
-
hashedPassword = hash;
|
|
218
|
-
that.log.debug(logPrefix + 'Password hashed, username: "' + username + '"');
|
|
219
|
-
cb();
|
|
220
|
-
});
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
// Create all fields
|
|
224
|
-
tasks.push(function (cb) {
|
|
225
|
-
const tasks = [];
|
|
226
|
-
|
|
227
|
-
for (const fieldName of Object.keys(userData)) {
|
|
228
|
-
tasks.push(function (cb) {
|
|
229
|
-
that.helpers.getFieldUuid(fieldName, cb);
|
|
230
|
-
});
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
async.parallel(tasks, cb);
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
// Write new user via queue
|
|
237
|
-
tasks.push(function (cb) {
|
|
238
|
-
const options = {'exchange': that.exchangeName},
|
|
239
|
-
sendObj = {};
|
|
240
|
-
|
|
241
|
-
sendObj.action = 'create';
|
|
242
|
-
sendObj.params = {};
|
|
243
|
-
sendObj.params.uuid = uuid;
|
|
244
|
-
sendObj.params.username = username;
|
|
245
|
-
sendObj.params.password = hashedPassword;
|
|
246
|
-
sendObj.params.fields = userData;
|
|
247
|
-
|
|
248
|
-
that.intercom.send(sendObj, options, function (err, msgUuid) {
|
|
249
|
-
if (err) return cb(err);
|
|
250
|
-
|
|
251
|
-
that.dataWriter.emitter.once(msgUuid, cb);
|
|
252
|
-
});
|
|
253
|
-
});
|
|
254
|
-
|
|
255
|
-
async.series(tasks, function (err) {
|
|
256
|
-
if (err) return cb(err);
|
|
257
|
-
|
|
258
|
-
that.fromUuid(uuid, function (err, user) {
|
|
259
|
-
if (err) {
|
|
260
|
-
that.log.error(logPrefix + err.message);
|
|
261
|
-
return cb(err);
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
cb(null, user);
|
|
265
|
-
});
|
|
266
|
-
});
|
|
267
|
-
};
|
|
268
|
-
|
|
269
|
-
/**
|
|
270
|
-
* Create a user object from a field
|
|
271
|
-
* IMPORTANT! Only fetches first matching user!
|
|
272
|
-
*
|
|
273
|
-
* @param str fieldName
|
|
274
|
-
* @param str fieldValue
|
|
275
|
-
* @param func cb(err, user) - "user" being a new user object or boolean false on failed search
|
|
276
|
-
*/
|
|
277
|
-
User.prototype.fromField = function fromField(fieldName, fieldValue, cb) {
|
|
278
|
-
const dbFields = [fieldName.trim(), fieldValue.trim()],
|
|
279
|
-
that = this,
|
|
280
|
-
sql = 'SELECT uud.userUuid\n' +
|
|
281
|
-
'FROM user_users_data uud\n' +
|
|
282
|
-
' JOIN user_data_fields udf ON udf.uuid = uud.fieldUuid\n' +
|
|
283
|
-
'WHERE udf.name = ? AND uud.data = ?\n' +
|
|
284
|
-
'LIMIT 1';
|
|
285
|
-
|
|
286
|
-
that.dataWriter.ready(function (err) {
|
|
287
|
-
if (err) return cb(err);
|
|
288
|
-
that.db.query(sql, dbFields, function (err, rows) {
|
|
289
|
-
if (err) return cb(err);
|
|
290
|
-
|
|
291
|
-
if (rows.length === 0) return cb(null, false);
|
|
292
|
-
|
|
293
|
-
that.fromUuid(that.lUtils.formatUuid(rows[0].userUuid), cb);
|
|
294
|
-
});
|
|
295
|
-
});
|
|
296
|
-
};
|
|
297
|
-
|
|
298
|
-
/**
|
|
299
|
-
* Create a user object from fields
|
|
300
|
-
* IMPORTANT! Only fetches first matching user that matches all fields!
|
|
301
|
-
*
|
|
302
|
-
* @param obj fields - {'fieldName': 'fieldValue', 'fieldName2': 'fieldValue2'}
|
|
303
|
-
* @param func cb(err, user) - "user" being a new user object or boolean false on failed search
|
|
304
|
-
*/
|
|
305
|
-
User.prototype.fromFields = function fromFields(fields, cb) {
|
|
306
|
-
const dbFields = [],
|
|
307
|
-
that = this;
|
|
308
|
-
|
|
309
|
-
let sql = 'SELECT uuid FROM user_users u\nWHERE\n 1 + 1\n';
|
|
310
|
-
|
|
311
|
-
for (const fieldName of Object.keys(fields)) {
|
|
312
|
-
sql += ' AND uuid IN (SELECT userUuid FROM user_users_data WHERE data = ? AND fieldUuid = (SELECT uuid FROM user_data_fields WHERE name = ?))\n';
|
|
313
|
-
dbFields.push(fields[fieldName].trim());
|
|
314
|
-
dbFields.push(fieldName.trim());
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
sql += 'LIMIT 1';
|
|
318
|
-
|
|
319
|
-
that.dataWriter.ready(function (err) {
|
|
320
|
-
if (err) return cb(err);
|
|
321
|
-
that.db.query(sql, dbFields, function (err, rows) {
|
|
322
|
-
if (err) return cb(err);
|
|
323
|
-
|
|
324
|
-
if (rows.length === 0) return cb(null, false);
|
|
325
|
-
|
|
326
|
-
that.fromUuid(that.lUtils.formatUuid(rows[0].uuid), cb);
|
|
327
|
-
});
|
|
328
|
-
});
|
|
329
|
-
};
|
|
330
|
-
|
|
331
|
-
/**
|
|
332
|
-
* Create a user object from username and password
|
|
333
|
-
*
|
|
334
|
-
* @param str username
|
|
335
|
-
* @param str password
|
|
336
|
-
* @param func cb(err, user) - "user" being a new user object or boolean false on failed login
|
|
337
|
-
*/
|
|
338
|
-
User.prototype.fromUserAndPass = function fromUserAndPass(username, password, cb) {
|
|
339
|
-
const logPrefix = topLogPrefix + 'fromUserAndPass() - ',
|
|
340
|
-
tasks = [],
|
|
341
|
-
that = this;
|
|
342
|
-
|
|
343
|
-
let hashedPassword,
|
|
344
|
-
userUuid,
|
|
345
|
-
userObj;
|
|
346
|
-
|
|
347
|
-
username = username.trim();
|
|
348
|
-
password = password.trim();
|
|
349
|
-
|
|
350
|
-
tasks.push(function (cb) {
|
|
351
|
-
that.dataWriter.ready(cb);
|
|
352
|
-
});
|
|
353
|
-
|
|
354
|
-
tasks.push(function (cb) {
|
|
355
|
-
const dbFields = [username],
|
|
356
|
-
sql = 'SELECT uuid, password FROM user_users WHERE username = ?';
|
|
357
|
-
|
|
358
|
-
that.db.query(sql, dbFields, function (err, rows) {
|
|
359
|
-
if (err) return cb(err);
|
|
360
|
-
|
|
361
|
-
if (rows.length === 0) {
|
|
362
|
-
userObj = false;
|
|
363
|
-
return cb();
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
hashedPassword = rows[0].password;
|
|
367
|
-
userUuid = rows[0].uuid;
|
|
368
|
-
cb();
|
|
369
|
-
});
|
|
370
|
-
});
|
|
371
|
-
|
|
372
|
-
tasks.push(function (cb) {
|
|
373
|
-
if ( ! hashedPassword) return cb();
|
|
374
|
-
|
|
375
|
-
that.checkPassword(password, hashedPassword, function (err, res) {
|
|
376
|
-
if (err) {
|
|
377
|
-
that.log.error(logPrefix + err.message);
|
|
378
|
-
return cb(err);
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
if (res === false) {
|
|
382
|
-
userObj = false;
|
|
383
|
-
return cb();
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
that.fromUuid(that.lUtils.formatUuid(userUuid), function (err, result) {
|
|
387
|
-
userObj = result;
|
|
388
|
-
if (err) userObj = false;
|
|
389
|
-
cb(err);
|
|
390
|
-
});
|
|
391
|
-
});
|
|
392
|
-
});
|
|
393
|
-
|
|
394
|
-
async.series(tasks, function (err) {
|
|
395
|
-
cb(err, userObj);
|
|
396
|
-
});
|
|
397
|
-
};
|
|
398
|
-
|
|
399
|
-
/**
|
|
400
|
-
* Create a user object from username
|
|
401
|
-
*
|
|
402
|
-
* @param str username
|
|
403
|
-
* @param func cb(err, user) - "user" being a new user object
|
|
404
|
-
*/
|
|
405
|
-
User.prototype.fromUsername = function fromUsername(username, cb) {
|
|
406
|
-
const logPrefix = topLogPrefix + 'fromUsername() - ',
|
|
407
|
-
dbFields = [],
|
|
408
|
-
that = this,
|
|
409
|
-
sql = 'SELECT uuid FROM user_users WHERE username = ?';
|
|
410
|
-
|
|
411
|
-
username = username.trim();
|
|
412
|
-
dbFields.push(username);
|
|
413
|
-
|
|
414
|
-
that.dataWriter.ready(function (err) {
|
|
415
|
-
if (err) return cb(err);
|
|
416
|
-
|
|
417
|
-
that.db.query(sql, dbFields, function (err, rows) {
|
|
418
|
-
if (err) return cb(err);
|
|
419
|
-
|
|
420
|
-
if (rows.length === 0) {
|
|
421
|
-
that.log.debug(logPrefix + 'No user found for username: "' + username + '"');
|
|
422
|
-
return cb(null, false);
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
// Use fromUuid() to get the user instance
|
|
426
|
-
that.fromUuid(that.lUtils.formatUuid(rows[0].uuid), cb);
|
|
427
|
-
});
|
|
428
|
-
});
|
|
429
|
-
};
|
|
430
|
-
|
|
431
|
-
/**
|
|
432
|
-
* Instanciate user object from user id
|
|
433
|
-
*
|
|
434
|
-
* @param int userUuid
|
|
435
|
-
* @param func cb(err, userObj) - userObj will be false if no user is found
|
|
436
|
-
*/
|
|
437
|
-
User.prototype.fromUuid = function fromUuid(userUuid, cb) {
|
|
438
|
-
const userUuidBuf = this.lUtils.uuidToBuffer(userUuid),
|
|
439
|
-
logPrefix = topLogPrefix + 'fromUuid() - ',
|
|
440
|
-
returnObj = new UserBase(this),
|
|
441
|
-
dbFields = [userUuidBuf],
|
|
442
|
-
that = this,
|
|
443
|
-
sql = 'SELECT\n' +
|
|
444
|
-
' u.uuid,\n' +
|
|
445
|
-
' u.username,\n' +
|
|
446
|
-
' u.password,\n' +
|
|
447
|
-
' uf.uuid AS fieldUuid,\n' +
|
|
448
|
-
' uf.name AS fieldName,\n' +
|
|
449
|
-
' ud.data AS fieldData\n' +
|
|
450
|
-
'FROM\n' +
|
|
451
|
-
' user_users u\n' +
|
|
452
|
-
' LEFT JOIN user_users_data ud ON ud.userUuid = u.uuid\n' +
|
|
453
|
-
' LEFT JOIN user_data_fields uf ON uf.uuid = ud.fieldUuid\n' +
|
|
454
|
-
'WHERE u.uuid = ?';
|
|
455
|
-
|
|
456
|
-
if ( ! userUuidBuf) {
|
|
457
|
-
const err = new Error('Invalid userUuid');
|
|
458
|
-
that.log.warn(logPrefix + err.message);
|
|
459
|
-
return cb(err);
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
that.dataWriter.ready(function (err) {
|
|
463
|
-
if (err) return cb(err);
|
|
464
|
-
|
|
465
|
-
that.db.query(sql, dbFields, function (err, rows) {
|
|
466
|
-
if (err) return cb(err);
|
|
467
|
-
|
|
468
|
-
if (rows.length === 0) {
|
|
469
|
-
const err = new Error('No user found for userUuid: "' + userUuid + '"');
|
|
470
|
-
that.log.debug(logPrefix + err.message);
|
|
471
|
-
return cb(null, false);
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
returnObj.uuid = that.lUtils.formatUuid(rows[0].uuid);
|
|
475
|
-
returnObj.username = rows[0].username;
|
|
476
|
-
|
|
477
|
-
if (rows[0].password === '') {
|
|
478
|
-
returnObj.passwordIsFalse = true;
|
|
479
|
-
} else {
|
|
480
|
-
returnObj.passwordIsFalse = false;
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
for (let i = 0; rows[i] !== undefined; i ++) {
|
|
484
|
-
const row = rows[i];
|
|
485
|
-
|
|
486
|
-
if (row.fieldUuid) {
|
|
487
|
-
if (returnObj.fields[row.fieldName] === undefined) {
|
|
488
|
-
returnObj.fields[row.fieldName] = [];
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
returnObj.fields[row.fieldName].push(row.fieldData);
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
cb(null, returnObj);
|
|
496
|
-
});
|
|
497
|
-
});
|
|
498
|
-
};
|
|
499
|
-
|
|
500
|
-
/**
|
|
501
|
-
* Get field data for a user
|
|
502
|
-
*
|
|
503
|
-
* @param str userUuid
|
|
504
|
-
* @param str fieldName
|
|
505
|
-
* @param func cb(err, data) - data is always an array of data (or empty array)
|
|
506
|
-
*/
|
|
507
|
-
User.prototype.getFieldData = function getFieldData(userUuid, fieldName, cb) {
|
|
508
|
-
const logPrefix = topLogPrefix + 'getFieldData() - ',
|
|
509
|
-
that = this;
|
|
510
|
-
|
|
511
|
-
that.helpers.getFieldUuid(fieldName, function (err, fieldUuid) {
|
|
512
|
-
const userUuidBuffer = that.lUtils.uuidToBuffer(userUuid),
|
|
513
|
-
fieldUuidBuffer = that.lUtils.uuidToBuffer(fieldUuid),
|
|
514
|
-
dbFields = [userUuidBuffer, fieldUuidBuffer],
|
|
515
|
-
sql = 'SELECT data FROM user_users_data WHERE userUuid = ? AND fieldUuid = ?';
|
|
516
|
-
|
|
517
|
-
if (err) return cb(err);
|
|
518
|
-
|
|
519
|
-
if (userUuidBuffer === false) {
|
|
520
|
-
const err = new Error('Invalid user uuid');
|
|
521
|
-
that.log.verbose(logPrefix + err.message);
|
|
522
|
-
return cb(err);
|
|
523
|
-
}
|
|
524
|
-
|
|
525
|
-
if (fieldUuidBuffer === false) {
|
|
526
|
-
const err = new Error('Invalid field uuid');
|
|
527
|
-
that.log.verbose(logPrefix + err.message);
|
|
528
|
-
return cb(err);
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
that.db.query(sql, dbFields, function (err, rows) {
|
|
532
|
-
const data = [];
|
|
533
|
-
|
|
534
|
-
if (err) return cb(err);
|
|
535
|
-
|
|
536
|
-
for (let i = 0; rows[i] !== undefined; i ++) {
|
|
537
|
-
data.push(rows[i].data);
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
cb(null, data);
|
|
541
|
-
});
|
|
542
|
-
});
|
|
543
|
-
};
|
|
544
|
-
|
|
545
|
-
/**
|
|
546
|
-
* Hashes a new password
|
|
547
|
-
*
|
|
548
|
-
* @param str password
|
|
549
|
-
* @param func cb(err, hash)
|
|
550
|
-
*/
|
|
551
|
-
User.prototype.hashPassword = function hashPassword(password, cb) {
|
|
552
|
-
const logPrefix = topLogPrefix + 'hashPassword() - ',
|
|
553
|
-
that = this;
|
|
554
|
-
|
|
555
|
-
if ( ! password) {
|
|
556
|
-
password = '';
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
password = password.trim();
|
|
560
|
-
|
|
561
|
-
bcrypt.hash(password, 10, function (err, hash) {
|
|
562
|
-
if (err) {
|
|
563
|
-
that.log.error(logPrefix + err.message);
|
|
564
|
-
}
|
|
565
|
-
|
|
566
|
-
cb(err, hash);
|
|
567
|
-
});
|
|
568
|
-
};
|
|
569
|
-
|
|
570
|
-
/**
|
|
571
|
-
* Replace all fields
|
|
572
|
-
* IMPORTANT!!! Will clear all data not given in the fields parameter
|
|
573
|
-
*
|
|
574
|
-
* @param str userUuid
|
|
575
|
-
* @param obj fields - field name as key, field values as array to that key - ex: {'role': ['admin','user']}
|
|
576
|
-
* @param func cb(err)
|
|
577
|
-
*/
|
|
578
|
-
User.prototype.replaceUserFields = function replaceUserFields(uuid, fields, cb) {
|
|
579
|
-
const options = {'exchange': this.dataWriter.exchangeName},
|
|
580
|
-
sendObj = {},
|
|
581
|
-
that = this;
|
|
582
|
-
|
|
583
|
-
that.fromUuid(uuid, function (err, user) {
|
|
584
|
-
if (err) return cb(err);
|
|
585
|
-
|
|
586
|
-
sendObj.action = 'replaceFields';
|
|
587
|
-
sendObj.params = {};
|
|
588
|
-
sendObj.params.username = user.username;
|
|
589
|
-
sendObj.params.userUuid = uuid;
|
|
590
|
-
sendObj.params.fields = fields;
|
|
591
|
-
|
|
592
|
-
that.intercom.send(sendObj, options, function (err, msgUuid) {
|
|
593
|
-
if (err) return cb(err);
|
|
594
|
-
|
|
595
|
-
that.dataWriter.emitter.once(msgUuid, cb);
|
|
596
|
-
});
|
|
597
|
-
});
|
|
598
|
-
};
|
|
599
|
-
|
|
600
|
-
/**
|
|
601
|
-
* Remove a user
|
|
602
|
-
*
|
|
603
|
-
* @param uuid userUuid
|
|
604
|
-
* @param func cb(err)
|
|
605
|
-
*/
|
|
606
|
-
User.prototype.rmUser = function rmUser(userUuid, cb) {
|
|
607
|
-
const options = {'exchange': this.dataWriter.exchangeName},
|
|
608
|
-
sendObj = {},
|
|
609
|
-
that = this;
|
|
610
|
-
|
|
611
|
-
sendObj.action = 'rmUser';
|
|
612
|
-
sendObj.params = {};
|
|
613
|
-
sendObj.params.userUuid = userUuid;
|
|
614
|
-
|
|
615
|
-
that.intercom.send(sendObj, options, function (err, msgUuid) {
|
|
616
|
-
if (err) return cb(err);
|
|
617
|
-
|
|
618
|
-
that.dataWriter.emitter.once(msgUuid, cb);
|
|
619
|
-
});
|
|
620
|
-
};
|
|
621
|
-
|
|
622
|
-
/**
|
|
623
|
-
* Remove a user field
|
|
624
|
-
*
|
|
625
|
-
* @param uuid userUuid
|
|
626
|
-
* @param str fieldName
|
|
627
|
-
* @param func cb(err)
|
|
628
|
-
*/
|
|
629
|
-
User.prototype.rmUserField = function rmUserField(userUuid, fieldName, cb) {
|
|
630
|
-
const options = {'exchange': this.dataWriter.exchangeName},
|
|
631
|
-
sendObj = {},
|
|
632
|
-
that = this;
|
|
633
|
-
|
|
634
|
-
sendObj.action = 'rmUserField';
|
|
635
|
-
sendObj.params = {};
|
|
636
|
-
sendObj.params.userUuid = userUuid;
|
|
637
|
-
sendObj.params.fieldName = fieldName;
|
|
638
|
-
|
|
639
|
-
that.intercom.send(sendObj, options, function (err, msgUuid) {
|
|
640
|
-
if (err) return cb(err);
|
|
641
|
-
|
|
642
|
-
that.dataWriter.emitter.once(msgUuid, cb);
|
|
643
|
-
});
|
|
644
|
-
};
|
|
645
|
-
|
|
646
|
-
/**
|
|
647
|
-
* Set password for a user
|
|
648
|
-
*
|
|
649
|
-
* @param str userUuid
|
|
650
|
-
* @param str newPassword (plain text) or false for no valid password (user will not be able to login at all)
|
|
651
|
-
* @param func cb(err)
|
|
652
|
-
*/
|
|
653
|
-
User.prototype.setPassword = function setPassword(userUuid, newPassword, cb) {
|
|
654
|
-
const tasks = [],
|
|
655
|
-
that = this;
|
|
656
|
-
|
|
657
|
-
let hashedPassword;
|
|
658
|
-
|
|
659
|
-
tasks.push(function (cb) {
|
|
660
|
-
if (newPassword) {
|
|
661
|
-
that.hashPassword(newPassword.trim(), function (err, hash) {
|
|
662
|
-
hashedPassword = hash;
|
|
663
|
-
cb(err);
|
|
664
|
-
});
|
|
665
|
-
} else {
|
|
666
|
-
hashedPassword = false;
|
|
667
|
-
cb();
|
|
668
|
-
}
|
|
669
|
-
});
|
|
670
|
-
|
|
671
|
-
tasks.push(function (cb) {
|
|
672
|
-
const options = {'exchange': that.dataWriter.exchangeName},
|
|
673
|
-
sendObj = {};
|
|
674
|
-
|
|
675
|
-
sendObj.action = 'setPassword';
|
|
676
|
-
sendObj.params = {};
|
|
677
|
-
sendObj.params.userUuid = userUuid;
|
|
678
|
-
sendObj.params.password = hashedPassword;
|
|
679
|
-
|
|
680
|
-
that.intercom.send(sendObj, options, function (err, msgUuid) {
|
|
681
|
-
if (err) return cb(err);
|
|
682
|
-
|
|
683
|
-
that.dataWriter.emitter.once(msgUuid, cb);
|
|
684
|
-
});
|
|
685
|
-
});
|
|
686
|
-
|
|
687
|
-
async.series(tasks, cb);
|
|
688
|
-
};
|
|
689
|
-
|
|
690
|
-
/**
|
|
691
|
-
* Set the username for a user
|
|
692
|
-
*
|
|
693
|
-
* @param str userUuid
|
|
694
|
-
* @param str newusername
|
|
695
|
-
* @param fucn cb(err)
|
|
696
|
-
*/
|
|
697
|
-
User.prototype.setUsername = function setUsername(userUuid, newUsername, cb) {
|
|
698
|
-
const userUuidBuf = this.lUtils.uuidToBuffer(userUuid),
|
|
699
|
-
logPrefix = topLogPrefix + 'setUsername() - ',
|
|
700
|
-
that = this;
|
|
701
|
-
|
|
702
|
-
newUsername = newUsername.trim();
|
|
703
|
-
|
|
704
|
-
if ( ! newUsername) {
|
|
705
|
-
const err = new Error('No new username supplied');
|
|
706
|
-
that.log.warn(logPrefix + err.message);
|
|
707
|
-
return cb(err);
|
|
708
|
-
}
|
|
709
|
-
|
|
710
|
-
if (userUuidBuf === false) {
|
|
711
|
-
const err = new Error('Invalid user uuid');
|
|
712
|
-
that.log.warn(logPrefix + err.message);
|
|
713
|
-
return cb(err);
|
|
714
|
-
}
|
|
715
|
-
|
|
716
|
-
that.dataWriter.ready(function (err) {
|
|
717
|
-
if (err) return cb(err);
|
|
718
|
-
|
|
719
|
-
that.db.query('SELECT uuid FROM user_users WHERE username = ? AND uuid != ?', [newUsername, userUuidBuf], function (err, rows) {
|
|
720
|
-
const options = {'exchange': that.dataWriter.exchangeName},
|
|
721
|
-
sendObj = {};
|
|
722
|
-
|
|
723
|
-
if (err) return cb(err);
|
|
724
|
-
|
|
725
|
-
if (rows.length && that.lUtils.formatUuid(rows[0].uuid) !== userUuid) {
|
|
726
|
-
const err = new Error('Username is already taken');
|
|
727
|
-
return cb(err);
|
|
728
|
-
}
|
|
729
|
-
|
|
730
|
-
sendObj.action = 'setUsername';
|
|
731
|
-
sendObj.params = {};
|
|
732
|
-
sendObj.params.userUuid = userUuid;
|
|
733
|
-
sendObj.params.username = newUsername;
|
|
734
|
-
|
|
735
|
-
that.intercom.send(sendObj, options, function (err, msgUuid) {
|
|
736
|
-
if (err) return cb(err);
|
|
737
|
-
|
|
738
|
-
that.dataWriter.emitter.once(msgUuid, cb);
|
|
739
|
-
});
|
|
740
|
-
});
|
|
741
|
-
});
|
|
742
|
-
};
|
|
743
|
-
|
|
744
|
-
/**
|
|
745
|
-
* Checks if a unsername is available
|
|
746
|
-
*
|
|
747
|
-
* @param str username
|
|
748
|
-
* @param func cb(err, result) - result is a bolean
|
|
749
|
-
*/
|
|
750
|
-
User.prototype.usernameAvailable = function usernameAvailable(username, cb) {
|
|
751
|
-
const that = this;
|
|
752
|
-
|
|
753
|
-
let isAvailable;
|
|
754
|
-
|
|
755
|
-
username = username.trim();
|
|
756
|
-
|
|
757
|
-
that.dataWriter.ready(function (err) {
|
|
758
|
-
if (err) return cb(err);
|
|
759
|
-
|
|
760
|
-
that.db.query('SELECT uuid FROM user_users WHERE username = ?', [username], function (err, rows) {
|
|
761
|
-
if (err) return cb(err);
|
|
762
|
-
|
|
763
|
-
if (rows.length === 0) {
|
|
764
|
-
isAvailable = true;
|
|
765
|
-
} else {
|
|
766
|
-
isAvailable = false;
|
|
767
|
-
}
|
|
768
|
-
|
|
769
|
-
cb(null, isAvailable);
|
|
770
|
-
});
|
|
771
|
-
});
|
|
772
|
-
};
|
|
773
|
-
|
|
774
|
-
function UserBase(userInstance) {
|
|
775
|
-
const that = this;
|
|
776
|
-
|
|
777
|
-
that.fields = {};
|
|
778
|
-
|
|
779
|
-
that.userInstance = userInstance;
|
|
780
|
-
that.log = that.userInstance.log;
|
|
781
|
-
}
|
|
782
|
-
|
|
783
|
-
/**
|
|
784
|
-
* Add a field with value
|
|
785
|
-
*
|
|
786
|
-
* @param str name
|
|
787
|
-
* @param str value
|
|
788
|
-
* @param func cb(err)
|
|
789
|
-
*/
|
|
790
|
-
UserBase.prototype.addField = function addField(name, value, cb) {
|
|
791
|
-
const logPrefix = topLogPrefix + 'UserBase.addField() - ',
|
|
792
|
-
that = this;
|
|
793
|
-
|
|
794
|
-
if (that.uuid === undefined) {
|
|
795
|
-
const err = new Error('Cannot add field; no user loaded');
|
|
796
|
-
that.log.verbose(logPrefix + err.message);
|
|
797
|
-
return cb(err);
|
|
798
|
-
}
|
|
799
|
-
|
|
800
|
-
that.userInstance.addUserDataField(that.uuid, name, value, function (err) {
|
|
801
|
-
if (err) return cb(err);
|
|
802
|
-
|
|
803
|
-
if (that.fields[name] === undefined) {
|
|
804
|
-
that.fields[name] = [];
|
|
805
|
-
}
|
|
806
|
-
|
|
807
|
-
that.fields[name].push(value);
|
|
808
|
-
cb();
|
|
809
|
-
});
|
|
810
|
-
};
|
|
811
|
-
|
|
812
|
-
/**
|
|
813
|
-
* Adds one or more fields with values to the user object. Does not overwrite existing values. It is possible to add the same value multiple times
|
|
814
|
-
*
|
|
815
|
-
* @param obj fields - field name as key, field values as array to that key - ex: {'role': ['admin','user']}
|
|
816
|
-
* @param func cb(err)
|
|
817
|
-
*/
|
|
818
|
-
UserBase.prototype.addFields = function addFields(fields, cb) {
|
|
819
|
-
const logPrefix = topLogPrefix + 'UserBase.addFields() - ',
|
|
820
|
-
that = this;
|
|
821
|
-
|
|
822
|
-
if (that.uuid === undefined) {
|
|
823
|
-
const err = new Error('Cannot add field; no user loaded');
|
|
824
|
-
that.log.verbose(logPrefix + err.message);
|
|
825
|
-
return cb(err);
|
|
826
|
-
}
|
|
827
|
-
|
|
828
|
-
that.userInstance.addUserDataFields(that.uuid, fields, function (err) {
|
|
829
|
-
if (err) return cb(err);
|
|
830
|
-
|
|
831
|
-
for (let key in fields) {
|
|
832
|
-
if (that.fields[key] === undefined) {
|
|
833
|
-
that[key] = fields[key];
|
|
834
|
-
} else {
|
|
835
|
-
for (let value of fields[key]) {
|
|
836
|
-
that.fields[key].push(value);
|
|
837
|
-
}
|
|
838
|
-
}
|
|
839
|
-
}
|
|
840
|
-
|
|
841
|
-
cb();
|
|
842
|
-
});
|
|
843
|
-
};
|
|
844
|
-
|
|
845
|
-
/**
|
|
846
|
-
* Replace all fields
|
|
847
|
-
* IMPORTANT!!! Will clear all data not given in the fields parameter
|
|
848
|
-
*
|
|
849
|
-
* @param obj fields - field name as key, field values as array to that key - ex: {'role': ['admin','user']}
|
|
850
|
-
* @param func cb(err)
|
|
851
|
-
*/
|
|
852
|
-
UserBase.prototype.replaceFields = function replaceFields(fields, cb) {
|
|
853
|
-
const logPrefix = topLogPrefix + 'UserBase.replaceFields() - ',
|
|
854
|
-
that = this;
|
|
855
|
-
|
|
856
|
-
if (that.uuid === undefined) {
|
|
857
|
-
const err = new Error('Cannot replace fields; no user loaded');
|
|
858
|
-
that.log.verbose(logPrefix + err.message);
|
|
859
|
-
return cb(err);
|
|
860
|
-
}
|
|
861
|
-
|
|
862
|
-
that.userInstance.replaceUserFields(that.uuid, fields, function (err) {
|
|
863
|
-
if (err) return cb(err);
|
|
864
|
-
|
|
865
|
-
// Reload everything
|
|
866
|
-
that.userInstance.fromUuid(that.uuid, function (err, user) {
|
|
867
|
-
if (err) return cb(err);
|
|
868
|
-
|
|
869
|
-
that.fields = user.fields;
|
|
870
|
-
cb();
|
|
871
|
-
});
|
|
872
|
-
});
|
|
873
|
-
};
|
|
874
|
-
|
|
875
|
-
UserBase.prototype.rm = function rm(cb) {
|
|
876
|
-
const logPrefix = topLogPrefix + 'UserBase.rm() - ',
|
|
877
|
-
that = this;
|
|
878
|
-
|
|
879
|
-
if (that.uuid === undefined) {
|
|
880
|
-
const err = new Error('Cannot remove field; no user loaded');
|
|
881
|
-
that.log.verbose(logPrefix + err.message);
|
|
882
|
-
return cb(err);
|
|
883
|
-
}
|
|
884
|
-
|
|
885
|
-
that.userInstance.rmUser(that.uuid, function (err) {
|
|
886
|
-
if (err) return cb(err);
|
|
887
|
-
|
|
888
|
-
delete that.uuid;
|
|
889
|
-
delete that.username;
|
|
890
|
-
|
|
891
|
-
that.fields = {};
|
|
892
|
-
|
|
893
|
-
cb();
|
|
894
|
-
});
|
|
895
|
-
};
|
|
896
|
-
|
|
897
|
-
/**
|
|
898
|
-
* Remove a field from this user
|
|
899
|
-
*
|
|
900
|
-
* @param str name
|
|
901
|
-
* @param func cb(err)
|
|
902
|
-
*/
|
|
903
|
-
UserBase.prototype.rmField = function rmField(name, cb) {
|
|
904
|
-
const logPrefix = topLogPrefix + 'UserBase.rmField() - ',
|
|
905
|
-
that = this;
|
|
906
|
-
|
|
907
|
-
if (that.uuid === undefined) {
|
|
908
|
-
const err = new Error('Cannot remove field; no user loaded');
|
|
909
|
-
that.log.verbose(logPrefix + err.message);
|
|
910
|
-
return cb(err);
|
|
911
|
-
}
|
|
912
|
-
|
|
913
|
-
that.userInstance.rmUserField(that.uuid, name, function (err) {
|
|
914
|
-
if (err) return cb(err);
|
|
915
|
-
|
|
916
|
-
delete that.fields[name];
|
|
917
|
-
cb();
|
|
918
|
-
});
|
|
919
|
-
};
|
|
920
|
-
|
|
921
|
-
UserBase.prototype.setPassword = function (newPassword, cb) {
|
|
922
|
-
const logPrefix = topLogPrefix + 'UserBase.setPassword() - ',
|
|
923
|
-
that = this;
|
|
924
|
-
|
|
925
|
-
if (that.uuid === undefined) {
|
|
926
|
-
const err = new Error('Cannot set password; no user loaded');
|
|
927
|
-
that.log.verbose(logPrefix + err.message);
|
|
928
|
-
return cb(err);
|
|
929
|
-
}
|
|
930
|
-
|
|
931
|
-
that.userInstance.setPassword(that.uuid, newPassword, cb);
|
|
932
|
-
};
|
|
933
|
-
|
|
934
|
-
UserBase.prototype.setUsername = function (newUsername, cb) {
|
|
935
|
-
const logPrefix = topLogPrefix + 'UserBase.setUsername() - ',
|
|
936
|
-
that = this;
|
|
937
|
-
|
|
938
|
-
if (that.uuid === undefined) {
|
|
939
|
-
const err = new Error('Cannot set username; no user loaded');
|
|
940
|
-
that.log.verbose(logPrefix + err.message);
|
|
941
|
-
return cb(err);
|
|
942
|
-
}
|
|
943
|
-
|
|
944
|
-
that.userInstance.setUsername(that.uuid, newUsername, function (err) {
|
|
945
|
-
if (err) return cb(err);
|
|
946
|
-
|
|
947
|
-
that.username = newUsername;
|
|
948
|
-
cb();
|
|
949
|
-
});
|
|
950
|
-
};
|
|
951
|
-
|
|
952
|
-
exports = module.exports = User;
|
|
953
|
-
exports.Users = require(__dirname + '/users.js');
|