tolulope-od/banka

View on GitHub
server/controllers/UserController.js

Summary

Maintainability
B
4 hrs
Test Coverage
import bcrypt from 'bcrypt';
import jwt from 'jsonwebtoken';
import { accounts } from './AccountController';
import { users } from './AuthController';
import { isEmpty } from '../validation/authValidation';

export default class UserController {
  /**
   * @description Get a all accounts owned by a user
   * @param {Object} req The request object
   * @param {Object} res The response object
   * @route Get /api/v1/users/:user-email-address/accounts
   * @returns {Object} status code, data and message properties
   * @access private Staff and Client
   */
  static async fetchAllAccountsByUser(req, res) {
    const { userEmail } = req.params;
    let userAccounts;
    if (req.decoded.type !== 'staff') {
      if (req.decoded.email !== userEmail) {
        return res.status(403).json({
          status: 403,
          error: 'You are not authorized to carry out that action'
        });
      }
      userAccounts = await accounts.select(['*'], [`owneremail='${userEmail}'`]);
      return res.status(200).json({
        status: 200,
        data: userAccounts
      });
    }
    const doesUserExist = await users.select(['email'], [`email='${userEmail}'`]);
    if (isEmpty(doesUserExist)) {
      return res.status(404).json({
        status: 404,
        error: 'User not found'
      });
    }

    userAccounts = await accounts.select(['*'], [`owneremail='${doesUserExist[0].email}'`]);
    return res.status(200).json({
      status: 200,
      data: userAccounts
    });
  }

  /**
   * @description Upgrade a client to a staff
   * @param {Object} req The request object
   * @param {Object} res The response object
   * @route PATCH /api/v1/users/
   * @returns {Object} status code, data and message properties
   * @access private Admin
   */
  static async adminAddStaff(req, res) {
    if (req.decoded.isAdmin) {
      const { userEmail } = req.body;
      const findUser = await users.select(['*'], [`email='${userEmail}'`]);

      if (isEmpty(findUser)) {
        return res.status(404).json({
          status: 404,
          error: 'User not found'
        });
      }
      const { type, isAdmin } = findUser[0];
      if (type === 'staff' || isAdmin) {
        return res.status(409).json({
          status: 409,
          error: 'User is already a staff'
        });
      }

      const updatedUser = await users.update([`type='staff'`], [`email='${userEmail}'`]);
      const data = {
        id: updatedUser[0].id,
        firstname: updatedUser[0].firstname,
        lastname: updatedUser[0].lastname,
        email: updatedUser[0].email,
        type: updatedUser[0].type,
        isadmin: updatedUser[0].isadmin,
        createdat: updatedUser[0].createdat
      };
      return res.status(200).json({
        status: 200,
        data: [data],
        message: 'User is now a staff'
      });
    }

    return res.status(403).json({
      status: 403,
      error: 'You are not allowed to carry out that action'
    });
  }

  /**
   * @description Create a staff
   * @param {Object} req The request object
   * @param {Object} res The response object
   * @route POST /api/v1/users/
   * @returns {Object} status code, data and message properties
   * @access private Admin
   */
  static async createStaff(req, res) {
    if (req.decoded.isAdmin) {
      const { firstName, lastName, email, admin } = req.body;
      const existingUser = await users.select(['email'], [`email='${email}'`]);
      if (existingUser.length > 0) {
        return res.status(409).json({
          status: 409,
          error: 'Staff already exists'
        });
      }
      let isAdmin = true;
      if (isEmpty(admin)) {
        isAdmin = false;
      }
      const hashed = bcrypt.hashSync(lastName, 10);
      const newUser = await users.create(
        ['firstName', 'lastName', 'email', 'password', 'isAdmin', 'type'],
        [`'${firstName}', '${lastName}', '${email}', '${hashed}', ${isAdmin}, 'staff'`]
      );

      const payload = {
        id: newUser[0].id,
        email: newUser[0].email,
        type: newUser[0].type,
        firstName: newUser[0].firstname,
        lastName: newUser[0].lastname,
        isAdmin: newUser[0].isadmin
      };
      const token = jwt.sign(payload, process.env.SECRET_KEY, {
        expiresIn: '1hr'
      });
      const data = {
        token,
        id: newUser[0].id,
        firstName: newUser[0].firstname,
        lastName: newUser[0].lastname,
        email: newUser[0].email,
        type: newUser[0].type,
        isAdmin: newUser[0].isadmin,
        createdAt: newUser[0].createdat
      };
      return res.status(201).json({
        status: 201,
        data: [data],
        message: 'Staff created successfully'
      });
    }

    return res.status(401).json({
      status: 401,
      error: 'You are not allowed to carry out that action'
    });
  }

  /**
   * @description Get all stall
   * @param {Object} req The request object
   * @param {Object} res The response object
   * @route GET /api/v1/users/
   * @returns {Object} status code, data and message properties
   * @access private Admin
   */
  static async getAllStaff(req, res) {
    const { type } = req.decoded;
    if (type !== 'staff') {
      res.status(401).json({
        status: 401,
        error: 'Not allowed!'
      });
    }

    const allStaff = await users.select(
      ['id', 'firstname', 'lastname', 'email', 'type', 'isadmin', 'createdat'],
      [`type='staff'`]
    );
    res.status(200).json({
      status: 200,
      data: allStaff
    });
  }
}