const md5 = require('md5');
const QRCode = require('qrcode')
const Usersgroups = require('./usersgroups');
const Basedata = require('./basedata');
const Organizations = require('./organizations');
const Configuration = require('./configuration');
const Pdf = require('./core/pdf');
const { traceProcessWarnings } = require('process');
const { start } = require('repl');
class users {
constructor(logger) {
// always initialize all instance properties
this._logger = logger;
}
/**
* Loads List of users for presentation in UI list from core database
* @param {function} callback rows or null
*/
getListOfUsersForUI(callback) {
let query = "SELECT `users`.*, " +
"`basedata`.`firstname` AS firstname, " +
"`basedata`.`lastname` AS lastname, " +
"organizations.name AS organizationname, " +
"`organizations`.`id` AS organizationid " +
"FROM `users` " +
"LEFT JOIN `basedata` ON basedata.id = `users`.`basedataid` " +
"LEFT JOIN `organizations` ON `basedata`.`organizationid` = `organizations`.`id` " +
"ORDER BY `users`.id ASC";
global.coreDb.all(query, [], (err, rows) => {
if (err) {
this._logger.error('USERS-MODEL | Error loading users from core data: ' + err.message);
return callback(null);
} else {
return callback(rows);
}
});
}
/**
* Adds a new User to core database
* @param {string} username username of new user
* @param {string} password password of new user
* @param {integer} basedataId id of basedata entry this user belongs to
* @param {*} callback success (true or false)
*/
addUser(username, password, basedataId, callback) {
this.doesUserExist(username, basedataId, (checkResult) => {
if (checkResult === null) {
// Error checking core database
return callback(null);
} else if (checkResult === true) {
// Username exists, or for this basedata id another user exists
return callback(false);
} else if (checkResult === false) {
// No user exists for this basedata id and the username does not exist in core database
// Go on and create user
var passwordHashMD5 = md5(password);
let query = "INSERT INTO `users` (username, password, startPassword, startPasswordHash, basedataid) VALUES (?, ?, ?, ?, ?)";
global.coreDb.run(query,
[
username,
'',
password,
md5(password),
basedataId
],
function (err) {
if (err) {
console.log('ERROR: ' + err.message);
callback(false);
} else {
callback(true);
}
});
}
})
}
/**
* Return user entry from core database as row
* @param {integer} uId user Id of core database table
* @param {function} callback rows or null
*/
getUserForId(uId, callback) {
let query = "SELECT * FROM users WHERE id = ?";
global.coreDb.all(query, [
uId
], (err, rows) => {
if (err) {
this._logger.error('USERS-MODEL | Error loading user from core data: ' + err.message);
return callback(null);
} else {
return callback(rows);
}
});
}
/**
* Returns user for a given basedata id
* @param {integer} bId
* @param {function} callback row or null
*/
getUserForBasedataId(bId, callback) {
let query = "SELECT * FROM users WHERE basedataid = ?";
global.coreDb.all(query, [
bId
], (err, rows) => {
if (err) {
this._logger.error('USERS-MODEL | Error loading user from core data for basedataId: ' + err.message);
return callback(null);
} else {
return callback(rows);
}
});
}
/**
* Returns basedataId of user with username
* @param {string} username
* @param {function} callback null or basedataId of user
*/
getBasedataIdForUserWithName(username, callback) {
let query = "SELECT * FROM users WHERE username = ?";
global.coreDb.all(query, [
username
], (err, rows) => {
if (err) {
this._logger.error('USERS-MODEL | Error loading user from core data for basedataId: ' + err.message);
return callback(null);
} else {
if (rows.length > 0) {
var basedataId = rows[0].basedataid;
return callback(basedataId);
} else {
return callback(null);
}
}
});
}
/**
* Checks if a username exists or not
* @param {string} username
* @param {string} basedataId basedata Id, check if for this basedataId another user exists
* @param {function} callback true or false (user exists or not), null if error querying core database
*/
doesUserExist(username, basedataId, callback) {
let query = "SELECT * FROM `users` WHERE (username = ?) OR (basedataid = ?)";
global.coreDb.all(query, [
username,
basedataId
], (err, rows) => {
if (err) {
this._logger.error('USERS-MODEL | Error checking if user / basedataid exists in core data: ' + err.message);
return callback(null);
} else {
if (rows.length > 0) {
return callback(true);
} else {
return callback(false);
}
}
});
}
/**
* Checks if a username exists or not
* @param {string} username
* @param {function} callback rows or null
*/
getUserForUsername(username, callback) {
let query = "SELECT * FROM `users` WHERE (username = ?)";
global.coreDb.all(query, [
username,
], (err, rows) => {
if (err) {
this._logger.error('USERS-MODEL | Error checking if user / basedataid exists in core data: ' + err.message);
return callback(null);
} else {
if (rows.length > 0) {
return callback(rows);
} else {
return callback(false);
}
}
});
}
/**
* Checks if there is a start password set for user (e.g. new password has been set by admin)
* @param {integer} userId id of user
* @param {*} callback boolean: true = user has start password set, false = startPassword is not set
*/
isStartPasswordSetForUser(userId, callback) {
let query = "SELECT * FROM users WHERE id = ?";
global.coreDb.all(query, [
userId,
], (err, rows) => {
if (err) {
this._logger.error('USERS-MODEL | Error checking if user / basedataid has a startpassword set in core data: ' + err.message);
return callback(null);
} else {
if (rows.length > 0) {
if (rows[0].startPassword.length > 0) {
return callback(true);
} else {
return callback(false);
}
} else {
return callback(false);
}
}
});
}
/**
* Sets a new startPassword for user and removes the existing hashed password
* @param {integer} userId id of user the new startPassword shall be set for
* @param {*} startPassword human readable start password (not hashed!!)
* @param {*} callback success (true/false)
*/
setStartPasswordForUser(userId, startPassword, callback) {
let query = "UPDATE users SET startPassword = ?, startPasswordHash = ?, password = null WHERE id = ?";
global.coreDb.run(query,
[
startPassword,
md5(startPassword),
userId
],
function (err) {
if (err) {
console.log('ERROR: ' + err.message);
callback(false);
} else {
callback(true);
}
});
}
/**
* Sets a new password for user and removes a set startPassword
* @param {integer} userId id of user the password shall be set for
* @param {*} password new password to be set (not hashed)
* @param {*} callback success (true / false)
*/
setPasswordHashForUser(userId, password, callback) {
let query = "UPDATE users SET startPassword = null, startPasswordHash = null, password = ? WHERE id = ?";
let hash = md5(password);
global.coreDb.run(query,
[
hash,
userId
],
function (err) {
if (err) {
console.log('ERROR: ' + err.message);
callback(false);
} else {
callback(true);
}
});
}
/**
* Sets a new password for user based on a md5 hashed password
* @param {integer} userId id of user
* @param {*} passwordHash md5 hashed new password
* @param {*} callback success (true/false)
*/
setPasswordMD5HashedForUser(userId, passwordHash, callback) {
let query = "UPDATE users SET startPassword = null, startPasswordHash = null, password = ? WHERE id = ?";
global.coreDb.run(query,
[
passwordHash,
userId
],
function (err) {
if (err) {
console.log('ERROR: ' + err.message);
callback(false);
} else {
callback(true);
}
});
}
/**
*
* @param {integer} uId id of user to be updated
* @param {string} username new username
* @param {string} password new password
* @param {integer} basedataId basedata id this user should be referenced to
* @param {function} callback success, true of false
*/
updateUser(userId, reqBody, callback) {
let password = reqBody.password;
let username = reqBody.username;
this.getUserForId(userId, (userRow) => {
this.getUserForUsername(username, (rows) => {
var validNewUsername = false;
if (rows === null) {
// error during query of core database
console.log('ERROR: Error getting user for username ' + username);
} else if (rows.length > 0) {
// found username
if (rows[0].id === parseInt(userId)) {
validNewUsername = true;
}
} else {
// user not found
validNewUsername = true;
}
if (validNewUsername === true) {
// new Username is not existing or belongs to own user Entry
// now update the User in core database
// Check if password has changed, if not set to old hash
var startPassword = null;
var startPasswordHash = null;
if (password.length > 0) {
startPassword = password;
startPasswordHash = md5(password);
password = '';
//password = md5(password);
} else {
password = userRow[0].password;
}
// Start Updating the user entry in core database
let query = "UPDATE `users` SET password = ?, startPassword = ?, startPasswordHash = ?, username = ? WHERE `users`.`id` = ?";
global.coreDb.run(query,
[
password,
startPassword,
startPasswordHash,
username,
userId
],
function (err) {
if (err) {
console.log('ERROR: ' + err.message);
callback(false);
} else {
var usersgroups = new Usersgroups();
usersgroups.updateUsersGroups(userId, reqBody, (success) => {
callback(true);
})
}
});
} else {
console.log('not a valid username');
callback(false);
}
})
})
}
/**
* Returns list of all users from core database
* @param {function} callback rows or null
*/
getListOfUsers(callback) {
let query = "SELECT * FROM `users`";
global.coreDb.all(query, [], (err, rows) => {
if (err) {
this._logger.error('USERS-MODEL | Error loading users from core data: ' + err.message);
return callback(null);
} else {
return callback(rows);
}
});
db.query(query, (errUsers, resultUsers) => {
if (errUsers) {
// Errror loading organizations
console.log('Error loading users');
res.send('Error Reading Userlist');
return callback(null);
} else {
return callback(resultUsers);
}
});
}
/**
* Removes a user from core database
* @param {integer} uID user id of user to be removed from core database
* @param {function} callback success, true or false
*/
removeUser(uID, callback) {
let query = "DELETE FROM users WHERE id = ?";
global.coreDb.run(query,
[
uID
],
function (err) {
if (err) {
console.log('ERROR: ' + err.message);
callback(false);
} else {
callback(true);
}
});
}
/**
* Activates a user in coredatabase
* @param {integer} uID user id of user to be activated
* @param {function} callback success (true or false)
*/
activateUser(uID, callback) {
let query = "UPDATE `users` SET state = 1 WHERE `users`.`id` = ?";
global.coreDb.run(query,
[
uID
],
function (err) {
if (err) {
console.log('ERROR: ' + err.message);
callback(false);
} else {
callback(true);
}
});
}
/**
* Deactivates a user in coredatabase
* @param {integer} uID user id of user to be deactivated
* @param {function} callback success (true or false)
*/
deactivateUser(uID, callback) {
let query = "UPDATE `users` SET state = 0 WHERE `users`.`id` = ?";
global.coreDb.run(query,
[
uID
],
function (err) {
if (err) {
console.log('ERROR: ' + err.message);
callback(false);
} else {
callback(true);
}
});
}
/**
* Generates a pdf document with users credentials
* @param {integer} userId id of user the credentialreport should be generated for
* @param {function} callback success (true/false), path to pdf document or null
*/
generateCredentialsPDF(userId, callback) {
this.getUserForId(userId, (rowsUser) => {
if (rowsUser !== null) {
// Found User in database
console.log('rowsUser:');
console.log(rowsUser);
var user = rowsUser[0];
// Check if User has a startPassword set or he has changed his password
var password = 'bereits geändert';
var passwordQr = '';
if (user.startPassword !== null) {
if (user.startPassword.length > 0) {
password = user.startPassword;
passwordQr = user.startPassword;
}
}
var basedata = new Basedata(this._logger);
basedata.getBaseDataForId(user.basedataid, (rowsBasedata) => {
console.log('rowsBasedata:');
console.log(rowsBasedata);
if (rowsBasedata !== null) {
// Found Basedata Record for user
var organizations = new Organizations(this._logger);
organizations.getOrganizationWithId(rowsBasedata[0].organizationid, (rowsOrganization) => {
console.log('rowsOrganization:');
console.log(rowsOrganization);
if (rowsOrganization !== null) {
// Organization found
var configuration = new Configuration(this._logger);
configuration.getValueForKeyword('externalfqdn', (serverAddress) => {
// generate QR Code
this.generateCredentialsQR(user.username, passwordQr, serverAddress, 5010, (pathToQRCode) => {
// now start constructing the pdf document
var pdf = new Pdf(this._logger);
// initialize PDF documebt
pdf.initialize();
// add Header to PDF document
pdf.addHeader('Persönliche Zugangsdaten - ' + rowsBasedata[0].firstname + ' ' + rowsBasedata[0].lastname);
// if org-logo is of type jpeg render it to the header
var logo = '';
var path = require('path');
if (rowsOrganization[0].image !== null) {
if (path.extname(rowsOrganization[0].image) === 'jpg') {
// found a jpg, add logo to header
logo = global.appRoot + '/public/assets/img/' + rowsOrganization[0].image;
} else {
// logo is a different image type, render default image
logo = global.appRoot + '/public/assets/img/logoPdf.jpg';
}
} else {
logo = global.appRoot + '/public/assets/img/logoPdf.jpg';
}
pdf.headerLogo = logo;
pdf.addText(
'Willkommen bei ALARMiator ' + rowsBasedata[0].firstname,
{ fontSize: 16, font: require('pdfjs/font/Helvetica') }
);
pdf.addBr();
pdf.addBr();
pdf.addText(
'Dieses Dokument enthält Deine persönlichen Zugangsdaten für ALARMiator. Mit diesen Zugangsdaten kannst Du Dich in der ALARMiator Mobile App anmelden. Bitte halte Deine Zugangsdaten geheim. Folgend findest Du auch eine Übersicht aller über Dich in ALARMiator gespeicherter Infortmationen:',
{ fontSize: 12, font: require('pdfjs/font/Helvetica') }
);
pdf.addBr();
// Adding user credentials now
pdf.addTable([200, 300], 1);
pdf.addTableHeader(['Information', 'Wert']);
pdf.addTableRow(['Serveradresse', serverAddress]);
pdf.addTableRow(['Benutzername', user.username]);
pdf.addTableRow(['Passwort', password]);
// Add hint for QR-Code
pdf.addText(
'Deine Zugangsdaten sind in folgendem QR-Code enthalten. Du kannst mit der ALARMiator Mobile App den QR Code scannen und damit die Anmeldung sehr einfach durchführen.',
{
fontSize: 12,
font: require('pdfjs/font/Helvetica'),
paddingTop: 1 * pdf.cm
});
pdf.addBr();
pdf.addImage(pathToQRCode, 0, 0, 100, 'left');
var outputFile = global.appRoot + '/temp/credentials_' + userId + '_' + rowsBasedata[0].firstname + rowsBasedata[0].lastname + '.pdf';
//pdf.closePDF();
pdf.writeDocToFile(outputFile, (success) => {
if (success) {
return callback(true, outputFile);
} else {
return callback(false, null);
}
});
})
});
} else {
return callback(false, null);
}
})
} else {
// could not find Basedata record for user -> return false
return callback(false, null);
}
})
} else {
// User not found, return false
return callback(false, null);
}
})
}
/**
* Generates a QR Code with credentials, server and port
* @param {string} username username of user
* @param {*} password password of user
* @param {*} serveraddress address of server to be used
* @param {*} port port of server
* @param {*} callback path to jpeg of generated qr code
*/
generateCredentialsQR(username, password, serveraddress, port, callback) {
const path = global.appRoot + '/temp/credentials_QR_' + username + '.png';
const pathjpg = global.appRoot + '/temp/credentials_QR_' + username + '.jpg';
var payload = {
server: serveraddress,
port: port,
username: username,
password: password
};
QRCode.toFile(path, JSON.stringify(payload), {
color: {
dark: '#000', // Blue modules
light: '#FFF' // Transparent background
}
}, function (err) {
if (err) {
throw err
} else {
console.log('saved.');
const fs = require("fs");
const pngToJpeg = require('png-to-jpeg');
let buffer = fs.readFileSync(path);
pngToJpeg({ quality: 90 })(buffer)
.then(output => {
let dest = fs.writeFileSync(pathjpg, output);
callback(pathjpg);
});
}
});
}
}
// export the class
module.exports = users;