From 1fc0c19b999d2d4cc1031e4f03ef403cb382897b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rafael=20L=C3=A1szl=C3=B3?= <rlacko99@gmail.com>
Date: Sun, 3 Jan 2021 18:23:37 +0100
Subject: [PATCH] refactored user and some API

---
 src/middlewares/auth/isAdmin.ts               |  17 ++
 src/middlewares/auth/isStaffOrAdmin.ts        |  25 ---
 src/middlewares/files/updateProfilePicture.ts |   4 +-
 src/middlewares/news/getNewsList.ts           |   1 -
 src/middlewares/user/acceptPicture.ts         |   5 +-
 src/middlewares/user/deleteUser.ts            |   1 +
 src/middlewares/user/getUser.ts               |   7 +-
 src/middlewares/user/getUserWarningsList.ts   |   8 +-
 src/middlewares/user/getUsersList.ts          |  17 +-
 src/middlewares/user/rejectPicture.ts         |  32 ++++
 src/middlewares/user/setOwnUserId.ts          |   3 -
 src/middlewares/user/updateUser.ts            |  10 +-
 src/middlewares/utils/createdResponse.ts      |   2 +-
 src/middlewares/utils/getFieldValue.ts        |   2 +-
 src/middlewares/warning/addWarning.ts         |  43 +++--
 src/middlewares/warning/deleteWarning.ts      |  11 +-
 src/middlewares/warning/getWarning.ts         |   8 +-
 src/middlewares/warning/getWarningsList.ts    |   4 +-
 src/middlewares/warning/updateWarning.ts      |  27 ++-
 src/models/CounterSchema.ts                   |  14 --
 src/models/NotificationSchema.ts              |  13 --
 src/models/ProfileSchema.ts                   |  46 ++++-
 src/models/TermSchema.ts                      |   1 +
 src/models/WarningSchema.ts                   |  26 ---
 src/routes/files.ts                           |  40 ++--
 src/routes/news.ts                            |  14 +-
 src/routes/notifications.ts                   |   7 +
 src/routes/terms.ts                           |  41 +++--
 src/routes/user.ts                            | 171 +++++++++++++-----
 src/routes/warnings.ts                        |  12 +-
 30 files changed, 359 insertions(+), 253 deletions(-)
 create mode 100644 src/middlewares/auth/isAdmin.ts
 delete mode 100644 src/middlewares/auth/isStaffOrAdmin.ts
 create mode 100644 src/middlewares/user/rejectPicture.ts
 delete mode 100644 src/models/NotificationSchema.ts
 delete mode 100644 src/models/WarningSchema.ts

