Asymmetrik/mean2-starter

View on GitHub
src/server/app/admin/controllers/users/users.profile.server.controller.js

Summary

Maintainability
D
2 days
Test Coverage
'use strict';

let _ = require('lodash'),
    path = require('path'),
    q = require('q'),

    deps = require(path.resolve('./src/server/dependencies.js')),
    config = deps.config,
    dbs = deps.dbs,
    util = deps.utilService,
    logger = deps.logger,
    auditService = deps.auditService,

    User = dbs.admin.model('User');

/**
 * Private methods
 */

function searchUsers(req, res, copyUserFn) {

    // Handle the query/search/page
    let query = req.body.q;
    let search = req.body.s;

    let page = req.query.page;
    let size = req.query.size;
    let sort = req.query.sort;
    let dir = req.query.dir;

    // Limit has to be at least 1 and no more than 100
    if (null == size) { size = 20; }
    size = Math.max(1, Math.min(100, size));

    // Page needs to be positive and has no upper bound
    if (null == page){ page = 0; }
    page = Math.max(0, page);

    // Sort can be null, but if it's non-null, dir defaults to DESC
    if (null != sort && dir == null) { dir = 'DESC'; }

    // Create the variables to the search call
    let limit = size;
    let offset = page*size;
    let sortArr;
    if (null != sort){
        sortArr = [{ property: sort, direction: dir }];
    }

    User.search(query, search, limit, offset, sortArr).then((result) => {

        // Create the return copy of the users
        let users = [];
        result.results.forEach((element) => {
            users.push(copyUserFn(element));
        });

        // success
        let toReturn = {
            totalSize: result.count,
            pageNumber: page,
            pageSize: size,
            totalPages: Math.ceil(result.count/size),
            elements: users
        };

        // Serialize the response
        res.status(200).json(toReturn);
    }, (error) => {
        // failure
        logger.error(error);
        return util.send400Error(res, error);
    });
}


/**
 * Standard User Operations
 */

// Get Current User
exports.getCurrentUser = (req, res) => {

    // The user that is a parameter of the request is stored in 'userParam'
    let user = req.user;

    if (null == user){
        res.status(400).json({
            message: 'User not logged in'
        });
        return;
    }

    res.status(200).json(User.fullCopy(user));
};


// Update Current User
exports.updateCurrentUser = (req, res) => {

    // Make sure the user is logged in
    if (null == req.user){
        res.status(400).json({
            message: 'User is not signed in'
        });
        return;
    }

    // Get the full user (including the password)
    User.findOne({
        _id: req.user._id
    }).exec((err, user) => {

        let originalUser = User.auditCopy(user);

        // Copy over the new user properties
        user.name = req.body.name;
        user.organization = req.body.organization;
        user.email = req.body.email;
        user.phone = req.body.phone;
        user.username = req.body.username;
        user.messagesViewed = req.body.messagesViewed;

        // Update the updated date
        user.updated = Date.now();

        // If they are changing the password, verify the current password
        if (_.isString(req.body.password) && !_.isEmpty(req.body.password)) {
            if (!user.authenticate(req.body.currentPassword)) {

                // Audit failed authentication
                auditService.audit('user update authentication failed', 'user', 'update authentication failed',
                    User.auditCopy(req.user, util.getHeaderField(req.headers, 'x-real-ip')), {}, req.headers);

                res.status(400).json({
                    message: 'Current password invalid'
                });
                return;
            }

            // We passed the auth check and we're updating the password
            user.password = req.body.password;
        }

        // Save the user
        user.save((err) => {
            util.catchError(res, err, () => {
                // Remove the password/salt
                delete user.password;
                delete user.salt;

                // Audit user update
                auditService.audit('user updated', 'user', 'update',
                    User.auditCopy(req.user, util.getHeaderField(req.headers, 'x-real-ip')),
                    { before: originalUser, after: User.auditCopy(user) }, req.headers);

                // Log in with the new info
                req.login(user, (err) => {
                    if (err) {
                        res.status(400).json(err);
                    } else {
                        res.status(200).json(User.fullCopy(user));
                    }
                });
            });
        });

    });
};


// Get a filtered version of a user by id
exports.getUserById = (req, res) => {

    // The user that is a parameter of the request is stored in 'userParam'
    let user = req.userParam;

    if (null == user){
        res.status(400).json({
            message: 'User does not exist'
        });
        return;
    }

    res.status(200).json(User.filteredCopy(user));
};

// Search for users (return filtered version of user)
exports.searchUsers = (req, res) => {
    searchUsers(req, res, User.filteredCopy);
};

