Source: models/auth.js

/**
 * 
 * Authentication related methods
 * 
 */
const md5 = require('md5');
const Usersgroups = require('./usersgroups');


class auth {

    constructor() {

    }

    /**
     * Returns access groups (users_groups) for given user
     * @param {integer} uId userId of user
     * @param {*} callback rows or null
     */
    getUsersGroupsForUserWithId(uId, callback) {
        let query = "SELECT " +
            "xt_users_users_groups.*, " +
            "users_groups.isSystemGroup, " +
            "users_groups.grantnamespace, " +
            "users_groups.title AS groupTitle " +
            "FROM xt_users_users_groups " +
            "INNER JOIN users_groups ON users_groups.id = xt_users_users_groups.groupId " +
            "WHERE xt_users_users_groups.userId = ?";
        global.coreDb.all(query, [
            uId
        ], (err, rows) => {
            if (err) {
                this._logger.error('AUTH-MODEL | Error loading users group for user from core data: ' + err.message);
                return callback(null);
            } else {
                return callback(rows);
            }
        });
    }

    /**
     * 
     * @param {string} username username
     * @param {string} passwordHashMD5 hash of password
     * @param {function} callback success (true/false), if true row of user from core database
     */
    authenticateUserMD5(username, passwordHashMD5, callback) {
        let query = "SELECT `users`.*, " +
            "`organizations`.`name` AS organizationname, " +
            "`basedata`.`image` AS image, " +
            "`basedata`.`firstname` AS firstname, " +
            "`basedata`.`id` AS basedataId, " +
            "`basedata`.`lastname` AS lastname " +
            "FROM `users` " +
            "LEFT JOIN `basedata` ON `users`.`basedataid` = `basedata`.`id` " +
            "LEFT JOIN `organizations` ON `basedata`.`organizationid` = `organizations`.`id` " +
            "WHERE `username` = ? COLLATE NOCASE";

        global.coreDb.all(query, [
            username
        ], (err, rows) => {
            if (err) {
                this._logger.error('AUTH-MODEL | Error loading user for authentication from core data: ' + err.message);
                return callback(false, null);
            } else {
                if (rows.length > 0) {
                    // user found
                    var userRow = rows[0];
                    // Check if passwords match
                    if (passwordHashMD5 === userRow['password']) {
                        // Password typed in correct --> return user row
                        if (userRow['state'] === 1) {
                            // user is active
                            this.setLastLoginDate(userRow.id, (successLastLogin) => {
                                if (successLastLogin) {
                                    return callback(true, userRow);
                                } else {
                                    return callback(false, userRow);
                                }
                            })
                        } else {
                            return callback(false, userRow);
                        }
                        
                    } else if (passwordHashMD5 === userRow['startPasswordHash']) {
                        // User sent in a startPassword --> inform App that user is enforced to change password now
                        if (userRow['state'] === 1) {
                            // user is active
                            this.setLastLoginDate(userRow.id, (successLastLogin) => {
                                if (successLastLogin) {
                                    return callback(true, userRow);
                                } else {
                                    return callback(false, userRow);
                                }
                            })
                        } else {
                            return callback(false, userRow);
                        }
                    } else {
                        
                        return callback(false, null)
                    }
                } else {
                    // No User for given username found
                    return callback(false, null);
                }

            }
        });
    }

    /**
     * 
     * @param {string} username username caseinsensitive as string
     * @param {string} password password casesensitive as string
     * @param {function} callback success(true or false), userrowsuccess (row or null), passwordchange enforced (true, false)
     */
    authenticateUser(username, password, callback) {
        let query = "SELECT `users`.*, " +
            "`organizations`.`name` AS organizationname, " +
            "`basedata`.`image` AS image, " +
            "`basedata`.`firstname` AS firstname, " +
            "`basedata`.`lastname` AS lastname " +
            "FROM `users` " +
            "LEFT JOIN `basedata` ON `users`.`basedataid` = `basedata`.`id` " +
            "LEFT JOIN `organizations` ON `basedata`.`organizationid` = `organizations`.`id` " +
            "WHERE `username` = ? COLLATE NOCASE";

        global.coreDb.all(query, [
            username
        ], (err, rows) => {
            if (err) {
                this._logger.error('AUTH-MODEL | Error loading user for authentication from core data: ' + err.message);
                return callback(false, null, false);
            } else {
                if (rows.length > 0) {
                    // user found
                    var userRow = rows[0];
                    // Check if passwords match
                    var passwordHashMD5 = md5(password);
                    if (passwordHashMD5 === userRow['password']) {
                        this.setLastLoginDate(userRow.id, (successLastLogin) => {
                            if (successLastLogin) {
                                return callback(true, userRow, false);
                            } else {
                                return callback(false, userRow, false);
                            }

                        })
                    } else if (password === userRow['startPassword']) {
                        // User sent his startPassword
                        this.setLastLoginDate(userRow.id, (successLastLogin) => {
                            if (successLastLogin) {
                                return callback(true, userRow, true);
                            } else {
                                return callback(false, userRow, false);
                            }
                        })
                    } else {
                        // Wrong password typed in
                        return callback(false, null, false)
                    }
                } else {
                    // No User for given username found
                    return callback(false, null, false);
                }

            }
        });
    }