diff --git a/src/middlewares/auth/isAdmin.ts b/src/middlewares/auth/isAdmin.ts
new file mode 100644
index 00000000..b1b58d95
--- /dev/null
+++ b/src/middlewares/auth/isAdmin.ts
@@ -0,0 +1,17 @@
+import { NextFunction, Request, Response } from "express";
+
+import { Role } from "../../models/ProfileSchema";
+
+/**
+ * Middleware to check if the user
+ * is Staff member or Admin
+ */
+const isAdmin = () => (req: Request, res: Response, next: NextFunction) => {
+  if (req.session.user?.role == Role.Admin) return next();
+
+  return res
+    .status(403)
+    .json({ message: "You have to be Admin to see this page!" });
+};
+
+export default isAdmin;
diff --git a/src/middlewares/auth/isStaffOrAdmin.ts b/src/middlewares/auth/isStaffOrAdmin.ts
deleted file mode 100644
index d3cd7d44..00000000
--- a/src/middlewares/auth/isStaffOrAdmin.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import { NextFunction, Request, Response } from "express";
-
-import { Role } from "../../models/ProfileSchema";
-
-/**
- * Middleware to check if the user
- * is Staff member or Admin
- */
-const isStaffOrAdmin = () => (
-  req: Request,
-  res: Response,
-  next: NextFunction
-) => {
-  if (
-    req.session.user?.role == Role.Staff ||
-    req.session.user?.role == Role.Admin
-  )
-    return next();
-
-  return res
-    .status(403)
-    .json({ message: "You have to be Admin or Staff to see this page!" });
-};
-
-export default isStaffOrAdmin;
diff --git a/src/middlewares/files/updateProfilePicture.ts b/src/middlewares/files/updateProfilePicture.ts
index 1e432d01..8a7b86d8 100644
--- a/src/middlewares/files/updateProfilePicture.ts
+++ b/src/middlewares/files/updateProfilePicture.ts
@@ -13,8 +13,8 @@ const updateProfilePicture = () => async (
   next: NextFunction
 ) => {
   try {
-    if (res.data.profile!.picture) {
-      const oldFile = await File.findByIdAndRemove(res.data.profile!.picture)
+    if (res.data.profile!.newPicture) {
+      const oldFile = await File.findByIdAndRemove(res.data.profile!.newPicture)
         .lean()
         .exec();
       if (oldFile) fs.unlinkSync(oldFile!.path);
diff --git a/src/middlewares/news/getNewsList.ts b/src/middlewares/news/getNewsList.ts
index 7db23693..58ff01ae 100644
--- a/src/middlewares/news/getNewsList.ts
+++ b/src/middlewares/news/getNewsList.ts
@@ -4,7 +4,6 @@ import News from "../../models/NewsSchema";
 
 /**
  * Get all news and set res.data.news
- *
  */
 const getNewsList = () => async (
   req: Request,
diff --git a/src/middlewares/user/acceptPicture.ts b/src/middlewares/user/acceptPicture.ts
index 507accb8..0ff6b3f7 100644
--- a/src/middlewares/user/acceptPicture.ts
+++ b/src/middlewares/user/acceptPicture.ts
@@ -10,17 +10,18 @@ const acceptPicture = () => async (
   next: NextFunction
 ) => {
   try {
-    if (!res.data.profile?.picture)
+    if (!res.data.profile?.newPicture)
       return res.status(400).json({
         message: "The User doesn't have any unaccepted Profile picture!",
       });
 
+    // TODO Notification
     await Profile.updateOne(
       { _id: req.params.userId },
       {
         $set: {
           picture: undefined,
-          acceptedPicture: res.data.profile?.picture,
+          acceptedPicture: res.data.profile?.newPicture,
         },
       },
       { upsert: true, runValidators: true }
diff --git a/src/middlewares/user/deleteUser.ts b/src/middlewares/user/deleteUser.ts
index c8525029..ad2c4da0 100644
--- a/src/middlewares/user/deleteUser.ts
+++ b/src/middlewares/user/deleteUser.ts
@@ -4,6 +4,7 @@ import Profile from "../../models/ProfileSchema";
 
 /**
  * userId -> deletes the User
+ * TODO remove from referenced objects
  */
 const deleteUser = () => async (
   req: Request,
diff --git a/src/middlewares/user/getUser.ts b/src/middlewares/user/getUser.ts
index 446406a9..de494e0f 100644
--- a/src/middlewares/user/getUser.ts
+++ b/src/middlewares/user/getUser.ts
@@ -5,13 +5,16 @@ import Profile from "../../models/ProfileSchema";
 /**
  * req.params.userId -> found Profile to res.data.profile
  */
-const getUser = () => async (
+const getUser = (selectQuery: string) => async (
   req: Request,
   res: Response,
   next: NextFunction
 ) => {
   try {
-    res.data.profile = await Profile.findById(req.params.userId).lean().exec();
+    res.data.profile = await Profile.findById(req.params.userId)
+      .select(selectQuery)
+      .lean()
+      .exec();
 
     if (!res.data.profile)
       return res.status(404).json({ message: "User not found" });
diff --git a/src/middlewares/user/getUserWarningsList.ts b/src/middlewares/user/getUserWarningsList.ts
index 832cefb1..7985cab6 100644
--- a/src/middlewares/user/getUserWarningsList.ts
+++ b/src/middlewares/user/getUserWarningsList.ts
@@ -1,7 +1,5 @@
 import { NextFunction, Request, Response } from "express";
 
-import Warning from "../../models/WarningSchema";
-
 /**
  * res.data.profile -> found Warnings to res.data.warnings
  */
@@ -11,9 +9,9 @@ const getUserWarningsList = () => async (
   next: NextFunction
 ) => {
   try {
-    res.data.warnings = await Warning.find({
-      _id: { $in: res.data.profile?.warnings },
-    });
+    // res.data.warnings = await Warning.find({
+    //   _id: { $in: res.data.profile?.warnings },
+    // });
 
     next();
   } catch (err) {
diff --git a/src/middlewares/user/getUsersList.ts b/src/middlewares/user/getUsersList.ts
index a188f295..9e8e1504 100644
--- a/src/middlewares/user/getUsersList.ts
+++ b/src/middlewares/user/getUsersList.ts
@@ -1,17 +1,20 @@
 import { NextFunction, Request, Response } from "express";
+import Profile, { IProfile } from "../../models/ProfileSchema";
 
-import Profile from "../../models/ProfileSchema";
+import { FilterQuery } from "mongoose";
 
 /**
  * -> All Profiles to res.data.profiles
  */
-const getUsersList = () => async (
-  req: Request,
-  res: Response,
-  next: NextFunction
-) => {
+const getUsersList = (
+  selectQuery: string,
+  FilterQuery: FilterQuery<IProfile> = {}
+) => async (req: Request, res: Response, next: NextFunction) => {
   try {
-    res.data.profiles = await Profile.find().lean().exec();
+    res.data.profiles = await Profile.find(FilterQuery)
+      .select(selectQuery)
+      .lean()
+      .exec();
     next();
   } catch (err) {
     next(err);
diff --git a/src/middlewares/user/rejectPicture.ts b/src/middlewares/user/rejectPicture.ts
new file mode 100644
index 00000000..6f266102
--- /dev/null
+++ b/src/middlewares/user/rejectPicture.ts
@@ -0,0 +1,32 @@
+import { NextFunction, Request, Response } from "express";
+import Profile, { IProfile } from "../../models/ProfileSchema";
+
+/**
+ * userId -> updates the user
+ */
+const rejectPicture = () => async (
+  req: Request,
+  res: Response,
+  next: NextFunction
+) => {
+  try {
+    // TODO Notification
+    await Profile.updateOne(
+      { _id: req.params.userId },
+      {
+        $set: {
+          picture: undefined,
+        },
+      },
+      { upsert: true, runValidators: true }
+    )
+      .lean()
+      .exec();
+
+    next();
+  } catch (err) {
+    next(err);
+  }
+};
+
+export default rejectPicture;
diff --git a/src/middlewares/user/setOwnUserId.ts b/src/middlewares/user/setOwnUserId.ts
index 0cc81300..65c91c46 100644
--- a/src/middlewares/user/setOwnUserId.ts
+++ b/src/middlewares/user/setOwnUserId.ts
@@ -1,9 +1,6 @@
 import { NextFunction, Request, Response } from "express";
 import Profile, { IProfile } from "../../models/ProfileSchema";
 
-import { IWarning } from "../../models/WarningSchema";
-import Warning from "../../models/WarningSchema";
-
 /**
  * set req.params.userId to session.user.id
  */
diff --git a/src/middlewares/user/updateUser.ts b/src/middlewares/user/updateUser.ts
index cca499da..0e748d84 100644
--- a/src/middlewares/user/updateUser.ts
+++ b/src/middlewares/user/updateUser.ts
@@ -1,23 +1,17 @@
 import { NextFunction, Request, Response } from "express";
 import Profile, { IProfile } from "../../models/ProfileSchema";
 
-// Valid fields to update
-const validFields: Partial<keyof IProfile>[] = [
-  "studentCardNumber",
-  "roomNumber",
-];
-
 /**
  * userId -> updates the user
  */
-const updateUser = () => async (
+const updateUser = (fields: Partial<keyof IProfile>[]) => async (
   req: Request,
   res: Response,
   next: NextFunction
 ) => {
   try {
     let newFields: Partial<IProfile> = {};
-    validFields.forEach((field) => {
+    fields.forEach((field) => {
       const value = req.body[field];
       if (value) newFields[field] = value;
     });
diff --git a/src/middlewares/utils/createdResponse.ts b/src/middlewares/utils/createdResponse.ts
index 694b063e..251e80fb 100644
--- a/src/middlewares/utils/createdResponse.ts
+++ b/src/middlewares/utils/createdResponse.ts
@@ -4,7 +4,7 @@ import { Request, Response } from "express";
  * New Object created and returns its Id from res.data.newObjectId
  */
 const createdResponse = () => (req: Request, res: Response) => {
-  res.status(201).json({ id: res.data.newObjectId });
+  res.status(201).json({ _id: res.data.newObjectId });
 };
 
 export default createdResponse;
diff --git a/src/middlewares/utils/getFieldValue.ts b/src/middlewares/utils/getFieldValue.ts
index d3ffad58..f6f48697 100644
--- a/src/middlewares/utils/getFieldValue.ts
+++ b/src/middlewares/utils/getFieldValue.ts
@@ -8,7 +8,7 @@ import Term from "../../models/TermSchema";
  */
 const getFieldValue = (
   objectName: "profile" | "term",
-  fieldName: "picture" | "acceptedPicture" | "backgroundFile"
+  fieldName: "newPicture" | "acceptedPicture" | "backgroundFile"
 ) => async (req: Request, res: Response, next: NextFunction) => {
   try {
     const object: Record<string, any> = res.data[objectName]!;
diff --git a/src/middlewares/warning/addWarning.ts b/src/middlewares/warning/addWarning.ts
index ce60fe53..c0702e45 100644
--- a/src/middlewares/warning/addWarning.ts
+++ b/src/middlewares/warning/addWarning.ts
@@ -2,7 +2,6 @@ import { NextFunction, Request, Response } from "express";
 
 import { ErrorHandler } from "../utils/ErrorHandler";
 import Profile from "../../models/ProfileSchema";
-import Warning from "../../models/WarningSchema";
 import { validateFields } from "../utils/validateFields";
 import warningsRoute from "../../routes/warnings";
 
@@ -19,32 +18,32 @@ const addWarning = () => async (
       .exec();
     if (!warningReceiver) throw new ErrorHandler(404, "User not found!");
 
-    const warning = new Warning();
+    // const warning = new Warning();
 
-    // Validate and set fields from request body
-    validateFields({ fields, reqBody: req.body });
-    fields.forEach((field) => {
-      const value = req.body[field.name];
-      if (value) warning.set(field.name, req.body[field.name]);
-    });
+    // // Validate and set fields from request body
+    // validateFields({ fields, reqBody: req.body });
+    // fields.forEach((field) => {
+    //   const value = req.body[field.name];
+    //   if (value) warning.set(field.name, req.body[field.name]);
+    // });
 
-    warning.receiver = warningReceiver._id!;
-    warning.date = new Date();
-    warning.givenBy = {
-      id: req.session.user!.id!,
-      name: req.session.user!.name!,
-    };
+    // warning.receiver = warningReceiver._id!;
+    // warning.date = new Date();
+    // warning.givenBy = {
+    //   id: req.session.user!.id!,
+    //   name: req.session.user!.name!,
+    // };
 
-    await warning.save();
+    // await warning.save();
 
-    await Profile.updateOne(
-      { _id: warningReceiver._id },
-      { $push: { warnings: warning._id } }
-    )
-      .lean()
-      .exec();
+    // await Profile.updateOne(
+    //   { _id: warningReceiver._id },
+    //   { $push: { warnings: warning._id } }
+    // )
+    //   .lean()
+    //   .exec();
 
-    res.data.newObjectId = warning._id;
+    // res.data.newObjectId = warning._id;
     next();
   } catch (err) {
     next(err);
diff --git a/src/middlewares/warning/deleteWarning.ts b/src/middlewares/warning/deleteWarning.ts
index 376ccefc..20f1072b 100644
--- a/src/middlewares/warning/deleteWarning.ts
+++ b/src/middlewares/warning/deleteWarning.ts
@@ -1,7 +1,6 @@
 import { NextFunction, Request, Response } from "express";
 
 import Profile from "../../models/ProfileSchema";
-import Warning from "../../models/WarningSchema";
 
 const deleteWarning = () => async (
   req: Request,
@@ -9,12 +8,12 @@ const deleteWarning = () => async (
   next: NextFunction
 ) => {
   try {
-    const warning = await Warning.findByIdAndRemove(req.params.warningId);
+    // const warning = await Warning.findByIdAndRemove(req.params.warningId);
 
-    await Profile.updateOne(
-      { _id: warning?.receiver },
-      { $pull: { warnings: warning?._id } }
-    );
+    // await Profile.updateOne(
+    //   { _id: warning?.receiver },
+    //   { $pull: { warnings: warning?._id } }
+    // );
 
     next();
   } catch (err) {
diff --git a/src/middlewares/warning/getWarning.ts b/src/middlewares/warning/getWarning.ts
index df0edcb8..8b401cbb 100644
--- a/src/middlewares/warning/getWarning.ts
+++ b/src/middlewares/warning/getWarning.ts
@@ -1,7 +1,5 @@
 import { NextFunction, Request, Response } from "express";
 
-import Warning from "../../models/WarningSchema";
-
 /**
  * req.params.warningId -> Get Warning and set res.data.warning
  */
@@ -11,9 +9,9 @@ const getWarning = () => async (
   next: NextFunction
 ) => {
   try {
-    res.data.warning = await Warning.findById(req.params.warningId)
-      .lean()
-      .exec();
+    // res.data.warning = await Warning.findById(req.params.warningId)
+    //   .lean()
+    //   .exec();
     next();
   } catch (err) {
     next(err);
diff --git a/src/middlewares/warning/getWarningsList.ts b/src/middlewares/warning/getWarningsList.ts
index 3558a47d..47b52219 100644
--- a/src/middlewares/warning/getWarningsList.ts
+++ b/src/middlewares/warning/getWarningsList.ts
@@ -1,7 +1,5 @@
 import { NextFunction, Request, Response } from "express";
 
-import Warning from "../../models/WarningSchema";
-
 /**
  * -> Get Warnings and set res.data.warnings
  */
@@ -11,7 +9,7 @@ const getWarningsList = () => async (
   next: NextFunction
 ) => {
   try {
-    res.data.warnings = await Warning.find().lean().exec();
+    // res.data.warnings = await Warning.find().lean().exec();
     next();
   } catch (err) {
     next(err);
diff --git a/src/middlewares/warning/updateWarning.ts b/src/middlewares/warning/updateWarning.ts
index cd39652d..256cfb4a 100644
--- a/src/middlewares/warning/updateWarning.ts
+++ b/src/middlewares/warning/updateWarning.ts
@@ -1,8 +1,7 @@
 import { NextFunction, Request, Response } from "express";
-import Warning, { IWarning } from "../../models/WarningSchema";
 
 // Valid fields to update
-const validFields: Partial<keyof IWarning>[] = ["text"];
+// const validFields: Partial<keyof IWarning>[] = ["text"];
 
 /**
  * warningId -> Updates the warning
@@ -13,19 +12,19 @@ const updateWarning = () => async (
   next: NextFunction
 ) => {
   try {
-    let newFields: Partial<IWarning> = {};
-    validFields.forEach((field) => {
-      const value = req.body[field];
-      if (value) newFields[field] = value;
-    });
+    // let newFields: Partial<IWarning> = {};
+    // validFields.forEach((field) => {
+    //   const value = req.body[field];
+    //   if (value) newFields[field] = value;
+    // });
 
-    await Warning.updateOne(
-      { _id: req.params.warningId },
-      { $set: newFields },
-      { upsert: true, runValidators: true }
-    )
-      .lean()
-      .exec();
+    // await Warning.updateOne(
+    //   { _id: req.params.warningId },
+    //   { $set: newFields },
+    //   { upsert: true, runValidators: true }
+    // )
+    //   .lean()
+    //   .exec();
 
     next();
   } catch (err) {
diff --git a/src/models/CounterSchema.ts b/src/models/CounterSchema.ts
index cadcb729..40a88964 100644
--- a/src/models/CounterSchema.ts
+++ b/src/models/CounterSchema.ts
@@ -10,18 +10,4 @@ const CounterSchema = new Schema({
   seq: { type: Number, default: 0 },
 });
 
-// CardSchema.pre("save", function (this: ICard, next) {
-//   var doc = this;
-//   CounterSchema.findByIdAndUpdate(
-//     { _id: "cardId" },
-//     { $inc: { seq: 1 } },
-//     { upsert: true, new: true },
-//     function (error, counter: ICounter | null) {
-//       if (error) return next(error);
-//       doc.cardId = counter!.seq;
-//       next();
-//     }
-//   );
-// });
-
 export default model<ICounter>("Counter", CounterSchema);
diff --git a/src/models/NotificationSchema.ts b/src/models/NotificationSchema.ts
deleted file mode 100644
index 3914dc73..00000000
--- a/src/models/NotificationSchema.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import { Document, Schema, model } from "mongoose";
-
-export interface INotification extends Document {
-  text: string;
-  redirect?: string;
-}
-
-const NotificationSchema = new Schema({
-  text: { type: String, required: true },
-  redirect: { type: String, required: false },
-});
-
-export default model<INotification>("Notification", NotificationSchema);
diff --git a/src/models/ProfileSchema.ts b/src/models/ProfileSchema.ts
index c0546b79..0a8d37ab 100644
--- a/src/models/ProfileSchema.ts
+++ b/src/models/ProfileSchema.ts
@@ -1,32 +1,46 @@
 import { Document, Schema, model } from "mongoose";
-import { IWarning, WarningSchema } from "./WarningSchema";
-
-import { Admin } from "mongodb";
 
 export enum Role {
   Admin = "ADMIN",
-  Staff = "STAFF",
   User = "USER",
 }
 
+export interface INotification {
+  text: string;
+  redirect?: string;
+  isSeen: boolean;
+}
+
+export interface IWarning {
+  receiver: string;
+  text: string;
+  date: Date;
+  givenBy: {
+    id: string;
+    name: string;
+  };
+}
+
 export interface IProfile extends Document {
   externalId: string;
   studentCardNumber?: string;
   roomNumber?: Number;
-  picture?: string;
+  newPicture?: string;
   acceptedPicture?: string;
   role: Role;
   email: string;
   name: string;
-  warnings: string[] | [];
-  notifications: string[] | [];
+  isStaffMember?: boolean;
+  staffMemberText?: string;
+  warnings: IWarning[];
+  notifications: INotification[];
 }
 
 const ProfileSchema = new Schema({
   externalId: { type: String, required: true, unique: true, dropDups: true },
   studentCardNumber: { type: String, required: false },
   roomNumber: { type: Number, required: false },
-  picture: { type: Schema.Types.ObjectId, ref: "File", required: false },
+  newPicture: { type: Schema.Types.ObjectId, ref: "File", required: false },
   acceptedPicture: {
     type: Schema.Types.ObjectId,
     ref: "File",
@@ -40,9 +54,21 @@ const ProfileSchema = new Schema({
   },
   email: { type: String, required: true },
   name: { type: String, required: true },
-  warnings: [{ type: Schema.Types.ObjectId, ref: "Warning", required: false }],
+  isStaffMember: { type: Boolean, required: false, default: false },
+  staffMemberText: { type: String, required: false },
   notifications: [
-    { type: Schema.Types.ObjectId, ref: "Notification", required: false },
+    {
+      text: { type: String, required: true },
+      redirect: { type: String, required: false },
+      isSeen: { type: Boolean, required: true, default: false },
+    },
+  ],
+  warnings: [
+    {
+      text: { type: String, required: true },
+      date: { type: Date, required: true },
+      givenBy: { type: Schema.Types.ObjectId, ref: "Profile", required: true },
+    },
   ],
 });
 
diff --git a/src/models/TermSchema.ts b/src/models/TermSchema.ts
index 368f580c..2ee918a4 100644
--- a/src/models/TermSchema.ts
+++ b/src/models/TermSchema.ts
@@ -28,6 +28,7 @@ const TermSchema = new Schema({
   createDate: { type: Date, required: true },
   startDate: { type: Date, required: true },
   endDate: { type: Date, required: true },
+  deadline: { type: Date, required: true },
   members: [
     {
       user: { type: Schema.Types.ObjectId, ref: "Profile", required: true },
diff --git a/src/models/WarningSchema.ts b/src/models/WarningSchema.ts
deleted file mode 100644
index d58b1266..00000000
--- a/src/models/WarningSchema.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import { Document, Schema, model } from "mongoose";
-
-export interface IWarning extends Document {
-  receiver: string;
-  text: string;
-  date: Date;
-  givenBy: {
-    id: string;
-    name: string;
-  };
-}
-
-export const WarningSchema = new Schema({
-  receiver: { type: Schema.Types.ObjectId, ref: "Profile", required: true },
-  text: { type: String, required: true },
-  date: { type: Date, required: true },
-  givenBy: {
-    required: true,
-    type: {
-      id: { type: Schema.Types.ObjectId, ref: "Profile", required: true },
-      name: { String, required: true },
-    },
-  },
-});
-
-export default model<IWarning>("Warning", WarningSchema);
diff --git a/src/routes/files.ts b/src/routes/files.ts
index 827e0168..1956ccd5 100644
--- a/src/routes/files.ts
+++ b/src/routes/files.ts
@@ -11,9 +11,9 @@ import getFieldValue from "../middlewares/utils/getFieldValue";
 import getTerm from "../middlewares/term/getTerm";
 import getUser from "../middlewares/user/getUser";
 import { imageFilter } from "../middlewares/files/imageFilter";
+import isAdmin from "../middlewares/auth/isAdmin";
 import isLoggedIn from "../middlewares/auth/isLoggedIn";
 import isRegistered from "../middlewares/auth/isRegistered";
-import isStaffOrAdmin from "../middlewares/auth/isStaffOrAdmin";
 import multer from "multer";
 import noContentResponse from "../middlewares/utils/noContentResponse";
 import sendFile from "../middlewares/files/sendFile";
@@ -31,22 +31,36 @@ const CardImageUpload = multer({
   fileFilter: imageFilter,
 });
 
+// Get Active Member Picture (userId)
+// Get User Accepted Picture (id)
+// Get Card SVG (userId, termId)
+// Get UserListCardsPDF (userId[], termId)
+// UpdateTermCardImage (termId)
+// Get Card Image (termId)
+// GetOwnPicture
+// GetOwnAcceptedPicture
+// GetUserPicture (userId)
+// GetUserAcceptedPicture (userId)
+// UploadOwnPicture
+// UploadUserPicture (userId)
+// OwnTermCardPreview(termId)
+
 const filesRoute = (prefix: string, app: Application): void => {
   // Get a users profile picture
   app.get(
     `${prefix}/user/:userId/picture`,
     isRegistered(),
-    isStaffOrAdmin(),
-    getUser(),
-    getFieldValue("profile", "picture"),
+    isAdmin(),
+    getUser(""),
+    getFieldValue("profile", "newPicture"),
     sendFile()
   );
   // Get a users accepted picture
   app.get(
     `${prefix}/user/:userId/picture/accepted`,
     isRegistered(),
-    isStaffOrAdmin(),
-    getUser(),
+    isAdmin(),
+    getUser(""),
     getFieldValue("profile", "acceptedPicture"),
     sendFile()
   );
@@ -55,8 +69,8 @@ const filesRoute = (prefix: string, app: Application): void => {
     `${prefix}/me/picture`,
     isRegistered(),
     setOwnUserId(),
-    getUser(),
-    getFieldValue("profile", "picture"),
+    getUser(""),
+    getFieldValue("profile", "newPicture"),
     sendFile()
   );
   // Get own accepted picture
@@ -64,7 +78,7 @@ const filesRoute = (prefix: string, app: Application): void => {
     `${prefix}/me/picture/accepted`,
     isRegistered(),
     setOwnUserId(),
-    getUser(),
+    getUser(""),
     getFieldValue("profile", "acceptedPicture"),
     sendFile()
   );
@@ -76,8 +90,8 @@ const filesRoute = (prefix: string, app: Application): void => {
   app.post(
     `${prefix}/user/:userId/picture`,
     isRegistered(),
-    isStaffOrAdmin(),
-    getUser(),
+    isAdmin(),
+    getUser(""),
     profilePictureUpload.single("profile_picture"),
     createFile(),
     updateProfilePicture(),
@@ -88,7 +102,7 @@ const filesRoute = (prefix: string, app: Application): void => {
     `${prefix}/me/picture`,
     isRegistered(),
     setOwnUserId(),
-    getUser(),
+    getUser(""),
     profilePictureUpload.single("profile_picture"),
     createFile(),
     updateProfilePicture(),
@@ -106,7 +120,7 @@ const filesRoute = (prefix: string, app: Application): void => {
   app.post(
     `${prefix}/card/bg/term/:termId`,
     isRegistered(),
-    isStaffOrAdmin(),
+    isAdmin(),
     getTerm(),
     CardImageUpload.single("card_image"),
     createFile(),
diff --git a/src/routes/news.ts b/src/routes/news.ts
index df5693a1..b601e175 100644
--- a/src/routes/news.ts
+++ b/src/routes/news.ts
@@ -6,13 +6,19 @@ import deleteNews from "../middlewares/news/deleteNews";
 import example from "../middlewares/example";
 import getNewsList from "../middlewares/news/getNewsList";
 import getOneNews from "../middlewares/news/getOneNews";
+import isAdmin from "../middlewares/auth/isAdmin";
 import isRegistered from "../middlewares/auth/isRegistered";
-import isStaffOrAdmin from "../middlewares/auth/isStaffOrAdmin";
 import noContentResponse from "../middlewares/utils/noContentResponse";
 import responseNews from "../middlewares/news/responseNews";
 import responseOneNews from "../middlewares/news/responseOneNews";
 import updateNews from "../middlewares/news/updateNews";
 
+// GetNewsList [{ID, title, text, date}]
+// GetOneNews(Id) [{ID, title, text, date, modifyDate, publishedBy, editedBy}]
+// UpdateOneNews(Id) { title, text}
+// DeleteOneNews(id)
+// CreateOneNews {title, text}
+
 const newsRoute = (prefix: string, app: Application): void => {
   // Get all news
   app.get(`${prefix}/`, getNewsList(), responseNews());
@@ -20,7 +26,7 @@ const newsRoute = (prefix: string, app: Application): void => {
   app.post(
     `${prefix}/`,
     isRegistered(),
-    isStaffOrAdmin(),
+    isAdmin(),
     addNews(),
     createdResponse()
   );
@@ -30,7 +36,7 @@ const newsRoute = (prefix: string, app: Application): void => {
   app.put(
     `${prefix}/one/:newsId`,
     isRegistered(),
-    isStaffOrAdmin(),
+    isAdmin(),
     getOneNews(),
     updateNews(),
     noContentResponse()
@@ -39,7 +45,7 @@ const newsRoute = (prefix: string, app: Application): void => {
   app.delete(
     `${prefix}/one/:newsId`,
     isRegistered(),
-    isStaffOrAdmin(),
+    isAdmin(),
     getOneNews(),
     deleteNews(),
     noContentResponse()
diff --git a/src/routes/notifications.ts b/src/routes/notifications.ts
index e2db085a..98f29e0b 100644
--- a/src/routes/notifications.ts
+++ b/src/routes/notifications.ts
@@ -1,6 +1,13 @@
 import { Application } from "express";
 import example from "../middlewares/example";
 
+// getOwnNotificationCount {number}
+// getOwnNotifications {id, text, redirectUrl}
+// deleteOwnNotification (notificationId)
+// addUserNotification (userId) { text, redirectUrl}
+// addTermMembersNotification (termId) { text, redirectUrl}
+// addAllusersNotification { text, redirectUrl}
+
 const notificationsRoute = (prefix: string, app: Application): void => {
   // Get all Notifications
   app.get(`${prefix}/`, example());
diff --git a/src/routes/terms.ts b/src/routes/terms.ts
index 96553511..58d633fd 100644
--- a/src/routes/terms.ts
+++ b/src/routes/terms.ts
@@ -13,9 +13,9 @@ import getMembers from "../middlewares/term/getMembers";
 import getTerm from "../middlewares/term/getTerm";
 import getTermsList from "../middlewares/term/getTermsList";
 import getUser from "../middlewares/user/getUser";
+import isAdmin from "../middlewares/auth/isAdmin";
 import isNotMember from "../middlewares/term/isNotMember";
 import isRegistered from "../middlewares/auth/isRegistered";
-import isStaffOrAdmin from "../middlewares/auth/isStaffOrAdmin";
 import noContentResponse from "../middlewares/utils/noContentResponse";
 import responseMember from "../middlewares/term/responseMember";
 import responseMemberState from "../middlewares/term/responseMemberState";
@@ -26,6 +26,15 @@ import setOwnUserId from "../middlewares/user/setOwnUserId";
 import updateTerm from "../middlewares/term/updateTerm";
 import updateTermMember from "../middlewares/term/updateTermMember";
 
+// Get Terms List {id, name, startDate, endDate, deadline, ownState}
+// Apply Self to Term (ID)
+// Add Term {name*, startDate*, endDate*, deadline*, createDate}
+// Get Term(termID) {ID, name, startDate, endDate, deadline, memberState, cardState, cardReceivedDate}
+// Get Term Members(termID) [{ID, name, memberState, cardState, cardReceivedDate, warningNumber }]
+// UpdateMember(termId, userId) { memberState, cardState, cardReceivedDate }
+// UpdateMembersList(termId, userId[]) { memberState, cardState, cardReceivedDate}
+// UpdateTerm(termId) {name, startDate, endDate, deadline, createDate}
+
 const termsRoute = (prefix: string, app: Application): void => {
   // Get all Terms without members
   app.get(
@@ -38,7 +47,7 @@ const termsRoute = (prefix: string, app: Application): void => {
   app.get(
     `${prefix}/wmembers`,
     isRegistered(),
-    isStaffOrAdmin(),
+    isAdmin(),
     getTermsList(),
     responseTermsList(true)
   );
@@ -46,7 +55,7 @@ const termsRoute = (prefix: string, app: Application): void => {
   app.post(
     `${prefix}/`,
     isRegistered(),
-    isStaffOrAdmin(),
+    isAdmin(),
     addTerm(),
     createdResponse()
   );
@@ -61,7 +70,7 @@ const termsRoute = (prefix: string, app: Application): void => {
   app.get(
     `${prefix}/term/:termId/wmembers`,
     isRegistered(),
-    isStaffOrAdmin(),
+    isAdmin(),
     getTerm(),
     responseTerm(true)
   );
@@ -69,7 +78,7 @@ const termsRoute = (prefix: string, app: Application): void => {
   app.delete(
     `${prefix}/term/:termId`,
     isRegistered(),
-    isStaffOrAdmin(),
+    isAdmin(),
     deleteTerm(),
     noContentResponse()
   );
@@ -77,7 +86,7 @@ const termsRoute = (prefix: string, app: Application): void => {
   app.get(
     `${prefix}/term/:termId/members`,
     isRegistered(),
-    isStaffOrAdmin(),
+    isAdmin(),
     getTerm(),
     getMembers(),
     responseMembersList()
@@ -86,7 +95,7 @@ const termsRoute = (prefix: string, app: Application): void => {
   app.get(
     `${prefix}/term/:termId/members/:stateFilter`,
     isRegistered(),
-    isStaffOrAdmin(),
+    isAdmin(),
     getTerm(),
     filterMembersByState(),
     responseMembersList()
@@ -105,7 +114,7 @@ const termsRoute = (prefix: string, app: Application): void => {
   app.get(
     `${prefix}/term/:termId/state/user/:userId`,
     isRegistered(),
-    isStaffOrAdmin(),
+    isAdmin(),
     getTerm(),
     getMember(),
     getMemberState(),
@@ -130,7 +139,7 @@ const termsRoute = (prefix: string, app: Application): void => {
     `${prefix}/apply/me/latest`,
     isRegistered(),
     setOwnUserId(),
-    getUser(),
+    getUser(""),
     getLatestTerm(),
     isNotMember(),
     addMember(),
@@ -140,8 +149,8 @@ const termsRoute = (prefix: string, app: Application): void => {
   app.post(
     `${prefix}/apply/user/:userId/latest`,
     isRegistered(),
-    isStaffOrAdmin(),
-    getUser(),
+    isAdmin(),
+    getUser(""),
     getLatestTerm(),
     isNotMember(),
     addMember(),
@@ -151,8 +160,8 @@ const termsRoute = (prefix: string, app: Application): void => {
   app.post(
     `${prefix}/apply/user/:userId/term/:termId`,
     isRegistered(),
-    isStaffOrAdmin(),
-    getUser(),
+    isAdmin(),
+    getUser(""),
     getTerm(),
     isNotMember(),
     addMember(),
@@ -162,7 +171,7 @@ const termsRoute = (prefix: string, app: Application): void => {
   app.put(
     `${prefix}/term/:termId`,
     isRegistered(),
-    isStaffOrAdmin(),
+    isAdmin(),
     getTerm(),
     updateTerm(),
     noContentResponse()
@@ -170,9 +179,9 @@ const termsRoute = (prefix: string, app: Application): void => {
   app.put(
     `${prefix}/term/:termId/user/:userId`,
     isRegistered(),
-    isStaffOrAdmin(),
+    isAdmin(),
     getTerm(),
-    getUser(),
+    getUser(""),
     updateTermMember(),
     noContentResponse()
   );
diff --git a/src/routes/user.ts b/src/routes/user.ts
index 2090a1f4..ede4def5 100644
--- a/src/routes/user.ts
+++ b/src/routes/user.ts
@@ -8,28 +8,32 @@ import getFieldValue from "../middlewares/utils/getFieldValue";
 import getUser from "../middlewares/user/getUser";
 import getUserWarningsList from "../middlewares/user/getUserWarningsList";
 import getUsersList from "../middlewares/user/getUsersList";
+import isAdmin from "../middlewares/auth/isAdmin";
 import isLoggedIn from "../middlewares/auth/isLoggedIn";
 import isNotRegistered from "../middlewares/auth/isNotRegistered";
 import isRegistered from "../middlewares/auth/isRegistered";
-import isStaffOrAdmin from "../middlewares/auth/isStaffOrAdmin";
 import noContentResponse from "../middlewares/utils/noContentResponse";
 import registerOwnUser from "../middlewares/user/registerOwnUser";
+import rejectPicture from "../middlewares/user/rejectPicture";
 import responseUser from "../middlewares/user/responseUser";
 import responseUsersList from "../middlewares/user/responseUsersList";
 import responseWarningsList from "../middlewares/warning/responseWarningsList";
 import setOwnUserId from "../middlewares/user/setOwnUserId";
 import updateUser from "../middlewares/user/updateUser";
 
+// OwnTermMemberships [{id, name, membership}]
+// UserTermMemberships(userId) [{id, name, membership}]
+// OwnWarnings [{id, text, date}]
+// UserWarnings(userId) [{id, text, date}]
+// deleteUserWarning(userId, warningId)
+// addUserWarning(userId) {text}
+// updateuserWarning(userId, warningId) {text}
+
 const usersRoute = (prefix: string, app: Application): void => {
-  // Get all users
-  app.get(
-    `${prefix}/`,
-    isRegistered(),
-    isStaffOrAdmin(),
-    getUsersList(),
-    responseUsersList()
-  );
-  // Register own user
+  /**
+   * Register Own User
+   * Role: NORMAL
+   */
   app.post(
     `${prefix}/me`,
     isLoggedIn(),
@@ -37,75 +41,154 @@ const usersRoute = (prefix: string, app: Application): void => {
     registerOwnUser(),
     createdResponse()
   );
-  // Get own user
+
+  /**
+   * Get list of users
+   * Role: ADMIN
+   */
   app.get(
-    `${prefix}/me`,
+    `${prefix}/`,
     isRegistered(),
-    setOwnUserId(),
-    getUser(),
-    responseUser()
+    isAdmin(),
+    getUsersList("_id name newPicture"),
+    responseUsersList()
   );
-  // Get a user
+
+  /**
+   * Get One User
+   * Role: ADMIN
+   */
   app.get(
     `${prefix}/user/:userId`,
     isRegistered(),
-    isStaffOrAdmin(),
-    getUser(),
+    isAdmin(),
+    getUser(
+      "_id name role email externalId studentCardNumber roomNumber isStaffMember staffMemberText"
+    ),
     responseUser()
   );
-  // Get own warnings
+
+  /**
+   * Get Own User
+   * Role: NORMAL
+   */
   app.get(
-    `${prefix}/me/warnings`,
+    `${prefix}/me`,
     isRegistered(),
     setOwnUserId(),
-    getUser(),
-    getUserWarningsList(),
-    responseWarningsList()
+    getUser("id name role email studentCardNumber roomNumber"),
+    responseUser()
   );
-  // Get a user's warnings
+
+  /**
+   * Get Own User Short
+   * Role: NORMAL
+   */
   app.get(
-    `${prefix}/user/:userId/warnings`,
+    `${prefix}/me/short`,
     isRegistered(),
-    isStaffOrAdmin(),
-    getUser(),
-    getUserWarningsList(),
-    responseWarningsList()
+    setOwnUserId(),
+    getUser("id name role"),
+    responseUser()
   );
-  // Update own user
+
+  /**
+   * Update Own User
+   * Role: NORMAL
+   */
   app.put(
     `${prefix}/me`,
     isRegistered(),
     setOwnUserId(),
-    updateUser(),
+    updateUser(["studentCardNumber", "roomNumber"]),
     noContentResponse()
   );
-  // Update a user
+
+  /**
+   * Update User
+   * Role: ADMIN
+   */
   app.put(
     `${prefix}/user/:userId`,
     isRegistered(),
-    isStaffOrAdmin(),
-    updateUser(),
+    isAdmin(),
+    updateUser([
+      "studentCardNumber",
+      "roomNumber",
+      "isStaffMember",
+      "staffMemberText",
+    ]),
     noContentResponse()
   );
-  // Delete a user
-  app.delete(
-    `${prefix}/user/:userId`,
+
+  /**
+   * Get list of staff Members
+   * Role: NORMAL
+   */
+  app.get(
+    `${prefix}/staff`,
     isRegistered(),
-    isStaffOrAdmin(),
-    deleteUser(),
-    noContentResponse()
+    getUsersList("_id name email staffMemberText", { isStaffMember: true }),
+    responseUsersList()
   );
-  // Accept/Reject a users picture TODO
+
+  /**
+   * Accept a users Picture
+   * Role: ADMIN
+   */
   app.post(
     `${prefix}/user/:userId/picture/accept`,
     isRegistered(),
-    isStaffOrAdmin(),
-    getUser(),
+    isAdmin(),
+    getUser("acceptedPicture newPicture"),
     getFieldValue("profile", "acceptedPicture"),
-    deleteFile(),
     acceptPicture(),
+    deleteFile(),
+    noContentResponse()
+  );
+  /**
+   * Reject a users Picture
+   * Role: ADMIN
+   */
+  app.post(
+    `${prefix}/user/:userId/picture/reject`,
+    isRegistered(),
+    isAdmin(),
+    getUser("acceptedPicture newPicture"),
+    getFieldValue("profile", "newPicture"),
+    rejectPicture(),
+    deleteFile(),
     noContentResponse()
   );
+
+  // Get own warnings
+  app.get(
+    `${prefix}/me/warnings`,
+    isRegistered(),
+    setOwnUserId(),
+    getUser(""),
+    getUserWarningsList(),
+    responseWarningsList()
+  );
+  // Get a user's warnings
+  app.get(
+    `${prefix}/user/:userId/warnings`,
+    isRegistered(),
+    isAdmin(),
+    getUser(""),
+    getUserWarningsList(),
+    responseWarningsList()
+  );
+
+  // Delete a user
+  app.delete(
+    `${prefix}/user/:userId`,
+    isRegistered(),
+    isAdmin(),
+    deleteUser(),
+    noContentResponse()
+  );
+
   app.post(`${prefix}/user/:userId/picture/reject`, example());
 };
 
diff --git a/src/routes/warnings.ts b/src/routes/warnings.ts
index 543ee149..ef5dfac0 100644
--- a/src/routes/warnings.ts
+++ b/src/routes/warnings.ts
@@ -5,8 +5,8 @@ import deleteWarning from "../middlewares/warning/deleteWarning";
 import example from "../middlewares/example";
 import getWarning from "../middlewares/warning/getWarning";
 import getWarningsList from "../middlewares/warning/getWarningsList";
+import isAdmin from "../middlewares/auth/isAdmin";
 import isRegistered from "../middlewares/auth/isRegistered";
-import isStaffOrAdmin from "../middlewares/auth/isStaffOrAdmin";
 import noContentResponse from "../middlewares/utils/noContentResponse";
 import responseWarning from "../middlewares/warning/responseWarning";
 import responseWarningsList from "../middlewares/warning/responseWarningsList";
@@ -17,7 +17,7 @@ const warningsRoute = (prefix: string, app: Application): void => {
   app.get(
     `${prefix}/`,
     isRegistered(),
-    isStaffOrAdmin(),
+    isAdmin(),
     getWarningsList(),
     responseWarningsList()
   );
@@ -25,7 +25,7 @@ const warningsRoute = (prefix: string, app: Application): void => {
   app.post(
     `${prefix}/user/:userId`,
     isRegistered(),
-    isStaffOrAdmin(),
+    isAdmin(),
     addWarning(),
     createdResponse()
   );
@@ -33,7 +33,7 @@ const warningsRoute = (prefix: string, app: Application): void => {
   app.get(
     `${prefix}/warning/:warningId`,
     isRegistered(),
-    isStaffOrAdmin(),
+    isAdmin(),
     getWarning(),
     responseWarning()
   );
@@ -41,7 +41,7 @@ const warningsRoute = (prefix: string, app: Application): void => {
   app.put(
     `${prefix}/warning/:warningId`,
     isRegistered(),
-    isStaffOrAdmin(),
+    isAdmin(),
     updateWarning(),
     noContentResponse()
   );
@@ -49,7 +49,7 @@ const warningsRoute = (prefix: string, app: Application): void => {
   app.delete(
     `${prefix}/warning/:warningId`,
     isRegistered(),
-    isStaffOrAdmin(),
+    isAdmin(),
     deleteWarning(),
     noContentResponse()
   );
-- 
GitLab