// Match users given a search fragment
exports.matchUsers = (req, res) => {
    // Handle the query/search/page
    let query = req.body.q;
    let search = req.body.s;

    let page = req.query.page;
    let size = req.query.size;
    let sort = req.query.sort;
    let dir = req.query.dir;

    // Limit has to be at least 1 and no more than 100
    if (null == size){ size = 20; }
    size = Math.max(1, Math.min(100, size));

    // Page needs to be positive and has no upper bound
    if (null == page){ page = 0; }
    page = Math.max(0, page);

    // Sort can be null, but if it's non-null, dir defaults to DESC
    if (null != sort && dir == null){ dir = 'ASC'; }

    // Create the variables to the search call
    let limit = size;
    let offset = page*size;
    let sortArr;
    if (null != sort){
        sortArr = [{ property: sort, direction: dir }];
    }

    User.containsQuery(query, ['name', 'username', 'email'], search, limit, offset, sortArr).then((result) => {

        // Create the return copy of the users
        let users = [];
        result.results.forEach((element) => {
            users.push(User.filteredCopy(element));
        });

        // success
        let toReturn = {
            totalSize: result.count,
            pageNumber: page,
            pageSize: size,
            totalPages: Math.ceil(result.count/size),
            elements: users
        };

        // Serialize the response
        res.status(200).json(toReturn);
    }, (error) => {
        // failure
        logger.error(error);
        return util.send400Error(res, error);
    });
};



/**
 * Admin User Operations
 */

// Admin Get a User
exports.adminGetUser = (req, res) => {

    // The user that is a parameter of the request is stored in 'userParam'
    let user = req.userParam;

    if (null == user){
        res.status(400).json({
            message: 'User is not signed in'
        });
        return;
    }

    res.status(200).json(User.fullCopy(user));
};

//Admin Get All Users
exports.adminGetAll = (req, res) => {

    // The field that the admin is requesting is a query parameter
    let field = req.body.field;
    if ( null == field || field.length === 0 ) {
        res.status(500).json({
            message: 'Query field must be provided'
        });
    }

    let query = req.body.query;

    logger.debug('Querying Users for %s', field);
    let proj = {};
    proj[field] = 1;
    User.find(util.toMongoose(query), proj)
        .exec((error, results) => {

            if (null != error) {
                // failure
                logger.error(error);
                return util.send400Error(res, error);
            }

            res.status(200).json(results.map((r) => { return r[field]; }));
        });
};

// Admin Update a User
exports.adminUpdateUser = (req, res) => {

    // The persistence user
    let user = req.userParam;

    // A copy of the original user for auditing
    let originalUser = User.auditCopy(user);

    if (null == user){
        res.status(400).json({
            message: 'Could not find user'
        });
        return;
    }

    // Copy over the new user properties
    user.name = req.body.name;
    user.organization = req.body.organization;
    user.email = req.body.email;
    user.phone = req.body.phone;
    user.username = req.body.username;
    user.roles = req.body.roles;
    user.bypassAccessCheck = req.body.bypassAccessCheck;

    if (_.isString(req.body.password) && !_.isEmpty(req.body.password)) {
        user.password = req.body.password;
    }


    // Update the updated date
    user.updated = Date.now();

    // Save the user
    user.save((err) => {
        util.catchError(res, err, () => {
            // Audit user update
            auditService.audit('admin user updated', 'user', 'admin update',
                User.auditCopy(req.user, util.getHeaderField(req.headers, 'x-real-ip')),
                { before: originalUser, after: User.auditCopy(user) }, req.headers);

            res.status(200).json(User.fullCopy(user));
        });
    });
};


// Admin Delete a User
exports.adminDeleteUser = (req, res) => {
    // Init Variables
    let user = req.userParam;

    if (null == user){
        res.status(400).json({
            message: 'Could not find user'
        });
        return;
    }

    // Delete the user
    user.remove((err) => {
        util.catchError(res, err, () => {
            // Audit user delete
            auditService.audit('admin user deleted', 'user', 'admin delete',
                User.auditCopy(req.user, util.getHeaderField(req.headers, 'x-real-ip')),
                User.auditCopy(user), req.headers);

            res.status(200).json(User.fullCopy(user));
        });
    });
};


// Admin Search for Users
exports.adminSearchUsers = (req, res) => {
    searchUsers(req, res, User.fullCopy);
};

function canEditProfile(authStrategy, user) {
    return authStrategy !== 'proxy-pki' || user.bypassAccessCheck === true;
}

exports.canEditProfile = canEditProfile;

// Are allowed to edit user profile info
exports.hasEdit = (req) => {
    let defer = q.defer();

    if (canEditProfile(config.auth.strategy, req.user)) {
        defer.resolve();
    }
    else {
        defer.reject({ status: 403, type: 'not-authorized', message: 'User not authorized to edit their profile' });
    }

    return defer.promise;
};