How can I hide certain attribute from response with Bookshelf?

128 Views Asked by At

I am building a simple REST API. When registering a new user, my API returns:

{
    "status": "success",
    "data": {
        "email": "[email protected]",
        "password": "$2b$10$DcFdth1FKskyy6A7uwCHDOE15oy4pgZBj.TwEBcQnSVrUK4mntZdy"
        "first_name": "Tester",
        "last_name": "Test",
        "id": 13
    }
}

I want to hide the password field in my response like so:

{
    "status": "success",
    "data": {
        "email": "[email protected]",
        "first_name": "Tester",
        "last_name": "Test",
        "id": 13
    }
}

I've added delete user.attributes.password to my code, but is this correct?

My code:

/**
 * Auth Controller
 */

const bcrypt = require('bcrypt');
const debug = require('debug')('books:auth_controller');
const { matchedData, validationResult } = require('express-validator');
const models = require('../models');

/**
 * Register a new user
 *
 * POST /register
 */
const register = async (req, res) => {
    // check for any validation errors
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
        return res.status(422).send({ status: 'fail', data: errors.array() });
    }

    // get only the validated data from the request
    const validData = matchedData(req);

    console.log("The validated data:", validData);

    // generate a hash of `validData.password`
    // and overwrite `validData.password` with the generated hash
    try {
        validData.password = await bcrypt.hash(validData.password, models.User.hashSaltRounds);

    } catch (error) {
        res.status(500).send({
            status: 'error',
            message: 'Exception thrown when hashing the password.',
        });
        throw error;
    }

    try {
        const user = await new models.User(validData).save();
        debug("Created new user successfully: %O", user);

        delete user.attributes.password;

        res.send({
            status: 'success',
            data: user,
        });

    } catch (error) {
        res.status(500).send({
            status: 'error',
            message: 'Exception thrown in database when creating a new user.',
        });
        throw error;
    }
}

module.exports = {
    register,
}

This is my user model. I am using Bookshelf.js.

/**
 * User model
 */

module.exports = (bookshelf) => {
    return bookshelf.model('User', {
        tableName: 'users',
        albums() {
            return this.hasMany('Album');
        },
        photos() {
        return this.hasMany('Photo');
    }
}, {
        hashSaltRounds: 10,

        async fetchById(id, fetchOptions = {}) {
            return await new this({ id }).fetch(fetchOptions);
        },

        async login(email, password) {
            // find user based on the email (bail if no such user exists)
            const user = await new this({ email }).fetch({ require: false });
            if (!user) {
                return false;
            }
            const hash = user.get('password');

            // hash the incoming cleartext password using the salt from the db
            // and compare if the generated hash matches the db-hash
            const result = await bcrypt.compare(password, hash);
            if (!result) {
                return false;
            }

            // all is well, return user
            return user;
        }
    });
};

1

There are 1 best solutions below

0
BaDr Amer On

you can add a list of model attributes to exclude from the output when serializing it. check it out here

return bookshelf.model('User', {
    tableName: 'users',
    hidden: ['password']
})