Added suspension mechanism.

This commit is contained in:
Harrison Deng 2022-04-07 17:56:04 -05:00
parent 2e8ba9c5b1
commit eb4e4b2444
5 changed files with 107 additions and 40 deletions

View File

@ -5,6 +5,6 @@ export const apiClient = axios.create({
timeout: 5000, timeout: 5000,
withCredentials: process.env.NODE_ENV === "development", withCredentials: process.env.NODE_ENV === "development",
validateStatus: function (status) { validateStatus: function (status) {
return status === 401 || status == 200; return status === 401 || status === 200 || status === 400 || status === 201;
} }
}); });

View File

@ -1,5 +1,6 @@
import express from "express"; import express from "express";
import { requireAuthenticated } from "../middleware/authority.js"; import validator from "validator";
import { requireAdmin, requireAuthenticated } from "../middleware/authority.js";
import { needDatabase } from "../middleware/database.js"; import { needDatabase } from "../middleware/database.js";
import userModel from "../schemas/userModel.js"; import userModel from "../schemas/userModel.js";
import User from "../schemas/userModel.js"; import User from "../schemas/userModel.js";
@ -67,50 +68,85 @@ UserController.get("/:id?", needDatabase, requireAuthenticated, async (req, res)
res.status(200).send(user); res.status(200).send(user);
}); });
UserController.patch("/:id?", needDatabase, requireAuthenticated, async (req, res) => { UserController.patch("/:id?", needDatabase, requireAuthenticated, async (req, res) => {
let user = null; try {
if (req.params.id) { let user = null;
if (req.user.accessLevel > 2) { if (req.params.id) {
user = await userModel.findById(req.params.id); if (req.user.accessLevel > 2) {
user = await userModel.findById(req.params.id);
} else {
res.status(401).send("Unauthorized.");
return;
}
} else { } else {
res.status(401).send("Unauthorized."); user = req.user;
}
if (req.body._id) {
res.status(400).send("Cannot change user ID.");
return; return;
} }
} else {
user = req.user;
}
if (req.body._id) {
res.status(400).send("Cannot change user ID.");
return;
}
if (req.body.createdMatches) { if (req.body.createdMatches) {
res.status(400).send("Cannot directly change the list of created matches."); res.status(400).send("Cannot directly change the list of created matches.");
return; return;
} }
if (req.body.password) { if (req.body.password) {
res.status(400).send("Cannot directly change user password."); res.status(400).send("Cannot directly change user password.");
return; return;
} }
if (req.body.participatingMatches) { if (req.body.participatingMatches) {
res.status(400).send("Cannot directly change the list of participating matches."); res.status(400).send("Cannot directly change the list of participating matches.");
return; return;
} }
if (req.body.joinDate) { if (req.body.joinDate) {
res.status(400).send("Cannot change the join date."); res.status(400).send("Cannot change the join date.");
return; return;
} }
if (req.body.accessLevel && req.user.accessLevel < 3) { if (req.body.accessLevel && req.user.accessLevel < 3) {
res.status(401).send("Unauthorized to change the access level of this user."); res.status(401).send("Unauthorized to change the access level of this user.");
return; return;
} }
await user.updateOne(req.body); if (req.body.suspend && req.user.accessLevel < 3) {
res.status(200).send("Updated."); res.status(401).send("Unauthorized to change the accounts disabled date. ");
return;
}
await user.updateOne(req.body);
res.status(200).send("Updated.");
} catch (error) {
console.error(error);
res.status(500).send("Internal server error");
}
});
UserController.get("/all/active", requireAdmin, async (req, res) => {
try {
if (req.user.accessLevel < 3) {
res.status(401).send("You do not have the required privileges.");
return;
}
let res = await userModel.find().where("suspend").lt(Date.now);
res.status(200).send({ all: res });
} catch (error) {
console.error(error);
res.status(500).send("Internal server error");
}
});
UserController.get("/all/suspended", requireAuthenticated, async (req, res) => {
try {
let res = await userModel.find().where("suspend").gte(Date.now);
res.status(200).send({ suspended: res });
} catch (error) {
console.error(error);
res.status(500).send("Internal server error");
}
}); });
/* TODO: Implement middleware for removing users. /* TODO: Implement middleware for removing users.
@ -136,13 +172,15 @@ UserController.delete("/:id?", needDatabase, requireAuthenticated, async (req, r
UserController.post("/", needDatabase, async (req, res) => { UserController.post("/", needDatabase, async (req, res) => {
try { try {
let createdUser = new User({ const data = {
email: req.body.email, email: req.body.email,
firstName: req.body.firstName, firstName: req.body.firstName,
lastName: req.body.lastName, lastName: req.body.lastName,
phone: req.body.phone, phone: req.body.phone,
password: req.body.password, password: req.body.password,
}); };
let createdUser = new User(data);
await createdUser.save(); await createdUser.save();
res.sendStatus(201); res.sendStatus(201);
return; return;

View File

@ -2,6 +2,7 @@ import MongoStore from "connect-mongo";
import session from "express-session"; import session from "express-session";
import { mongooseDbName, mongoURI } from "../database/mongoose.js"; import { mongooseDbName, mongoURI } from "../database/mongoose.js";
import userModel from "../schemas/userModel.js"; import userModel from "../schemas/userModel.js";
import { checkDatabaseConnection } from "./database.js";
const sessionConf = { const sessionConf = {
secret: process.env.SESSION_SECRET || "super duper secret string.", secret: process.env.SESSION_SECRET || "super duper secret string.",
cookie: { cookie: {
@ -18,6 +19,10 @@ if (process.env.NODE_ENV === "production") {
export const userSession = session(sessionConf); export const userSession = session(sessionConf);
export async function requireAuthenticated(req, res, next) { export async function requireAuthenticated(req, res, next) {
if (!checkDatabaseConnection()) {
req.status(500).send("Internal server error.");
return;
}
if (req.session.userId) { if (req.session.userId) {
req.user = await userModel.findById(req.session.userId); req.user = await userModel.findById(req.session.userId);
next(); next();
@ -26,3 +31,22 @@ export async function requireAuthenticated(req, res, next) {
return; return;
} }
} }
export async function requireAdmin(req, res, next) {
if (!checkDatabaseConnection()) {
req.status(500).send("Internal server error.");
return;
}
if (req.session.userId) {
req.user = await userModel.findById(req.session.userId);
if (req.user.accessLevel < 3) {
res.status(401).send("Not authorized");
return;
}
next();
} else {
res.status(401).send("Not authorized.");
return;
}
}

View File

@ -1,9 +1,13 @@
import mongoose from "mongoose"; import mongoose from "mongoose";
export function needDatabase(res, req, next) { export function needDatabase(req, res, next) {
if (mongoose.connection.readyState != 1) { if (checkDatabaseConnection()) {
res.status(500).send("Internal server error: Database connection faulty."); res.status(500).send("Internal server error: Database connection faulty.");
} else { } else {
next(); next();
} }
}
export function checkDatabaseConnection() {
return mongoose.connection.readyState == 1;
} }

View File

@ -36,6 +36,7 @@ const userSchema = new mongoose.Schema({
participatingMatchesPublicity: { type: Boolean, required: true, default: false }, participatingMatchesPublicity: { type: Boolean, required: true, default: false },
friends: { type: Types.ObjectId, ref: modelNameRegister.User }, friends: { type: Types.ObjectId, ref: modelNameRegister.User },
accessLevel: { type: Number, required: true, default: 0 }, accessLevel: { type: Number, required: true, default: 0 },
suspend: { type: Date, required: true, default: Date.now } // suspend the user until the when the user was created.
}); });
userSchema.statics.credentialsExist = async function (email, password) { userSchema.statics.credentialsExist = async function (email, password) {