'How to implement multi roles user authentication using express and mongoose?

I'm trying to create a MERN app where there will be multiple roles like 'principle', 'teacher', 'student', 'guardian'. Primarily I have created userModel to register users and create a role key that will have the different role values pointing to other models (like teacherModel/ studentModel). My userModel is like that

const mongoose = require('mongoose')

const userSchema = mongoose.Schema(
  {
    email: {
      type: String,
      required: [true, 'Please add an email'],
      unique: true
    },

    password: {
      type: String,
      required: [true, 'Please add a password']
    },

    role: [
      {
        type: mongoose.Schema.ObjectId,
        ref: 'Teacher'
      },

      {
        type: mongoose.Schema.ObjectId,
        ref: 'Student'
      }
    ]
  },

  {
    timestamps: true
  }
)

module.exports = mongoose.model('User', userSchema)

and the teacherModel is

const mongoose = require('mongoose')

const teacherSchema = mongoose.Schema({
  name: {
    type: String,
    required: [true, 'Please add your name']
  },

  teacherId: {
    type: Number,
    required: [true, 'Please add your teacher id']
  }
})

module.exports = mongoose.model('Teacher', teacherSchema)

I have created an userConroller, I want to register a user with their name, email, password, and role. I have put the name into the individual role so that I can search teachers or students separately, not both. Here, is my userController

const asyncHandler = require('express-async-handler')
const bcrypt = require('bcryptjs')

const User = require('../models/userModel')

// @description  Register a new user
// @route        /api/users
// @access       Public
const registerUser = asyncHandler(async (req, res) => {
  const { email, password, role } = req.body

  // Validation
  if (!name || !email || !password || !role) {
    res.status(400)

    throw new Error('Please include all fields')
  }

  // Find if user already exists
  const userExists = await User.findOne({ email })

  if (userExists) {
    res.status(400)

    throw new Error('User already exists')
  }

  // Hash Password
  const salt = await bcrypt.genSalt(10)
  const hashedPassword = await bcrypt.hash(password, salt)

  const user = await User.create({
    email,
    password: hashedPassword,
    role,
  })

  if (user) {
    res.status(201).json({
      _id: user._id,
      email: user.email,
      role: user.role
    })
  } else {
    res.status(400)

    throw new error('Invalid user data')
  }
})

When I try to register with postman, I get this error message,

"User validation failed: role.0: Cast to [ObjectId] failed for value "[ 'teacher' ]" (type string) at path "role.0" because of "CastError""

What have I messed up?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source