## Models *sffs* ```jsx const mongoose = require("mongoose") const Schema = mongoose.Schema const taskSchema = Schema({ name: { type: String, require: true }, description: { type: String, require: true }, tag: { important: { type: Boolean, require: true, default: false }, urgent: { type: Boolean, require: true, default: false } }, status: { type: String, enum: ["pending", "working", "review", "done", "archive"], default: "pending" }, assigner: { type: mongoose.ObjectId, ref: "User", require: true }, assignee: [{ type: mongoose.ObjectId, ref: "User", require: true }], reviewDueAt: { type: Date, require: true }, reviewAt: [{ type: Date }], doneDueAt: { type: Date, require: true }, doneAt: { type: Date }, isDeleted: { type: Boolean, require: true, default: false } }, { timestamps: true }) const Task = mongoose.model("Task", taskSchema) module.exports = Task ``` ```jsx const mongoose = require("mongoose") const Schema = mongoose.Schema const userSchema = Schema({ name: { type: String, require: true }, role: { type: String, enum: ["assigner", "assignee"], require: true, default: "assignee" }, isDeleted: { type: Boolean, require: true, default: false } }, { timestamps: true }) const User = mongoose.model("User", userSchema) module.exports = User ``` ## Task controller ```jsx const Task = require("../model/Task"); const User = require("../model/User"); const taskController = {} taskController.getTasks = async (req, res, next) => { try { const assignerId = req.headers.authorization if (!assignerId) { const exception = new Error("Login required") exception.statusCode = 401 throw exception } const tasks = await Task.find({ isDeleted: false }) res.status(200).send(tasks); } catch (error) { next(error) } } taskController.getTaskById = async (req, res, next) => { try { const taskId = req.params.id const userId = req.headers.authorization if (!userId) { const exception = new Error("Login required") exception.statusCode = 401 throw exception } const task = await Task.findById(taskId) res.status(200).send(task); } catch (error) { next(error) } } taskController.createTask = async (req, res, next) => { try { const assignerId = req.headers.authorization const { name, description, tag, status, assignee, reviewDueAt, doneDueAt } = req.body if (!assignerId) { const exception = new Error("Login required") exception.statusCode = 401 throw exception } const assigner = await User.findById(assignerId) if (assigner.role !== "assigner") { const exception = new Error("Only assigner can assign task.") exception.statusCode = 401 throw exception } if (!name || !description || !assignee || !reviewDueAt || !doneDueAt) { const exception = new Error("Missing information") exception.statusCode = 404 throw exception } await Task.create({ name, description, tag, status, assignee, assigner: assignerId, reviewDueAt, doneDueAt }) res.status(200).send({ message: "New task created" }); } catch (err) { next(err) } } taskController.updateTask = async (req, res, next) => { try { const taskId = req.params.id const userId = req.headers.authorization let { name, description, tag, status, assignee, assigner, reviewDueAt, doneDueAt } = req.body if (!userId) { const exception = new Error("Login required") exception.statusCode = 401 throw exception } let task = await Task.findById(taskId) if (!task) { const exception = new Error("Task not found") exception.statusCode = 404 throw exception } const user = await User.findById(userId) console.log("first", task.assignee.includes(mongoose.Types.ObjectId(userId))) if (user.role !== "assigner" & !task.assignee.includes(mongoose.Types.ObjectId(userId))) { const exception = new Error("Can't change status of task that is not yours") exception.statusCode = 401 throw exception } switch (user.role) { case "assigner": if (task.status === "archive") { console.log("here") const exception = new Error("Can't touch archived tasks") exception.statusCode = 401 throw exception } break; default: //assignee if (task.status === "done" || task.status === "archive" || status === "done" || status === "archive") { const exception = new Error("Can't touch the task at this status") exception.statusCode = 401 throw exception } break; } if (!name || !description || !assignee?.length || !reviewDueAt || !doneDueAt) { const exception = new Error("Missing information") exception.statusCode = 404 throw exception } let reviewAt const basicTask = { name, description, tag, status, assignee, assigner, reviewDueAt, doneDueAt, } switch (status) { case "review": task = await Task.findByIdAndUpdate(taskId, { ...basicTask, $push: { reviewAt: Date.now() } }, { new: true }) break; case "done": task = await Task.findByIdAndUpdate(taskId, { ...basicTask, doneAt: Date.now() }, { new: true }) break; default: task = await Task.findByIdAndUpdate(taskId, basicTask, { new: true }) break; } res.status(200).send(task); } catch (error) { next(error) } } taskController.deleteTask = async (req, res, next) => { try { const id = req.params.id const userId = req.headers.authorization if (!userId) { const exception = new Error("Login required") exception.statusCode = 401 throw exception } let task = await Task.findById(id) if (!task) { const exception = new Error("Task not found") exception.statusCode = 404 throw exception } await Task.findByIdAndUpdate(id, { isDeleted: true }) res.status(200).send({ message: "the task is deleted" }); } catch (error) { next(error) } } module.exports = taskController ``` ## User controller ```jsx const Task = require("../model/Task") const User = require("../model/User") const userController = {} userController.getUsers = async (req, res, next) => { try { //get the userId from header of request const userId = req.headers.authorization //if there is no userId in header, throw exception that the user must login for authorization if (!userId) { const exception = new Error("Login required") exception.statusCode = 401 throw exception } //check if user exists const assigner = await User.findById(userId) if (!assigner) { const exception = new Error("User not found") exception.statusCode = 404 throw exception } const users = await User.find() res.status(200).send({ data: users, total: users.length }); } catch (error) { next(error) } } userController.getUserById = async (req, res, next) => { try { const userId = req.headers.authorization const id = req.params.id if (!userId) { const exception = new Error("Login required") exception.statusCode = 401 throw exception } const assigner = await User.findById(userId) if (!assigner) { const exception = new Error("User not found") exception.statusCode = 404 throw exception } const user = await User.findById(id) res.status(200).send(user); } catch (error) { next(error) } } userController.createUser = async (req, res, next) => { try { const { name, role } = req.body //get the userId from header of request const userId = req.headers.authorization //if there is no userId in header, throw exception if (!userId) { const exception = new Error("Login required") exception.statusCode = 401 throw exception } //check if user exists const assigner = await User.findById(userId) if (!assigner) { const exception = new Error("User not found") exception.statusCode = 404 throw exception } //check if user's role is assigner if (assigner.role !== "assigner") { const exception = new Error("Only assigner can create new user") exception.statusCode = 401 throw exception } if (!name || !role) { const exception = new Error("Missing information") exception.statusCode = 404 throw exception } await User.create({ name, role }) res.status(200).send({ message: "New user created" }); } catch (err) { next(err) } } module.exports = userController ```