    /**
     * Sets last login timestamp in user record in core database to "now" in local timezone
     * @param {integer} uId 
     * @param {function} callback success, true or false
     */
    setLastLoginDate(uId, callback) {
        let query = "UPDATE users SET lastlogin = DATETIME('now', 'localtime') WHERE id = ?;"
        global.coreDb.all(query, [
            uId
        ], (err, rows) => {
            if (err) {
                this._logger.error('AUTH-MODEL | Error setting last login date in core database for user: ' + err.message);
                return callback(false);
            } else {
                return callback(true);
            }
        });
    }

    /**
     * Changes a users password
     * @param {integer} basedataId basedata id of user the password should be changed for
     * @param {string} oldPassword the old password
     * @param {string} newPassword the new password
     * @param {function} callback success (true or false)
     */
    changePassword(username, oldPassword, newPassword, callback) {
        let query = "SELECT * FROM users WHERE username = ?;"
        global.coreDb.all(query, [
            username
        ], (err, rows) => {
            if (err) {
                this._logger.error('AUTH-MODEL | Error getting user for password change request: ' + err.message);
                return callback(false);
            } else {
                if (rows.length > 0) {
                    // User found. Check if passwords match
                    var passwordHashMD5 = md5(oldPassword);
                    if (passwordHashMD5 === rows[0]['password']) {
                        // given old password matches existing one in database. now set the new password in database;
                        var newPasswordMD5 = md5(newPassword);
                        let query = "UPDATE users SET password = ? WHERE username = ?";
                        global.coreDb.all(query, [
                            newPasswordMD5,
                            username
                        ], (err, rows) => {
                            if (err) {
                                this._logger.error('AUTH-MODEL | Error setting new password in core database for user: ' + err.message);
                                return callback(false);
                            } else {
                                return callback(true);
                            }
                        });
                    } else {
                        // Wrong password typed in
                        return callback(false)
                    }
                } else {
                    return callback(false);
                }
            }
        });
    }

    /**
     * Checks if session is valid for redirecting user from login page to home dashboard
     * @param {object} session session object
     * @param {*} callback valid (true) or not valid (false)
     */
    checkForValidSession(session, callback) {
        var valid = false;
        if (typeof session != 'undefined') {
            if (session != null) {
                if (typeof session.loggedin != 'undefined') {
                    if (session.loggedin === true) {
                        valid = true;
                    } else {
                        return callback(false);
                    }
                } else {
                    return callback(false);
                }
                if (typeof session.username != 'undefined') {
                    if (session.username.length > 0) {
                        valid = true;
                    } else {
                        return callback(false);
                    }
                } else {
                    return callback(false);
                }
                if (typeof session.userid != 'undefined') {
                    if (session.userid > 0) {
                        valid = true;
                    } else {
                        return callback(false);
                    }
                } else {
                    return callback(false);
                }
                if (typeof session.basedataId != 'undefined') {
                    if (session.basedataId > 0) {
                        valid = true;
                    } else {
                        return callback(false);
                    }
                } else {
                    return callback(false);
                }
                if (typeof session.organization != 'undefined') {
                    if (session.organization.length > 0) {
                        valid = true;
                    } else {
                        return callback(false);
                    }
                } else {
                    return callback(false);
                }
                if (typeof session.name != 'undefined') {
                    if (session.name.length > 0) {
                        valid = true;
                    } else {
                        return callback(false);
                    }
                } else {
                    return callback(false);
                }

                return callback(valid);
            } else {
                return callback(false);
            }
        } else {
            return callback(false);
        }
    }
}

module.exports = auth;