diff --git a/package-lock.json b/package-lock.json
index ee8a43b8f5571ee129407564515c01a959ee935f..cb959ebd88fee3935a9aa05f9aec5849b9dc0b65 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1253,11 +1253,11 @@
       "dev": true
     },
     "axios": {
-      "version": "0.19.2",
-      "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz",
-      "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==",
+      "version": "0.21.1",
+      "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
+      "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
       "requires": {
-        "follow-redirects": "1.5.10"
+        "follow-redirects": "^1.10.0"
       }
     },
     "babel-jest": {
@@ -2640,27 +2640,9 @@
       }
     },
     "follow-redirects": {
-      "version": "1.5.10",
-      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz",
-      "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==",
-      "requires": {
-        "debug": "=3.1.0"
-      },
-      "dependencies": {
-        "debug": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
-          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
-          "requires": {
-            "ms": "2.0.0"
-          }
-        },
-        "ms": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-          "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
-        }
-      }
+      "version": "1.13.1",
+      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.1.tgz",
+      "integrity": "sha512-SSG5xmZh1mkPGyKzjZP8zLjltIfpW32Y5QpdNJyjcfGxK3qo3NDDkZOZSFiGn1A6SclQxY9GzEwAHQ3dmYRWpg=="
     },
     "for-in": {
       "version": "1.0.2",
diff --git a/package.json b/package.json
index 1461ed00f8f099a61d494df8fc45d8c0fe7e0706..c0674e34a95be2e5f1f03a367249d8aad06741dd 100644
--- a/package.json
+++ b/package.json
@@ -30,7 +30,7 @@
   "dependencies": {
     "@types/express-session": "^1.17.3",
     "@types/simple-oauth2": "^2.5.4",
-    "axios": "^0.19.2",
+    "axios": "^0.21.1",
     "body-parser": "^1.19.0",
     "dotenv": "^8.2.0",
     "express": "^4.17.1",
diff --git a/src/index.ts b/src/index.ts
index 0181a400f7831df7b7bec7e6a19aa454a988d008..6d24c07a1577ed37cb7fe5ffd1a93382e3045799 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,18 +1,12 @@
 import "./utils/env";
 
-import { ErrorHandler, handleError } from "./middlewares/utils/ErrorHandler";
 import express, { Application, NextFunction, Request, Response } from "express";
 
-import authRoute from "./routes/auth";
 import bodyParser from "body-parser";
-import cardRoute from "./routes/card";
 import expressSession from "express-session";
-import fileRoute from "./routes/file";
 import mongoose from "mongoose";
 import morgan from "morgan";
-import newsRoute from "./routes/news";
-import usersRoute from "./routes/user";
-import warningsRoute from "./routes/warning";
+import setRouters from "./routes/setRouters";
 
 mongoose
   .connect("mongodb://localhost:27017/bodysch", {
@@ -60,26 +54,6 @@ app.use((req: Request, res: Response, next: NextFunction) => {
   next();
 });
 
-// Register routes
-
-authRoute(app);
-
-newsRoute(app);
-
-usersRoute(app);
-
-fileRoute(app);
-
-cardRoute(app);
-
-warningsRoute(app);
-
-app.use((err: any, req: Request, res: Response, next: NextFunction) => {
-  if (err instanceof ErrorHandler) return handleError(err, res);
-
-  //Flush out the stack to the console
-  console.error(err.stack);
-  res.status(500).send("Houston, we have a problem!");
-});
+setRouters(app);
 
 app.listen(8000, () => console.log(`Example app listening on port 8000!`));
diff --git a/src/middlewares/auth/complete.ts b/src/middlewares/auth/complete.ts
index d53beb27813200edd4f230e5dff1282c70cc5268..a9e1c91583d663f741a0a45fd37e79cab93cdd70 100644
--- a/src/middlewares/auth/complete.ts
+++ b/src/middlewares/auth/complete.ts
@@ -5,13 +5,6 @@ import Profile from "../../models/ProfileSchema";
 import { authschResponse } from "../../utils/types/authschResponse";
 import axios from "axios";
 
-/**
- * Called after authentication.
- * Uses the provided req.query.code from authsch
- * to get the logged in Users data.
- * If the user is registered, then the Profile object
- * id from the database will be added to session.profile.id
- */
 const complete = () => async (
   req: Request,
   res: Response,
@@ -31,17 +24,33 @@ const complete = () => async (
     );
 
     req.session!.user = {
-      external_id: String(response.data.internal_id),
+      externalId: String(response.data.internal_id),
       email: String(response.data.mail),
       name: `${response.data.sn} ${response.data.givenName}`,
       token,
     };
 
     const profile = await Profile.findOne({
-      external_id: response.data.internal_id,
+      externalId: response.data.internal_id,
     }).lean();
 
-    if (profile) req.session!.user.id = profile._id;
+    if (profile) {
+      req.session!.user.id = profile._id;
+      req.session!.user.role = profile.role;
+
+      // Update user data if something changed in authSch
+      if (
+        profile.name != req.session.user.name ||
+        profile.email != req.session.user.email
+      ) {
+        await Profile.updateOne(
+          { externalId: response.data.internal_id },
+          { name: req.session.user.name, email: req.session.user.email }
+        )
+          .lean()
+          .exec();
+      }
+    }
 
     return res.redirect(process.env.REDIRECT_URI || "/");
   } catch (err) {
diff --git a/src/middlewares/auth/isAdmin.ts b/src/middlewares/auth/isAdmin.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a9f693f024deed3dbcd5f0a5ebf8b1a00cc39b00
--- /dev/null
+++ b/src/middlewares/auth/isAdmin.ts
@@ -0,0 +1,13 @@
+import { NextFunction, Request, Response } from "express";
+
+import { Role } from "../../models/ProfileSchema";
+
+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/isAuthenticated.ts b/src/middlewares/auth/isAuthenticated.ts
deleted file mode 100644
index 3cbf6fe16bebe21da098c4b65cfc72ae8bce7cb9..0000000000000000000000000000000000000000
--- a/src/middlewares/auth/isAuthenticated.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import { NextFunction, Request, Response } from "express";
-
-/**
- * Middleware to check if the user
- * is authenticated and registered
- */
-const isAuthenticated = () => (
-  req: Request,
-  res: Response,
-  next: NextFunction
-) => {
-  if (req.session!.user) {
-    if (req.session!.user.id) next();
-    else {
-      res.status(403);
-      res.json({ message: "You have to register to see this page!" });
-    }
-  } else {
-    res.status(401);
-    res.json({ message: "You have to login to see this page!" });
-  }
-};
-
-export default isAuthenticated;
diff --git a/src/middlewares/auth/isLoggedIn.ts b/src/middlewares/auth/isLoggedIn.ts
index 713f192cea102e7820f39b42514ab62af6017919..5dc2df3b9feae7f62590dc45f60d90b21bdd3ac7 100644
--- a/src/middlewares/auth/isLoggedIn.ts
+++ b/src/middlewares/auth/isLoggedIn.ts
@@ -1,9 +1,5 @@
 import { NextFunction, Request, Response } from "express";
 
-/**
- * Middleware to check if the user
- * is logged in.
- */
 const isLoggedIn = () => (req: Request, res: Response, next: NextFunction) => {
   if (req.session!.user) {
     next();
diff --git a/src/middlewares/auth/isNotRegistered.ts b/src/middlewares/auth/isNotRegistered.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c90aad76532c77df7d35441709ce4a8fa404e768
--- /dev/null
+++ b/src/middlewares/auth/isNotRegistered.ts
@@ -0,0 +1,19 @@
+import { NextFunction, Request, Response } from "express";
+
+const isNotRegistered = () => (
+  req: Request,
+  res: Response,
+  next: NextFunction
+) => {
+  if (req.session!.user) {
+    if (!req.session!.user.id) return next();
+
+    return res.status(403).json({ message: "You are already registered!" });
+  }
+
+  return res
+    .status(401)
+    .json({ message: "You have to login to see this page!" });
+};
+
+export default isNotRegistered;
diff --git a/src/middlewares/auth/isRegistered.ts b/src/middlewares/auth/isRegistered.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ab90fd534a8fef41ff7686f3e482aed5680098c2
--- /dev/null
+++ b/src/middlewares/auth/isRegistered.ts
@@ -0,0 +1,21 @@
+import { NextFunction, Request, Response } from "express";
+
+const isRegistered = () => (
+  req: Request,
+  res: Response,
+  next: NextFunction
+) => {
+  if (req.session!.user) {
+    if (req.session!.user.id) return next();
+
+    return res
+      .status(403)
+      .json({ message: "You have to register to see this page!" });
+  }
+
+  return res
+    .status(401)
+    .json({ message: "You have to login to see this page!" });
+};
+
+export default isRegistered;
diff --git a/src/middlewares/auth/login.ts b/src/middlewares/auth/login.ts
index 15fad1eb38a0b1a28059aed696d8cebea8d9feb9..82a622d0fb8ce9f099334c0b24cccaaebb6569bd 100644
--- a/src/middlewares/auth/login.ts
+++ b/src/middlewares/auth/login.ts
@@ -5,10 +5,8 @@ const authorizationUri = oauth2().authorizationCode.authorizeURL({
   scope: scope,
 });
 
-/**
- * Redirects to the authorization URL
- */
-const login = () => (req: Request, res: Response) =>
+const login = () => (req: Request, res: Response) => {
   res.redirect(authorizationUri);
+};
 
 export default login;
diff --git a/src/middlewares/auth/logout.ts b/src/middlewares/auth/logout.ts
index c3a150c09c9e0fc891cbc8a303f47da369007dad..5394a755275a525bb5af511c02581960b469126d 100644
--- a/src/middlewares/auth/logout.ts
+++ b/src/middlewares/auth/logout.ts
@@ -1,15 +1,14 @@
 import { NextFunction, Request, Response } from "express";
 
-/**
- * Logs out the user by destroying the session
- */
 const logout = () => async (
   req: Request,
   res: Response,
   next: NextFunction
 ) => {
   try {
-    await req.session!.destroy(() => console.log("user logged out."));
+    await req.session!.destroy(() => {
+      // user logged out, do nothing
+    });
     res.redirect("/");
   } catch (err) {
     next(err);
diff --git a/src/middlewares/auth/refreshToken.ts b/src/middlewares/auth/refreshToken.ts
index bc7303be1cd5e25317dc21cc71a1cd023781a7d7..0ef3d75223ad939a0287a564d128b77661136b7b 100644
--- a/src/middlewares/auth/refreshToken.ts
+++ b/src/middlewares/auth/refreshToken.ts
@@ -2,9 +2,6 @@ import { NextFunction, Request, Response } from "express";
 
 import { oauth2 } from "../../utils/auth";
 
-/**
- * Refresh user accessToken
- */
 const refreshToken = () => async (
   req: Request,
   res: Response,
diff --git a/src/middlewares/cards/addCard.ts b/src/middlewares/cards/addCard.ts
deleted file mode 100644
index 06c620304a0da9f2de122d126dafcc83f40618a7..0000000000000000000000000000000000000000
--- a/src/middlewares/cards/addCard.ts
+++ /dev/null
@@ -1,56 +0,0 @@
-import { NextFunction, Request, Response } from "express";
-
-import Card from "../../models/CardSchema";
-import { ErrorHandler } from "../utils/ErrorHandler";
-import Profile from "../../models/ProfileSchema";
-import { validateFields } from "../utils/validateFields";
-
-const fields = [
-  { name: "userId", required: true },
-  { name: "expirationDate", required: true },
-];
-
-/**
- * Middleware that creates a Card
- * from the request body and sets
- * res.data.card to the created Card.
- */
-const addCard = () => async (
-  req: Request,
-  res: Response,
-  next: NextFunction
-) => {
-  try {
-    // Register
-    const newCard = new Card();
-
-    // Validate and set fields from request body
-    validateFields({ fields, reqBody: req.body });
-    fields.forEach((field) => {
-      const value = req.body[field.name];
-      if (value) newCard.set(field.name, req.body[field.name]);
-    });
-
-    // Find and remove old card
-    const oldCard = await Card.findOne({ userId: newCard.userId })
-      .lean()
-      .exec();
-    if (oldCard) await Card.deleteOne({ userId: newCard.userId }).lean().exec();
-
-    const profile = await Profile.findById(newCard.userId).lean().exec();
-
-    if (!profile) throw new ErrorHandler(400, "User doesn't exist");
-
-    newCard.fullName = profile!.name;
-    newCard.roomNumber = profile!.roomNumber;
-
-    await newCard.save();
-    res.data.card = newCard;
-
-    next();
-  } catch (err) {
-    next(err);
-  }
-};
-
-export default addCard;
diff --git a/src/middlewares/cards/getCard.ts b/src/middlewares/cards/getCard.ts
deleted file mode 100644
index 58106bdc38f65e1accb4e5bdd2772cc13406f682..0000000000000000000000000000000000000000
--- a/src/middlewares/cards/getCard.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import { NextFunction, Request, Response } from "express";
-
-import Card from "../../models/CardSchema";
-
-/**
- * Middleware to find the card with
- * id = req.params.id
- * and set res.data.card
- */
-const getCard = () => async (
-  req: Request,
-  res: Response,
-  next: NextFunction
-) => {
-  try {
-    res.data.card = await Card.findById(req.params.id).lean();
-
-    next();
-  } catch (err) {
-    next(err);
-  }
-};
-
-export default getCard;
diff --git a/src/middlewares/cards/getCardList.ts b/src/middlewares/cards/getCardList.ts
deleted file mode 100644
index 4c76a26237ea947fb756b6d73ae93f1727044f1f..0000000000000000000000000000000000000000
--- a/src/middlewares/cards/getCardList.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import { NextFunction, Request, Response } from "express";
-
-import Card from "../../models/CardSchema";
-
-/**
- * Middleware to find all cards
- * and set res.data.cards
- */
-const getCardList = () => async (
-  req: Request,
-  res: Response,
-  next: NextFunction
-) => {
-  try {
-    res.data.cards = await Card.find().lean().exec();
-    next();
-  } catch (err) {
-    next(err);
-  }
-};
-
-export default getCardList;
diff --git a/src/middlewares/cards/getCardListValid.ts b/src/middlewares/cards/getCardListValid.ts
deleted file mode 100644
index 42b912b725d7dd25f0c340fb36e5be0fca267c9e..0000000000000000000000000000000000000000
--- a/src/middlewares/cards/getCardListValid.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-import { NextFunction, Request, Response } from "express";
-
-import Card from "../../models/CardSchema";
-
-/**
- * Middleware to find all
- * not expired cards
- * and set res.data.cards
- */
-const getCardListValid = () => async (
-  req: Request,
-  res: Response,
-  next: NextFunction
-) => {
-  try {
-    res.data.cards = await Card.find({
-      expirationDate: { $gte: new Date() },
-    })
-      .lean()
-      .exec();
-    next();
-  } catch (err) {
-    next(err);
-  }
-};
-
-export default getCardListValid;
diff --git a/src/middlewares/cards/responseCard.ts b/src/middlewares/cards/responseCard.ts
deleted file mode 100644
index 32a6cb875306f5d690bbdd43b047cb280ed6f9ad..0000000000000000000000000000000000000000
--- a/src/middlewares/cards/responseCard.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import { Request, Response } from "express";
-
-/**
- * Return the found card from res.data.card
- */
-const responseCard = (): any => (req: Request, res: Response) => {
-  if (!res.data.card)
-    return res.status(404).json({ message: "Card not found!" });
-
-  return res.json(res.data.card);
-};
-
-export default responseCard;
diff --git a/src/middlewares/cards/responseCardList.ts b/src/middlewares/cards/responseCardList.ts
deleted file mode 100644
index 9a516c153dd57790b142fb896e50b7c32d2dfce2..0000000000000000000000000000000000000000
--- a/src/middlewares/cards/responseCardList.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import { Request, Response } from "express";
-
-/**
- * Return the found card from res.data.cards
- */
-const responseCardList = (): any => (req: Request, res: Response) => {
-  return res.json(res.data.cards);
-};
-
-export default responseCardList;
diff --git a/src/middlewares/example.ts b/src/middlewares/example.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ff1579d19e8f9c61dd49174a48ce32771500cfe9
--- /dev/null
+++ b/src/middlewares/example.ts
@@ -0,0 +1,7 @@
+import { Request, Response } from "express";
+
+const example = () => (req: Request, res: Response) => {
+  res.status(200).json({ message: "Example" });
+};
+
+export default example;
diff --git a/src/middlewares/files/card/cardImageStorage.ts b/src/middlewares/files/card/cardImageStorage.ts
deleted file mode 100644
index f9132f439581ca685bf465a114d719d1e6bc4a2b..0000000000000000000000000000000000000000
--- a/src/middlewares/files/card/cardImageStorage.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import multer from "multer";
-
-export const cardImageStorage = multer.diskStorage({
-  destination: function (req, file, callback) {
-    callback(null, "uploads/card_image/");
-  },
-  filename: function (req, file, callback) {
-    const fileExtension = file.originalname.substring(
-      file.originalname.lastIndexOf(".")
-    );
-    callback(
-      null,
-      Date.now() + "-" + Math.random().toString(36).substring(7) + fileExtension
-    );
-  },
-});
-
-export default cardImageStorage;
diff --git a/src/middlewares/files/card/getCardImage.ts b/src/middlewares/files/card/getCardImage.ts
deleted file mode 100644
index 323292098f719a6ec4e935eab803eee5c0a707e0..0000000000000000000000000000000000000000
--- a/src/middlewares/files/card/getCardImage.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import { NextFunction, Request, Response } from "express";
-
-import CardImage from "../../../models/CardImageSchema";
-
-/**
- * Middleware to get the Entry card background image
- * and set res.data.cardImage
- */
-const getCardImage = () => async (
-  req: Request,
-  res: Response,
-  next: NextFunction
-) => {
-  try {
-    res.data.cardImage = await CardImage.findOne().lean().exec();
-    next();
-  } catch (err) {
-    next(err);
-  }
-};
-
-export default getCardImage;
diff --git a/src/middlewares/files/card/responseCardImage.ts b/src/middlewares/files/card/responseCardImage.ts
deleted file mode 100644
index a5a52bb27733615d26df3f6e048d6b9f580b06c6..0000000000000000000000000000000000000000
--- a/src/middlewares/files/card/responseCardImage.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import { NextFunction, Request, Response } from "express";
-
-import File from "../../../models/FileSchema";
-
-/**
- * Return the Entry card background Image
- */
-const responseCardImage = (): any => async (
-  req: Request,
-  res: Response,
-  next: NextFunction
-) => {
-  try {
-    if (!res.data.cardImage)
-      return res.sendFile("src/utils/card/background.png", { root: "." });
-
-    const cardImage = await File.findById(res.data.cardImage.imageId)
-      .lean()
-      .exec();
-    return res.sendFile(cardImage!.path, { root: "." });
-  } catch (err) {
-    next(err);
-  }
-};
-
-export default responseCardImage;
diff --git a/src/middlewares/files/card/uploadCardImage.ts b/src/middlewares/files/card/uploadCardImage.ts
deleted file mode 100644
index 10fe5b55c96f9dff0c592368db1f352a0fe5d1d2..0000000000000000000000000000000000000000
--- a/src/middlewares/files/card/uploadCardImage.ts
+++ /dev/null
@@ -1,51 +0,0 @@
-import { NextFunction, Request, Response } from "express";
-
-import CardImage from "../../../models/CardImageSchema";
-import File from "../../../models/FileSchema";
-import fs from "fs";
-
-/**
- * Upload a new Card background Image
- */
-const uploadCardImage = () => async (
-  req: Request,
-  res: Response,
-  next: NextFunction
-) => {
-  try {
-    const oldCardImage = await CardImage.findOne().lean().exec();
-
-    if (oldCardImage) {
-      const oldFile = await File.findByIdAndRemove(oldCardImage.imageId)
-        .lean()
-        .exec();
-      if (oldFile) await fs.unlinkSync(oldFile!.path);
-    }
-
-    const newFile = new File();
-    newFile.originalName = req.file.originalname;
-    newFile.uploadDate = new Date();
-    newFile.path = req.file.path;
-    newFile.mimeType = req.file.mimetype;
-
-    await newFile.save();
-
-    if (oldCardImage) {
-      await CardImage.updateOne(
-        { _id: oldCardImage?._id },
-        { imageId: String(newFile._id) }
-      ).exec();
-    } else {
-      const cardImage = new CardImage();
-      cardImage.imageId = String(newFile._id);
-
-      await cardImage.save();
-    }
-
-    return res.status(200).send();
-  } catch (err) {
-    next(err);
-  }
-};
-
-export default uploadCardImage;
diff --git a/src/middlewares/files/createFile.ts b/src/middlewares/files/createFile.ts
new file mode 100644
index 0000000000000000000000000000000000000000..05aec9161b3d70b8e8a5fbd9cfb608b47c0f494d
--- /dev/null
+++ b/src/middlewares/files/createFile.ts
@@ -0,0 +1,38 @@
+import { NextFunction, Request, Response } from "express";
+
+import { ErrorHandler } from "../utils/ErrorHandler";
+import File from "../../models/FileSchema";
+import fs from "fs";
+
+const createFile = () => async (
+  req: Request,
+  res: Response,
+  next: NextFunction
+) => {
+  try {
+    const newFile = new File();
+
+    newFile.originalName = req.file.originalname;
+    newFile.uploadDate = new Date();
+    newFile.path = req.file.path;
+    newFile.mimeType = req.file.mimetype;
+    try {
+      await newFile.save();
+    } catch (e) {
+      fs.unlinkSync(req.file.path);
+      throw new ErrorHandler(
+        500,
+        "There was an error while recording the file in the Database!"
+      );
+    }
+
+    res.data.value = newFile._id;
+    res.data.newObjectId = newFile._id;
+
+    next();
+  } catch (err) {
+    next(err);
+  }
+};
+
+export default createFile;
diff --git a/src/middlewares/files/deleteFile.ts b/src/middlewares/files/deleteFile.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3e7f084542abca873da4d44c00127ee829a75533
--- /dev/null
+++ b/src/middlewares/files/deleteFile.ts
@@ -0,0 +1,23 @@
+import { NextFunction, Request, Response } from "express";
+
+import File from "../../models/FileSchema";
+import fs from "fs";
+
+const deleteFile = () => async (
+  req: Request,
+  res: Response,
+  next: NextFunction
+) => {
+  try {
+    if (!res.data.value) return next();
+
+    const oldFile = await File.findByIdAndRemove(res.data.value).lean().exec();
+    if (oldFile) fs.unlinkSync(oldFile!.path);
+
+    next();
+  } catch (err) {
+    next(err);
+  }
+};
+
+export default deleteFile;
diff --git a/src/middlewares/files/fileFilter.ts b/src/middlewares/files/fileFilter.ts
deleted file mode 100644
index 28c4e66ad3c45e98d5778db42d65be0df4f95968..0000000000000000000000000000000000000000
--- a/src/middlewares/files/fileFilter.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import multer, { FileFilterCallback, Multer } from "multer";
-
-/**
- * multer fileFilter that only lets png or jpeg to be uploaded
- *
- * @param {Express.Request} req
- * @param {Express.Multer.File} file
- * @param {FileFilterCallback} cb
- */
-export function fileFilter(
-  req: Express.Request,
-  file: Express.Multer.File,
-  cb: FileFilterCallback
-) {
-  if (file.mimetype !== "image/png" && file.mimetype !== "image/jpeg") {
-    req.fileValidationError = "Invalid file type!";
-    return cb(null, false);
-  } else {
-    cb(null, true);
-  }
-}
diff --git a/src/middlewares/files/handleFileValidationError.ts b/src/middlewares/files/handleFileValidationError.ts
deleted file mode 100644
index 0bdf0f873267ba1f3c6fd0e362c828a42654336d..0000000000000000000000000000000000000000
--- a/src/middlewares/files/handleFileValidationError.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-import { NextFunction, Request, Response } from "express";
-
-/**
- * Middleware that handles errors after uploading a file
- */
-const handleFileValidationError = () => async (
-  req: Request,
-  res: Response,
-  next: NextFunction
-) => {
-  if (req.fileValidationError) {
-    return res.status(400).send(req.fileValidationError);
-  }
-  if (!req.file) {
-    return res.status(400).send("File wasn't provided!");
-  }
-  next();
-};
-
-export default handleFileValidationError;
diff --git a/src/middlewares/files/imageFilter.ts b/src/middlewares/files/imageFilter.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c8e2f40629a9e5f0235d4acfa130bd5993591edb
--- /dev/null
+++ b/src/middlewares/files/imageFilter.ts
@@ -0,0 +1,14 @@
+import { ErrorHandler } from "../utils/ErrorHandler";
+import { FileFilterCallback } from "multer";
+
+export function imageFilter(
+  req: Express.Request,
+  file: Express.Multer.File,
+  cb: FileFilterCallback
+) {
+  if (file.mimetype !== "image/png" && file.mimetype !== "image/jpeg") {
+    return cb(new ErrorHandler(400, "Invalid file type!"));
+  } else {
+    cb(null, true);
+  }
+}
diff --git a/src/middlewares/files/imageStorage.ts b/src/middlewares/files/imageStorage.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f4c4b4a60d83670756ed514698ddc904a1abf27b
--- /dev/null
+++ b/src/middlewares/files/imageStorage.ts
@@ -0,0 +1,22 @@
+import multer from "multer";
+
+export const imageStorage = (location: string) =>
+  multer.diskStorage({
+    destination: function (req, file, callback) {
+      callback(null, location);
+    },
+    filename: function (req, file, callback) {
+      const fileExtension = file.originalname.substring(
+        file.originalname.lastIndexOf(".")
+      );
+      callback(
+        null,
+        Date.now() +
+          "-" +
+          Math.random().toString(36).substring(7) +
+          fileExtension
+      );
+    },
+  });
+
+export default imageStorage;
diff --git a/src/middlewares/files/profile/getProfilePicture.ts b/src/middlewares/files/profile/getProfilePicture.ts
deleted file mode 100644
index 660beab170d280d365f7530fe6319e611e9bf865..0000000000000000000000000000000000000000
--- a/src/middlewares/files/profile/getProfilePicture.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import { NextFunction, Request, Response } from "express";
-
-import File from "../../../models/FileSchema";
-
-/**
- * Get Profile picture file from res.data.profile
- */
-const getProfilePicture = () => async (
-  req: Request,
-  res: Response,
-  next: NextFunction
-) => {
-  try {
-    if (!res.data.profile!.pictureId)
-      return res
-        .status(400)
-        .send({ message: "You dont have a profile picture!" });
-
-    const file = await File.findById(res.data.profile!.pictureId).lean().exec();
-    return res.sendFile(file!.path, { root: "." });
-  } catch (err) {
-    next(err);
-  }
-};
-
-export default getProfilePicture;
diff --git a/src/middlewares/files/profile/profilePictureStorage.ts b/src/middlewares/files/profile/profilePictureStorage.ts
deleted file mode 100644
index 3ce61b9ee3e42f73925838a9760492c9c2bb48e1..0000000000000000000000000000000000000000
--- a/src/middlewares/files/profile/profilePictureStorage.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import multer from "multer";
-import path from "path";
-
-export const profilePictureStorage = multer.diskStorage({
-  destination: function (req, file, callback) {
-    callback(null, "uploads/profile_pictures/");
-  },
-  filename: function (req, file, callback) {
-    const fileExtension = file.originalname.substring(
-      file.originalname.lastIndexOf(".")
-    );
-    callback(
-      null,
-      Date.now() + "-" + Math.random().toString(36).substring(7) + fileExtension
-    );
-  },
-});
-
-export default profilePictureStorage;
diff --git a/src/middlewares/files/profile/uploadProfilePicture.ts b/src/middlewares/files/profile/uploadProfilePicture.ts
deleted file mode 100644
index d18667298cf4cde82b167572556ab8c5ed4d0e1c..0000000000000000000000000000000000000000
--- a/src/middlewares/files/profile/uploadProfilePicture.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-import { NextFunction, Request, Response } from "express";
-
-import { ErrorHandler } from "../../../middlewares/utils/ErrorHandler";
-import File from "../../../models/FileSchema";
-import Profile from "../../../models/ProfileSchema";
-import fs from "fs";
-
-/**
- * Upload a new profile picture to a given User in res.data.profile
- */
-const uploadProfilePicture = () => async (
-  req: Request,
-  res: Response,
-  next: NextFunction
-) => {
-  try {
-    if (!res.data.profile) throw new ErrorHandler(400, "User not found!");
-    if (res.data.profile.pictureId) {
-      const oldFile = await File.findByIdAndRemove(res.data.profile.pictureId)
-        .lean()
-        .exec();
-      if (oldFile) await fs.unlinkSync(oldFile!.path);
-    }
-
-    const newFile = new File();
-
-    newFile.originalName = req.file.originalname;
-    newFile.uploadDate = new Date();
-    newFile.path = req.file.path;
-    newFile.mimeType = req.file.mimetype;
-
-    await newFile.save();
-
-    await Profile.updateOne(
-      { _id: res.data.profile!._id },
-      { pictureId: newFile._id }
-    ).exec();
-
-    return res.status(200).send();
-  } catch (err) {
-    next(err);
-  }
-};
-
-export default uploadProfilePicture;
diff --git a/src/middlewares/files/sendFile.ts b/src/middlewares/files/sendFile.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a1aa128a5ff356fbb47e3e60764b3300f13b31ae
--- /dev/null
+++ b/src/middlewares/files/sendFile.ts
@@ -0,0 +1,22 @@
+import { NextFunction, Request, Response } from "express";
+
+import { ErrorHandler } from "../utils/ErrorHandler";
+import File from "../../models/FileSchema";
+
+const sendFile = (): any => async (
+  req: Request,
+  res: Response,
+  next: NextFunction
+) => {
+  try {
+    const file = await File.findById(res.data.value).lean().exec();
+
+    if (!file) throw new ErrorHandler(404, "File not found!");
+
+    return res.sendFile(file.path, { root: "." });
+  } catch (err) {
+    next(err);
+  }
+};
+
+export default sendFile;
diff --git a/src/middlewares/files/card/getUserCard.ts b/src/middlewares/files/sendUserCard.ts
similarity index 54%
rename from src/middlewares/files/card/getUserCard.ts
rename to src/middlewares/files/sendUserCard.ts
index e1e35121f6bfeced11f4abab806d3003bb73b5b3..4a98f43d8fc9e85e4baed7fd8e8f98cbf929b21d 100644
--- a/src/middlewares/files/card/getUserCard.ts
+++ b/src/middlewares/files/sendUserCard.ts
@@ -1,44 +1,39 @@
 import { NextFunction, Request, Response } from "express";
 
-import Card from "../../../models/CardSchema";
-import File from "../../../models/FileSchema";
+import File from "../../models/FileSchema";
 import fs from "fs";
 
-/**
- * Generate Entry card svg from Users data and card
- */
-const getUserCard = (): any => async (
+const sendUserCard = (): any => async (
   req: Request,
   res: Response,
   next: NextFunction
 ) => {
   try {
-    const userCard = await Card.findOne({ userId: res.data.profile?._id })
-      .lean()
-      .exec();
-    if (!userCard)
+    if (res.data.term!.members!.length == 0)
       return res
         .status(404)
-        .json({ message: "The user doesn't have any card!" });
+        .json({ message: "The given user is not a member" });
 
     let profilePicture = "data:image/png;base64,";
-    if (!res.data.profile!.pictureId) {
+    if (!res.data.profile!.acceptedPicture) {
       profilePicture += fs.readFileSync(
         "src/utils/card/profile_picture.png",
         "base64"
       );
     } else {
-      const profilePicFile = await File.findById(res.data.profile!.pictureId)
+      const profilePicFile = await File.findById(
+        res.data.profile!.acceptedPicture
+      )
         .lean()
         .exec();
       profilePicture += fs.readFileSync(profilePicFile!.path, "base64");
     }
 
     let bgPicture = "data:image/png;base64,";
-    if (!res.data.cardImage)
+    if (!res.data.term!.backgroundFile)
       bgPicture += fs.readFileSync("src/utils/card/background.png", "base64");
     else {
-      const bgFile = await File.findById(res.data.cardImage.imageId)
+      const bgFile = await File.findById(res.data.term!.backgroundFile)
         .lean()
         .exec();
       bgPicture += fs.readFileSync(bgFile!.path, "base64");
@@ -49,12 +44,15 @@ const getUserCard = (): any => async (
     const result = svg
       .replace(/{{profile_picture}}/g, profilePicture)
       .replace(/{{background_image}}/g, bgPicture)
-      .replace(/{{full_name}}/g, String(userCard?.fullName))
-      .replace(/{{room_number}}/g, String(userCard?.roomNumber))
-      .replace(/{{card_number}}/g, String(userCard?.cardId))
+      .replace(/{{full_name}}/g, String(res.data.profile!.name))
+      .replace(/{{room_number}}/g, String(res.data.profile!.roomNumber))
+      .replace(
+        /{{card_number}}/g,
+        String(res.data.term!.members![0].cardNumber)
+      )
       .replace(
         /{{expiration_date}}/g,
-        String(userCard?.expirationDate.toISOString().split("T")[0])
+        String(res.data.term!.endDate!.toISOString().split("T")[0])
       );
 
     return res.type("svg").send(result);
@@ -63,4 +61,4 @@ const getUserCard = (): any => async (
   }
 };
 
-export default getUserCard;
+export default sendUserCard;
diff --git a/src/middlewares/files/updateProfilePicture.ts b/src/middlewares/files/updateProfilePicture.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b7b038947bfa2316c2809d3a934d0f66cea5df96
--- /dev/null
+++ b/src/middlewares/files/updateProfilePicture.ts
@@ -0,0 +1,31 @@
+import { NextFunction, Request, Response } from "express";
+
+import File from "../../models/FileSchema";
+import Profile from "../../models/ProfileSchema";
+import fs from "fs";
+
+const updateProfilePicture = () => async (
+  req: Request,
+  res: Response,
+  next: NextFunction
+) => {
+  try {
+    if (res.data.profile!.newPicture) {
+      const oldFile = await File.findByIdAndRemove(res.data.profile!.newPicture)
+        .lean()
+        .exec();
+      if (oldFile) fs.unlinkSync(oldFile!.path);
+    }
+
+    await Profile.updateOne(
+      { _id: res.data.profile!._id },
+      { newPicture: res.data.value! }
+    ).exec();
+
+    next();
+  } catch (err) {
+    next(err);
+  }
+};
+
+export default updateProfilePicture;
diff --git a/src/middlewares/files/updateTermCardBg.ts b/src/middlewares/files/updateTermCardBg.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4f14dfc9de50c4b5377ec1f14aa7b6d51581231c
--- /dev/null
+++ b/src/middlewares/files/updateTermCardBg.ts
@@ -0,0 +1,33 @@
+import { NextFunction, Request, Response } from "express";
+
+import File from "../../models/FileSchema";
+import Term from "../../models/TermSchema";
+import fs from "fs";
+
+const updateTermCardBg = () => async (
+  req: Request,
+  res: Response,
+  next: NextFunction
+) => {
+  try {
+    if (res.data.term!.backgroundFile) {
+      const oldFile = await File.findByIdAndRemove(
+        res.data.term!.backgroundFile
+      )
+        .lean()
+        .exec();
+      if (oldFile) fs.unlinkSync(oldFile!.path);
+    }
+
+    await Term.updateOne(
+      { _id: res.data.term!._id },
+      { backgroundFile: res.data.value! }
+    ).exec();
+
+    next();
+  } catch (err) {
+    next(err);
+  }
+};
+
+export default updateTermCardBg;
diff --git a/src/middlewares/news/addNews.ts b/src/middlewares/news/addNews.ts
index 4be1fe97e8a6805c8a9059e674e63c6195dd4a9e..bbbed67f1a2797e35a382180800cdf2e43469c47 100644
--- a/src/middlewares/news/addNews.ts
+++ b/src/middlewares/news/addNews.ts
@@ -1,21 +1,11 @@
+import News, { INews } from "../../models/NewsSchema";
 import { NextFunction, Request, Response } from "express";
 
-import News from "../../models/NewsSchema";
 import { validateFields } from "../utils/validateFields";
 
-const fields = [
-  { name: "title", required: true },
-  { name: "text", required: true },
-];
-
-/**
- * Create a New Article
- */
-const addNews = () => async (
-  req: Request,
-  res: Response,
-  next: NextFunction
-) => {
+const addNews = (
+  fields: { name: Partial<keyof INews>; required: boolean }[]
+) => async (req: Request, res: Response, next: NextFunction) => {
   try {
     const news = new News();
 
@@ -27,10 +17,11 @@ const addNews = () => async (
     });
 
     news.publishedAt = new Date();
+    news.publishedBy = req.session.user!.id!;
 
     await news.save();
 
-    res.data.newsObject = news;
+    res.data.newObjectId = news._id;
     next();
   } catch (err) {
     next(err);
diff --git a/src/middlewares/news/deleteNews.ts b/src/middlewares/news/deleteNews.ts
index 406b13381c488d42e56e855de82fc5f5a7b4b51d..e9925c9a1047c7b4249d2331fdd3c5c25760f4ef 100644
--- a/src/middlewares/news/deleteNews.ts
+++ b/src/middlewares/news/deleteNews.ts
@@ -1,6 +1,5 @@
 import { NextFunction, Request, Response } from "express";
 
-import { ErrorHandler } from "../utils/ErrorHandler";
 import News from "../../models/NewsSchema";
 
 const deleteNews = () => async (
@@ -9,8 +8,10 @@ const deleteNews = () => async (
   next: NextFunction
 ) => {
   try {
-    const news = await News.findByIdAndRemove(req.params.id).lean().exec();
-    if (!news) throw new ErrorHandler(404, "News not found!");
+    const news = await News.findByIdAndRemove(req.params.newsId)
+      .select("_id")
+      .lean()
+      .exec();
     next();
   } catch (err) {
     next(err);
diff --git a/src/middlewares/news/getNews.ts b/src/middlewares/news/getNews.ts
deleted file mode 100644
index 2f8e60a6473aa2d2c688e65cd8b4c55196c75f8c..0000000000000000000000000000000000000000
--- a/src/middlewares/news/getNews.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import { NextFunction, Request, Response } from "express";
-
-import News from "../../models/NewsSchema";
-
-/**
- * Get one News with id = req.params.id
- * and set res.data.newsObject
- */
-const getNews = () => async (
-  req: Request,
-  res: Response,
-  next: NextFunction
-) => {
-  try {
-    res.data.newsObject = await News.findById(req.params.id).lean().exec();
-    next();
-  } catch (err) {
-    next(err);
-  }
-};
-
-export default getNews;
diff --git a/src/middlewares/news/getNewsList.ts b/src/middlewares/news/getNewsList.ts
index 21b6f71e4d52d7fda3becf97b5bd32433eb4b396..c6b4aabd8b6e517a763e12f730420a44dce5304b 100644
--- a/src/middlewares/news/getNewsList.ts
+++ b/src/middlewares/news/getNewsList.ts
@@ -2,17 +2,13 @@ import { NextFunction, Request, Response } from "express";
 
 import News from "../../models/NewsSchema";
 
-/**
- * Get all news and set res.data.news
- *
- */
-const getNewsList = () => async (
+const getNewsList = (selectQuery: string) => async (
   req: Request,
   res: Response,
   next: NextFunction
 ) => {
   try {
-    res.data.news = await News.find();
+    res.data.news = await News.find().select(selectQuery).lean().exec();
     next();
   } catch (err) {
     next(err);
diff --git a/src/middlewares/news/getOneNews.ts b/src/middlewares/news/getOneNews.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ef7de250bdae376950e22c0dc09ea862b1627890
--- /dev/null
+++ b/src/middlewares/news/getOneNews.ts
@@ -0,0 +1,25 @@
+import { NextFunction, Request, Response } from "express";
+
+import News from "../../models/NewsSchema";
+
+const getOneNews = (selectQuery: string) => async (
+  req: Request,
+  res: Response,
+  next: NextFunction
+) => {
+  try {
+    res.data.oneNews = await News.findById(req.params.newsId)
+      .select(selectQuery)
+      .lean()
+      .exec();
+
+    if (!res.data.oneNews)
+      return res.status(404).json({ message: "News not found!" });
+
+    next();
+  } catch (err) {
+    next(err);
+  }
+};
+
+export default getOneNews;
diff --git a/src/middlewares/news/responseNews.ts b/src/middlewares/news/responseNews.ts
index d570a738ba7e7830e0e19dc2a43e0994dd5d5b23..ebea2e333b84a0c99f7a9df8ed5349b4395cc3ec 100644
--- a/src/middlewares/news/responseNews.ts
+++ b/src/middlewares/news/responseNews.ts
@@ -1,10 +1,7 @@
-import { NextFunction, Request, Response, response } from "express";
+import { Request, Response } from "express";
 
-/**
- * Return the found news from res.data.news
- */
 const responseNews = () => (req: Request, res: Response) => {
-  res.json(res.data.news);
+  res.json(res.data.news || []);
 };
 
 export default responseNews;
diff --git a/src/middlewares/news/responseNewsObject.ts b/src/middlewares/news/responseNewsObject.ts
deleted file mode 100644
index abcf8d595e0e04a29b1df9d03d3910c650ae0e95..0000000000000000000000000000000000000000
--- a/src/middlewares/news/responseNewsObject.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import { NextFunction, Request, Response, response } from "express";
-
-/**
- * Return the found user from res.data.profile
- */
-const responseNewsObject = () => (req: Request, res: Response) => {
-  if (!res.data.newsObject) {
-    res.status(404).json({ message: "News not found!" });
-  } else {
-    res.json(res.data.newsObject);
-  }
-};
-
-export default responseNewsObject;
diff --git a/src/middlewares/news/responseOneNews.ts b/src/middlewares/news/responseOneNews.ts
new file mode 100644
index 0000000000000000000000000000000000000000..51d04a05880f7a605537a0bc5fcdb08346325b23
--- /dev/null
+++ b/src/middlewares/news/responseOneNews.ts
@@ -0,0 +1,11 @@
+import { Request, Response } from "express";
+
+const responseOneNews = () => (req: Request, res: Response) => {
+  if (!res.data.oneNews) {
+    res.status(404).json({ message: "News not found!" });
+  } else {
+    res.json(res.data.oneNews);
+  }
+};
+
+export default responseOneNews;
diff --git a/src/middlewares/news/updateNews.ts b/src/middlewares/news/updateNews.ts
index 8be12bb9b85310d5818650019d513ab6b0341330..6c5d77c875a65050878ca47bf660392e7bd528b1 100644
--- a/src/middlewares/news/updateNews.ts
+++ b/src/middlewares/news/updateNews.ts
@@ -1,28 +1,26 @@
 import News, { INews } from "../../models/NewsSchema";
 import { NextFunction, Request, Response } from "express";
 
-// Valid fields to update
-const validFields = ["title", "text"];
-
-/**
- * Update a News Object
- */
-const updateNews = () => async (
+const updateNews = (fields: Partial<keyof INews>[]) => async (
   req: Request,
   res: Response,
   next: NextFunction
 ) => {
   try {
-    const news = await News.findById(req.params.id).exec();
+    let newFields: Partial<INews> = {};
+    fields.forEach((field) => {
+      const value = req.body[field];
+      if (value) newFields[field] = value;
+    });
+    newFields["updatedBy"] = req.session.user!.id;
 
-    if (news) {
-      validFields.forEach((field) => {
-        const value = req.body[field];
-        if (value) news.set(field, value);
-      });
-      await news.save();
-    }
-    res.data.newsObject = news;
+    await News.updateOne(
+      { _id: req.params.newsId },
+      { $set: newFields },
+      { upsert: true, runValidators: true }
+    )
+      .lean()
+      .exec();
 
     next();
   } catch (err) {
diff --git a/src/middlewares/term/addMember.ts b/src/middlewares/term/addMember.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ee148f2ac9177085d868607515bb52c77375aa6f
--- /dev/null
+++ b/src/middlewares/term/addMember.ts
@@ -0,0 +1,41 @@
+import { NextFunction, Request, Response } from "express";
+import Term, { CardState, IMember, MemberState } from "../../models/TermSchema";
+
+import Counter from "../../models/CounterSchema";
+
+const addMember = () => async (
+  req: Request,
+  res: Response,
+  next: NextFunction
+) => {
+  try {
+    const counter = await Counter.findByIdAndUpdate(
+      { _id: "cardId" },
+      { $inc: { seq: 1 } },
+      { upsert: true, new: true }
+    )
+      .lean()
+      .exec();
+
+    const member: IMember = {
+      user: res.data.profile!._id,
+      memberState: MemberState.Applied,
+      cardState: CardState.Created,
+      cardNumber: Number(counter.seq),
+    };
+
+    await Term.updateOne(
+      { _id: res.data.term!._id },
+      { $push: { members: member } },
+      { runValidators: true }
+    )
+      .lean()
+      .exec();
+
+    next();
+  } catch (err) {
+    next(err);
+  }
+};
+
+export default addMember;
diff --git a/src/middlewares/term/addTerm.ts b/src/middlewares/term/addTerm.ts
new file mode 100644
index 0000000000000000000000000000000000000000..542cdb0cde2397b3dd366dc702e5b1221cb3f1a7
--- /dev/null
+++ b/src/middlewares/term/addTerm.ts
@@ -0,0 +1,28 @@
+import { NextFunction, Request, Response } from "express";
+import Term, { ITerm } from "../../models/TermSchema";
+
+import { validateFields } from "../utils/validateFields";
+
+const addTerm = (
+  fields: { name: Partial<keyof ITerm>; required: boolean }[]
+) => async (req: Request, res: Response, next: NextFunction) => {
+  try {
+    const term = new Term();
+
+    // Validate and set fields from request body
+    validateFields({ fields, reqBody: req.body });
+    fields.forEach((field) => {
+      const value = req.body[field.name];
+      if (value) term.set(field.name, req.body[field.name]);
+    });
+    term.createDate = new Date();
+    await term.save();
+
+    res.data.newObjectId = term._id;
+    next();
+  } catch (err) {
+    next(err);
+  }
+};
+
+export default addTerm;
diff --git a/src/middlewares/term/deleteTerm.ts b/src/middlewares/term/deleteTerm.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c3233d6d69e63b3e6fed8b811996d6f7f591767e
--- /dev/null
+++ b/src/middlewares/term/deleteTerm.ts
@@ -0,0 +1,25 @@
+import { NextFunction, Request, Response } from "express";
+
+import File from "../../models/FileSchema";
+import Term from "../../models/TermSchema";
+
+const deleteTerm = () => async (
+  req: Request,
+  res: Response,
+  next: NextFunction
+) => {
+  try {
+    const removedTerm = await Term.findByIdAndDelete(req.params.termId)
+      .select("_id backgroundFile")
+      .lean()
+      .exec();
+    if (!removedTerm)
+      return res.status(404).json({ message: "Term not found!" });
+    await File.findByIdAndDelete(removedTerm?.backgroundFile);
+    next();
+  } catch (err) {
+    next(err);
+  }
+};
+
+export default deleteTerm;
diff --git a/src/middlewares/term/getTerm.ts b/src/middlewares/term/getTerm.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8d9af82a58d22f21cdd826cef63b9ddb03fe1866
--- /dev/null
+++ b/src/middlewares/term/getTerm.ts
@@ -0,0 +1,39 @@
+import { NextFunction, Request, Response } from "express";
+
+import Term from "../../models/TermSchema";
+
+/**
+ * termId -> term
+ */
+const getTerm = (sendBgFile = false) => async (
+  req: Request,
+  res: Response,
+  next: NextFunction
+) => {
+  try {
+    res.data.term = await Term.findOne(
+      { _id: req.params.termId },
+      {
+        _id: 1,
+        name: 1,
+        startDate: 1,
+        endDate: 1,
+        deadline: 1,
+        createDate: 1,
+        backgroundFile: sendBgFile ? 1 : 0,
+        members: { $elemMatch: { user: req.params.userId } },
+      }
+    )
+      .lean()
+      .exec();
+
+    if (!res.data.term)
+      return res.status(404).json({ message: "Term not found" });
+
+    next();
+  } catch (err) {
+    next(err);
+  }
+};
+
+export default getTerm;
diff --git a/src/middlewares/term/getTermMembers.ts b/src/middlewares/term/getTermMembers.ts
new file mode 100644
index 0000000000000000000000000000000000000000..79ffe98c6c88a69005b29c5f9998d86e499d7874
--- /dev/null
+++ b/src/middlewares/term/getTermMembers.ts
@@ -0,0 +1,31 @@
+import { NextFunction, Request, Response } from "express";
+
+import Term from "../../models/TermSchema";
+
+const getTermMembers = () => async (
+  req: Request,
+  res: Response,
+  next: NextFunction
+) => {
+  try {
+    const term = await Term.findOne(
+      { _id: req.params.termId },
+      {
+        members: 1,
+      }
+    )
+      .populate("members.user", { name: 1, warnings: { $size: "$warnings" } })
+      .lean()
+      .exec();
+
+    if (!term) return res.status(404).json({ message: "Term not found" });
+
+    res.data.members = term?.members;
+
+    next();
+  } catch (err) {
+    next(err);
+  }
+};
+
+export default getTermMembers;
diff --git a/src/middlewares/term/getTermWithQuery.ts b/src/middlewares/term/getTermWithQuery.ts
new file mode 100644
index 0000000000000000000000000000000000000000..561e30417c5d1564f3c07972748a0e89530b2878
--- /dev/null
+++ b/src/middlewares/term/getTermWithQuery.ts
@@ -0,0 +1,25 @@
+import { NextFunction, Request, Response } from "express";
+
+import Term from "../../models/TermSchema";
+
+const getTermWithQuery = (selectQuery: string) => async (
+  req: Request,
+  res: Response,
+  next: NextFunction
+) => {
+  try {
+    res.data.term = await Term.findById(req.params.termId)
+      .select(selectQuery)
+      .lean()
+      .exec();
+
+    if (!res.data.term)
+      return res.status(404).json({ message: "Term not found" });
+
+    next();
+  } catch (err) {
+    next(err);
+  }
+};
+
+export default getTermWithQuery;
diff --git a/src/middlewares/term/getTermsList.ts b/src/middlewares/term/getTermsList.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c916feeed5fde205e13fa34048a87d62a14448b6
--- /dev/null
+++ b/src/middlewares/term/getTermsList.ts
@@ -0,0 +1,32 @@
+import { NextFunction, Request, Response } from "express";
+
+import Term from "../../models/TermSchema";
+
+const getTermsList = () => async (
+  req: Request,
+  res: Response,
+  next: NextFunction
+) => {
+  try {
+    res.data.terms = await Term.find(
+      {},
+      {
+        _id: 1,
+        name: 1,
+        startDate: 1,
+        endDate: 1,
+        deadline: 1,
+        createDate: 1,
+        members: { $elemMatch: { user: req.params.userId } },
+      }
+    )
+      .lean()
+      .exec();
+
+    next();
+  } catch (err) {
+    next(err);
+  }
+};
+
+export default getTermsList;
diff --git a/src/middlewares/term/getUserTermMemberships.ts b/src/middlewares/term/getUserTermMemberships.ts
new file mode 100644
index 0000000000000000000000000000000000000000..49868f370ba4255d39518111752576f068382b18
--- /dev/null
+++ b/src/middlewares/term/getUserTermMemberships.ts
@@ -0,0 +1,28 @@
+import { NextFunction, Request, Response } from "express";
+
+import Term from "../../models/TermSchema";
+
+const getUserTermMemberships = () => async (
+  req: Request,
+  res: Response,
+  next: NextFunction
+) => {
+  try {
+    res.data.terms = await Term.find(
+      { "members.user": req.params.userId },
+      {
+        _id: 1,
+        name: 1,
+        members: { $elemMatch: { user: req.params.userId } },
+      }
+    )
+      .lean()
+      .exec();
+
+    next();
+  } catch (err) {
+    next(err);
+  }
+};
+
+export default getUserTermMemberships;
diff --git a/src/middlewares/term/isNotMember.ts b/src/middlewares/term/isNotMember.ts
new file mode 100644
index 0000000000000000000000000000000000000000..903262194dace009d6872dc4cf6bc5ecb0c99565
--- /dev/null
+++ b/src/middlewares/term/isNotMember.ts
@@ -0,0 +1,21 @@
+import { NextFunction, Request, Response } from "express";
+
+const isNotMember = () => async (
+  req: Request,
+  res: Response,
+  next: NextFunction
+) => {
+  try {
+    res.data.member = res.data.term?.members?.find(
+      (member) => member.user == req.params.userId
+    );
+    if (res.data.member)
+      return res.status(400).json({ message: "Already a member!" });
+
+    next();
+  } catch (err) {
+    next(err);
+  }
+};
+
+export default isNotMember;
diff --git a/src/middlewares/term/responseMembersList.ts b/src/middlewares/term/responseMembersList.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7b2454844a5b67d158011ffa407c721b49435303
--- /dev/null
+++ b/src/middlewares/term/responseMembersList.ts
@@ -0,0 +1,7 @@
+import { Request, Response } from "express";
+
+const responseMembersList = () => (req: Request, res: Response) => {
+  return res.json(res.data.members);
+};
+
+export default responseMembersList;
diff --git a/src/middlewares/term/responseTerm.ts b/src/middlewares/term/responseTerm.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d178cc7a7ad21e2e28a3b4213871ec72c929746c
--- /dev/null
+++ b/src/middlewares/term/responseTerm.ts
@@ -0,0 +1,10 @@
+import { Request, Response } from "express";
+
+const responseTerm = () => (req: Request, res: Response) => {
+  if (!res.data.term)
+    return res.status(404).json({ message: "Term not found!" });
+
+  return res.json(res.data.term);
+};
+
+export default responseTerm;
diff --git a/src/middlewares/term/responseTermsList.ts b/src/middlewares/term/responseTermsList.ts
new file mode 100644
index 0000000000000000000000000000000000000000..9c478a3100d25d2d0d485604a94ada65dc1d59a7
--- /dev/null
+++ b/src/middlewares/term/responseTermsList.ts
@@ -0,0 +1,7 @@
+import { Request, Response } from "express";
+
+const responseTermsList = () => (req: Request, res: Response) => {
+  return res.json(res.data.terms || []);
+};
+
+export default responseTermsList;
diff --git a/src/middlewares/term/updateTerm.ts b/src/middlewares/term/updateTerm.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8187677774c730d6d1518acd123e94984840c868
--- /dev/null
+++ b/src/middlewares/term/updateTerm.ts
@@ -0,0 +1,30 @@
+import { NextFunction, Request, Response } from "express";
+import Term, { ITerm } from "../../models/TermSchema";
+
+const updateTerm = (fields: Partial<keyof ITerm>[]) => async (
+  req: Request,
+  res: Response,
+  next: NextFunction
+) => {
+  try {
+    let newFields: Partial<ITerm> = {};
+    fields.forEach((field) => {
+      const value = req.body[field];
+      if (value) newFields[field] = value;
+    });
+
+    await Term.updateOne(
+      { _id: req.params.termId },
+      { $set: newFields },
+      { upsert: true, runValidators: true }
+    )
+      .lean()
+      .exec();
+
+    next();
+  } catch (err) {
+    next(err);
+  }
+};
+
+export default updateTerm;
diff --git a/src/middlewares/term/updateTermMember.ts b/src/middlewares/term/updateTermMember.ts
new file mode 100644
index 0000000000000000000000000000000000000000..da560d8b7c5424b3eb84d64947a27f9b8a09a40a
--- /dev/null
+++ b/src/middlewares/term/updateTermMember.ts
@@ -0,0 +1,30 @@
+import { NextFunction, Request, Response } from "express";
+import Term, { IMember } from "../../models/TermSchema";
+
+const updateTermMember = (fields: Partial<keyof IMember>[]) => async (
+  req: Request,
+  res: Response,
+  next: NextFunction
+) => {
+  try {
+    let newFields: Partial<any> = {};
+    fields.forEach((field) => {
+      const value = req.body[field];
+      if (value) newFields["members.$." + field] = value;
+    });
+
+    await Term.updateOne(
+      { _id: req.params.termId, "members.user": req.params.userId },
+      { $set: newFields },
+      { runValidators: true }
+    )
+      .lean()
+      .exec();
+
+    next();
+  } catch (err) {
+    next(err);
+  }
+};
+
+export default updateTermMember;
diff --git a/src/middlewares/user/acceptPicture.ts b/src/middlewares/user/acceptPicture.ts
new file mode 100644
index 0000000000000000000000000000000000000000..182e8539aa9606d17bbf410c7dc56eb09cc7e9dc
--- /dev/null
+++ b/src/middlewares/user/acceptPicture.ts
@@ -0,0 +1,37 @@
+import { NextFunction, Request, Response } from "express";
+
+import Profile from "../../models/ProfileSchema";
+
+const acceptPicture = () => async (
+  req: Request,
+  res: Response,
+  next: NextFunction
+) => {
+  try {
+    if (!res.data.profile?.newPicture)
+      return res.status(400).json({
+        message: "The User doesn't have any unaccepted Profile picture!",
+      });
+
+    const newPic = res.data.profile.newPicture;
+    // TODO Notification
+    await Profile.updateOne(
+      { _id: req.params.userId },
+      {
+        $set: {
+          newPicture: undefined,
+          acceptedPicture: newPic,
+        },
+      },
+      { upsert: true, runValidators: true }
+    )
+      .lean()
+      .exec();
+
+    next();
+  } catch (err) {
+    next(err);
+  }
+};
+
+export default acceptPicture;
diff --git a/src/middlewares/user/deleteUser.ts b/src/middlewares/user/deleteUser.ts
index 00b61114dbd328f9dae3e3cc57257ea272b96292..1bd4a702c6f40daba33c03b0772d05e25b6ea5f8 100644
--- a/src/middlewares/user/deleteUser.ts
+++ b/src/middlewares/user/deleteUser.ts
@@ -2,16 +2,14 @@ import { NextFunction, Request, Response } from "express";
 
 import Profile from "../../models/ProfileSchema";
 
-/**
- * Middleware to delete User where id = req.params.id
- */
+// TODO Delete from Terms
 const deleteUser = () => async (
   req: Request,
   res: Response,
   next: NextFunction
 ) => {
   try {
-    await Profile.findByIdAndDelete(req.params.id);
+    await Profile.findByIdAndDelete(req.params.userId).lean().exec();
     next();
   } catch (err) {
     next(err);
diff --git a/src/middlewares/user/getUser.ts b/src/middlewares/user/getUser.ts
index 079233a6c62ff771d3d51b790bc903d7e6231999..8c1713ad4e35c703c592d171e1b69a95742b42b1 100644
--- a/src/middlewares/user/getUser.ts
+++ b/src/middlewares/user/getUser.ts
@@ -1,20 +1,22 @@
 import { NextFunction, Request, Response } from "express";
 
-import { IWarning } from "../../models/WarningSchema";
 import Profile from "../../models/ProfileSchema";
-import Warning from "../../models/WarningSchema";
 
-/**
- * Middleware to get a User by req.params.id
- * and set res.data.profile
- */
-const getUser = () => async (
+// TODO remove from Term members
+const getUser = (selectQuery: string) => async (
   req: Request,
   res: Response,
   next: NextFunction
 ) => {
   try {
-    res.data.profile = await Profile.findById(req.params.id).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" });
+
     next();
   } catch (err) {
     next(err);
diff --git a/src/middlewares/user/getUsersList.ts b/src/middlewares/user/getUsersList.ts
index 3cc3e4cb1a91a0670b701bf412aa4fa872757b7a..cc1107e2efaad3bd09b0dee7390ed71c55006910 100644
--- a/src/middlewares/user/getUsersList.ts
+++ b/src/middlewares/user/getUsersList.ts
@@ -1,14 +1,17 @@
 import { NextFunction, Request, Response } from "express";
+import Profile, { IProfile } from "../../models/ProfileSchema";
 
-import Profile from "../../models/ProfileSchema";
+import { FilterQuery } from "mongoose";
 
-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();
+    res.data.profiles = await Profile.find(filterQuery)
+      .select(selectQuery)
+      .lean()
+      .exec();
     next();
   } catch (err) {
     next(err);
diff --git a/src/middlewares/user/notice/addNoticeToUser.ts b/src/middlewares/user/notice/addNoticeToUser.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0d46e29eda04863fd899f64f24805eccf865dd2d
--- /dev/null
+++ b/src/middlewares/user/notice/addNoticeToUser.ts
@@ -0,0 +1,34 @@
+import { NextFunction, Request, Response } from "express";
+import Profile, { INotice } from "../../../models/ProfileSchema";
+
+import { Types } from "mongoose";
+import { validateFields } from "../../utils/validateFields";
+
+const addNoticeToUser = (
+  fields: { name: Partial<keyof INotice>; required: boolean }[]
+) => async (req: Request, res: Response, next: NextFunction) => {
+  try {
+    validateFields({ fields, reqBody: req.body });
+
+    const notice: INotice = {
+      text: req.body.text,
+      redirect: req.body.redirect || "",
+      isSeen: false,
+      _id: String(new Types.ObjectId()),
+    };
+
+    await Profile.updateOne(
+      { _id: req.params.userId },
+      { $push: { notices: notice } },
+      { runValidators: true }
+    )
+      .lean()
+      .exec();
+
+    next();
+  } catch (err) {
+    next(err);
+  }
+};
+
+export default addNoticeToUser;
diff --git a/src/middlewares/user/notice/deleteNotice.ts b/src/middlewares/user/notice/deleteNotice.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a820add2e0bd123d2567f8b7644c7288f4ee66d1
--- /dev/null
+++ b/src/middlewares/user/notice/deleteNotice.ts
@@ -0,0 +1,24 @@
+import { NextFunction, Request, Response } from "express";
+
+import Profile from "../../../models/ProfileSchema";
+
+const deleteNotice = () => async (
+  req: Request,
+  res: Response,
+  next: NextFunction
+) => {
+  try {
+    await Profile.updateOne(
+      { _id: req.params.userId },
+      { $pull: { notices: { _id: req.params.noticeId } } }
+    )
+      .lean()
+      .exec();
+
+    next();
+  } catch (err) {
+    next(err);
+  }
+};
+
+export default deleteNotice;
diff --git a/src/middlewares/user/notice/getUserNoticeNum.ts b/src/middlewares/user/notice/getUserNoticeNum.ts
new file mode 100644
index 0000000000000000000000000000000000000000..516168180b4088ef8ea392ccd9b23e4163b5f8c6
--- /dev/null
+++ b/src/middlewares/user/notice/getUserNoticeNum.ts
@@ -0,0 +1,30 @@
+import { NextFunction, Request, Response } from "express";
+
+import Profile from "../../../models/ProfileSchema";
+
+const getUserNoticeNum = () => async (
+  req: Request,
+  res: Response,
+  next: NextFunction
+) => {
+  try {
+    const profile = await Profile.findOne(
+      { _id: req.params.userId },
+      {
+        noticesNum: { $size: { $ifNull: ["$notices", []] } },
+      }
+    )
+      .lean()
+      .exec();
+
+    if (!profile) return res.status(404).json({ message: "Profile not found" });
+
+    res.data.number = profile!.noticesNum;
+
+    next();
+  } catch (err) {
+    next(err);
+  }
+};
+
+export default getUserNoticeNum;
diff --git a/src/middlewares/user/notice/getUserNotices.ts b/src/middlewares/user/notice/getUserNotices.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5907fe27a6b0a67ec3c379beca06929a528f9121
--- /dev/null
+++ b/src/middlewares/user/notice/getUserNotices.ts
@@ -0,0 +1,33 @@
+import { NextFunction, Request, Response } from "express";
+
+import Profile from "../../../models/ProfileSchema";
+
+const getUserNotices = () => async (
+  req: Request,
+  res: Response,
+  next: NextFunction
+) => {
+  try {
+    const profile = await Profile.findOne(
+      { _id: req.params.userId },
+      {
+        "notices._id": 1,
+        "notices.text": 1,
+        "notices.redirect": 1,
+        "notices.isSeen": 1,
+      }
+    )
+      .lean()
+      .exec();
+
+    if (!profile) return res.status(404).json({ message: "Profile not found" });
+
+    res.data.notices = profile.notices;
+
+    next();
+  } catch (err) {
+    next(err);
+  }
+};
+
+export default getUserNotices;
diff --git a/src/middlewares/user/notice/markNoticeAsSeen.ts b/src/middlewares/user/notice/markNoticeAsSeen.ts
new file mode 100644
index 0000000000000000000000000000000000000000..fd322d0700bbd27e1f4c29ac7c22daa1941f89a6
--- /dev/null
+++ b/src/middlewares/user/notice/markNoticeAsSeen.ts
@@ -0,0 +1,24 @@
+import { NextFunction, Request, Response } from "express";
+
+import Profile from "../../../models/ProfileSchema";
+
+const markNoticeAsSeen = () => async (
+  req: Request,
+  res: Response,
+  next: NextFunction
+) => {
+  try {
+    await Profile.updateOne(
+      { _id: req.params.userId, "notices._id": req.params.noticeId },
+      { $set: { "notices.$.isSeen": true } }
+    )
+      .lean()
+      .exec();
+
+    next();
+  } catch (err) {
+    next(err);
+  }
+};
+
+export default markNoticeAsSeen;
diff --git a/src/middlewares/user/notice/responseNoticesList.ts b/src/middlewares/user/notice/responseNoticesList.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8de13450e82105d84dd619d73b5fbf96342552aa
--- /dev/null
+++ b/src/middlewares/user/notice/responseNoticesList.ts
@@ -0,0 +1,7 @@
+import { Request, Response } from "express";
+
+const responseNoticesList = () => (req: Request, res: Response) => {
+  res.json(res.data.notices || []);
+};
+
+export default responseNoticesList;
diff --git a/src/middlewares/user/notice/responseNoticesNum.ts b/src/middlewares/user/notice/responseNoticesNum.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e052ef2c1bc1c178d7ec1916648f43f2c3f6b334
--- /dev/null
+++ b/src/middlewares/user/notice/responseNoticesNum.ts
@@ -0,0 +1,7 @@
+import { Request, Response } from "express";
+
+const responseNoticesNum = () => (req: Request, res: Response) => {
+  res.json({ noticesNum: res.data.number || 0 });
+};
+
+export default responseNoticesNum;
diff --git a/src/middlewares/user/addUser.ts b/src/middlewares/user/registerOwnUser.ts
similarity index 52%
rename from src/middlewares/user/addUser.ts
rename to src/middlewares/user/registerOwnUser.ts
index a70507a722f7225b9a22288e498306aed43356c8..a69bb43db10c504019294bb3ca4bc4ec4abcaf33 100644
--- a/src/middlewares/user/addUser.ts
+++ b/src/middlewares/user/registerOwnUser.ts
@@ -1,32 +1,19 @@
 import { NextFunction, Request, Response } from "express";
-import Profile, { IProfile, Role } from "../../models/ProfileSchema";
 
+import Profile from "../../models/ProfileSchema";
 import { validateFields } from "../utils/validateFields";
 
 const fields = [
   { name: "studentCardNumber", required: true },
   { name: "roomNumber", required: true },
-  { name: "picture", required: false },
 ];
 
-/**
- * Middleware to create own User if doesn't exist
- * and set res.data.profile to it
- */
-const addUser = () => async (
+const registerOwnUser = () => async (
   req: Request,
   res: Response,
   next: NextFunction
 ) => {
   try {
-    // Already registered
-    if (req.session?.user?.id) {
-      res.data.profile = await Profile.findById(req.session.user.id)
-        .lean()
-        .exec();
-      return next();
-    }
-
     // Register
     const newProfile = new Profile();
 
@@ -37,18 +24,19 @@ const addUser = () => async (
       if (value) newProfile.set(field.name, req.body[field.name]);
     });
 
-    newProfile.external_id = req.session!.user!.external_id;
-    newProfile.email = String(req.session?.user?.email);
-    newProfile.name = String(req.session?.user?.name);
+    newProfile.externalId = req.session.user!.externalId;
+    newProfile.email = String(req.session.user!.email);
+    newProfile.name = String(req.session.user!.name);
 
     await newProfile.save();
 
-    res.data.profile = newProfile;
+    res.data.newObjectId = newProfile._id;
     req.session!.user!.id = newProfile._id;
+    req.session!.user!.role = newProfile.role;
     next();
   } catch (err) {
     next(err);
   }
 };
 
-export default addUser;
+export default registerOwnUser;
diff --git a/src/middlewares/user/rejectPicture.ts b/src/middlewares/user/rejectPicture.ts
new file mode 100644
index 0000000000000000000000000000000000000000..606161f1a876dd8096bad408823f8600d7ad3d0a
--- /dev/null
+++ b/src/middlewares/user/rejectPicture.ts
@@ -0,0 +1,30 @@
+import { NextFunction, Request, Response } from "express";
+
+import Profile from "../../models/ProfileSchema";
+
+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/responseUser.ts b/src/middlewares/user/responseUser.ts
index 7df3e826930cc39fc6090cfcbc55d8bc4b63a416..0cb05e5ec04cf3a05bf8ece9d0b071be01d3f650 100644
--- a/src/middlewares/user/responseUser.ts
+++ b/src/middlewares/user/responseUser.ts
@@ -1,8 +1,5 @@
-import { NextFunction, Request, Response, response } from "express";
+import { Request, Response } from "express";
 
-/**
- * Return the found user from res.data.profile
- */
 const responseUser = () => (req: Request, res: Response) => {
   if (!res.data.profile) {
     res.status(404).json({ message: "User not found!" });
diff --git a/src/middlewares/user/responseUserList.ts b/src/middlewares/user/responseUserList.ts
deleted file mode 100644
index cdab625ef8f214eea31704eb76152bc56dce571e..0000000000000000000000000000000000000000
--- a/src/middlewares/user/responseUserList.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import { NextFunction, Request, Response, response } from "express";
-
-/**
- * Return the found users from res.data.profiles
- */
-const responseUserList = () => (req: Request, res: Response) => {
-  res.json(res.data.profiles);
-};
-
-export default responseUserList;
diff --git a/src/middlewares/user/responseUsersList.ts b/src/middlewares/user/responseUsersList.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6e8c2b3044efba8c07adf37356cd943b8430f0c1
--- /dev/null
+++ b/src/middlewares/user/responseUsersList.ts
@@ -0,0 +1,7 @@
+import { Request, Response } from "express";
+
+const responseUsersList = () => (req: Request, res: Response) => {
+  res.json(res.data.profiles || []);
+};
+
+export default responseUsersList;
diff --git a/src/middlewares/user/setOwnUserId.ts b/src/middlewares/user/setOwnUserId.ts
index 160663fc53881f399acb1f85b42523665a539030..ef20e229305b6a322d6575ece2f5c378b25e8731 100644
--- a/src/middlewares/user/setOwnUserId.ts
+++ b/src/middlewares/user/setOwnUserId.ts
@@ -1,19 +1,11 @@
 import { NextFunction, Request, Response } from "express";
-import Profile, { IProfile } from "../../models/ProfileSchema";
 
-import { IWarning } from "../../models/WarningSchema";
-import Warning from "../../models/WarningSchema";
-
-/**
- * Middleware to set req.params.id to the current users id.
- * getUser() middleware should be called after this.
- */
 const setOwnUserId = () => (
   req: Request,
   res: Response,
   next: NextFunction
 ) => {
-  req.params.id = req.session.user!.id!;
+  req.params.userId = req.session.user!.id!;
   next();
 };
 export default setOwnUserId;
diff --git a/src/middlewares/user/updateUser.ts b/src/middlewares/user/updateUser.ts
index d0c8d98048778f3e746e2f66fd9a065465165706..ff146d905d15a3e272a6dafdea9a6351f71f8834 100644
--- a/src/middlewares/user/updateUser.ts
+++ b/src/middlewares/user/updateUser.ts
@@ -1,29 +1,25 @@
 import { NextFunction, Request, Response } from "express";
+import Profile, { IProfile } from "../../models/ProfileSchema";
 
-import Profile from "../../models/ProfileSchema";
-
-// Valid fields to update
-const validFields = ["studentCardNumber", "roomNumber", "picture"];
-
-/**
- * Update a user
- */
-const updateUser = () => async (
+const updateUser = (fields: Partial<keyof IProfile>[]) => async (
   req: Request,
   res: Response,
   next: NextFunction
 ) => {
   try {
-    const profile = await Profile.findById(req.params.id).exec();
+    let newFields: Partial<IProfile> = {};
+    fields.forEach((field) => {
+      const value = req.body[field];
+      if (value) newFields[field] = value;
+    });
 
-    if (profile) {
-      validFields.forEach((field) => {
-        const value = req.body[field];
-        if (value) profile.set(field, value);
-      });
-      await profile.save();
-    }
-    res.data.profile = profile;
+    await Profile.updateOne(
+      { _id: req.params.userId },
+      { $set: newFields },
+      { upsert: true, runValidators: true }
+    )
+      .lean()
+      .exec();
 
     next();
   } catch (err) {
diff --git a/src/middlewares/user/userIsStaff.ts b/src/middlewares/user/userIsStaff.ts
new file mode 100644
index 0000000000000000000000000000000000000000..fd730d7b30b49007145dfa262d4066ad3430bb54
--- /dev/null
+++ b/src/middlewares/user/userIsStaff.ts
@@ -0,0 +1,18 @@
+import { NextFunction, Request, Response } from "express";
+
+const userIsStaff = () => async (
+  req: Request,
+  res: Response,
+  next: NextFunction
+) => {
+  try {
+    if (!res.data.profile!.isStaffMember)
+      return res.status(400).json({ message: "User is not a staff member!" });
+
+    next();
+  } catch (err) {
+    next(err);
+  }
+};
+
+export default userIsStaff;
diff --git a/src/middlewares/user/warning/addWarning.ts b/src/middlewares/user/warning/addWarning.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a9b9858995a8963cbf931daf6129318593ccbf62
--- /dev/null
+++ b/src/middlewares/user/warning/addWarning.ts
@@ -0,0 +1,34 @@
+import { NextFunction, Request, Response } from "express";
+import Profile, { IWarning } from "../../../models/ProfileSchema";
+
+import { Types } from "mongoose";
+import { validateFields } from "../../utils/validateFields";
+
+const addWarning = (
+  fields: { name: Partial<keyof IWarning>; required: boolean }[]
+) => async (req: Request, res: Response, next: NextFunction) => {
+  try {
+    validateFields({ fields, reqBody: req.body });
+
+    const warning: IWarning = {
+      text: req.body.text,
+      date: new Date(),
+      givenBy: String(req.session.user!.id),
+      _id: String(new Types.ObjectId()),
+    };
+
+    await Profile.updateOne(
+      { _id: req.params.userId },
+      { $push: { warnings: warning } },
+      { runValidators: true }
+    )
+      .lean()
+      .exec();
+
+    next();
+  } catch (err) {
+    next(err);
+  }
+};
+
+export default addWarning;
diff --git a/src/middlewares/warning/deleteWarning.ts b/src/middlewares/user/warning/deleteWarning.ts
similarity index 51%
rename from src/middlewares/warning/deleteWarning.ts
rename to src/middlewares/user/warning/deleteWarning.ts
index 6d1b633809db11a55a779f8fa2d95c7291a942fe..49d613be180ce61b21359803aa522f279b89c54f 100644
--- a/src/middlewares/warning/deleteWarning.ts
+++ b/src/middlewares/user/warning/deleteWarning.ts
@@ -1,7 +1,6 @@
 import { NextFunction, Request, Response } from "express";
 
-import Profile from "../../models/ProfileSchema";
-import Warning from "../../models/WarningSchema";
+import Profile from "../../../models/ProfileSchema";
 
 const deleteWarning = () => async (
   req: Request,
@@ -9,12 +8,13 @@ const deleteWarning = () => async (
   next: NextFunction
 ) => {
   try {
-    const warning = await Warning.findByIdAndRemove(req.params.warningId);
-
     await Profile.updateOne(
-      { _id: warning?.receiver },
-      { $pull: { warningIds: warning?._id } }
-    );
+      { _id: req.params.userId },
+      { $pull: { warnings: { _id: req.params.warningId } } }
+    )
+      .lean()
+      .exec();
+
     next();
   } catch (err) {
     next(err);
diff --git a/src/middlewares/user/warning/getUserWarningsList.ts b/src/middlewares/user/warning/getUserWarningsList.ts
new file mode 100644
index 0000000000000000000000000000000000000000..80945dc68920ecc13b49a70d1a08fcccacbbf4a2
--- /dev/null
+++ b/src/middlewares/user/warning/getUserWarningsList.ts
@@ -0,0 +1,32 @@
+import { NextFunction, Request, Response } from "express";
+
+import Profile from "../../../models/ProfileSchema";
+
+const getUserWarnings = () => async (
+  req: Request,
+  res: Response,
+  next: NextFunction
+) => {
+  try {
+    const profile = await Profile.findOne(
+      { _id: req.params.userId },
+      {
+        "warnings._id": 1,
+        "warnings.text": 1,
+        "warnings.date": 1,
+      }
+    )
+      .lean()
+      .exec();
+
+    if (!profile) return res.status(404).json({ message: "Profile not found" });
+
+    res.data.warnings = profile.warnings;
+
+    next();
+  } catch (err) {
+    next(err);
+  }
+};
+
+export default getUserWarnings;
diff --git a/src/middlewares/user/warning/responseWarningsList.ts b/src/middlewares/user/warning/responseWarningsList.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0fad27db1b1b8ea6432f55b1b5b0badbcdb303d8
--- /dev/null
+++ b/src/middlewares/user/warning/responseWarningsList.ts
@@ -0,0 +1,7 @@
+import { Request, Response } from "express";
+
+const responseWarningsList = () => (req: Request, res: Response) => {
+  res.json(res.data.warnings || []);
+};
+
+export default responseWarningsList;
diff --git a/src/middlewares/user/warning/updateWarning.ts b/src/middlewares/user/warning/updateWarning.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b75286acfb753ab86e7913c362c9d007c70bfd10
--- /dev/null
+++ b/src/middlewares/user/warning/updateWarning.ts
@@ -0,0 +1,30 @@
+import { NextFunction, Request, Response } from "express";
+import Profile, { IWarning } from "../../../models/ProfileSchema";
+
+const updateWarning = (fields: Partial<keyof IWarning>[]) => async (
+  req: Request,
+  res: Response,
+  next: NextFunction
+) => {
+  try {
+    let newFields: Partial<any> = {};
+    fields.forEach((field) => {
+      const value = req.body[field];
+      if (value) newFields["warnings.$." + field] = value;
+    });
+
+    await Profile.updateOne(
+      { _id: req.params.userId, "warnings._id": req.params.warningId },
+      { $set: newFields },
+      { runValidators: true }
+    )
+      .lean()
+      .exec();
+
+    next();
+  } catch (err) {
+    next(err);
+  }
+};
+
+export default updateWarning;
diff --git a/src/middlewares/utils/createdEmptyResponse.ts b/src/middlewares/utils/createdEmptyResponse.ts
new file mode 100644
index 0000000000000000000000000000000000000000..13cf0f4829696ff44fdea75466742d8daa7d934f
--- /dev/null
+++ b/src/middlewares/utils/createdEmptyResponse.ts
@@ -0,0 +1,7 @@
+import { Request, Response } from "express";
+
+const createdEmptyResponse = () => (req: Request, res: Response) => {
+  res.status(201).json({});
+};
+
+export default createdEmptyResponse;
diff --git a/src/middlewares/utils/createdResponse.ts b/src/middlewares/utils/createdResponse.ts
new file mode 100644
index 0000000000000000000000000000000000000000..88c19ebb150c3eef40cb6c69054762ba9fbfd64c
--- /dev/null
+++ b/src/middlewares/utils/createdResponse.ts
@@ -0,0 +1,7 @@
+import { Request, Response } from "express";
+
+const createdResponse = () => (req: Request, res: Response) => {
+  res.status(201).json({ _id: res.data.newObjectId });
+};
+
+export default createdResponse;
diff --git a/src/middlewares/utils/emptyResponse.ts b/src/middlewares/utils/emptyResponse.ts
deleted file mode 100644
index 73508b7e4b90888ce05ebca11ca2c16aba63aa69..0000000000000000000000000000000000000000
--- a/src/middlewares/utils/emptyResponse.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import { Request, Response } from "express";
-
-/**
- * Empty response
- */
-const emptyResponse = () => (req: Request, res: Response) => res.json({});
-
-export default emptyResponse;
diff --git a/src/middlewares/utils/getFieldValue.ts b/src/middlewares/utils/getFieldValue.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d2e90a765a768d5731db88cc3e3077e8b3366d40
--- /dev/null
+++ b/src/middlewares/utils/getFieldValue.ts
@@ -0,0 +1,19 @@
+import { NextFunction, Request, Response } from "express";
+
+const getFieldValue = (
+  objectName: "profile" | "term",
+  fieldName: "newPicture" | "acceptedPicture" | "backgroundFile"
+) => async (req: Request, res: Response, next: NextFunction) => {
+  try {
+    const object: Record<string, any> = res.data[objectName]!;
+    if (object) {
+      res.data.value = object[fieldName];
+    }
+
+    next();
+  } catch (err) {
+    next(err);
+  }
+};
+
+export default getFieldValue;
diff --git a/src/middlewares/utils/noContentResponse.ts b/src/middlewares/utils/noContentResponse.ts
new file mode 100644
index 0000000000000000000000000000000000000000..091a60442a3d31d0e1a05a8121420b5f3f6310f2
--- /dev/null
+++ b/src/middlewares/utils/noContentResponse.ts
@@ -0,0 +1,6 @@
+import { Request, Response } from "express";
+
+const noContentResponse = () => (req: Request, res: Response) =>
+  res.status(204).send();
+
+export default noContentResponse;
diff --git a/src/middlewares/warning/addWarning.ts b/src/middlewares/warning/addWarning.ts
deleted file mode 100644
index 58704d6448ce99b52b25be255b080069e39e3d4d..0000000000000000000000000000000000000000
--- a/src/middlewares/warning/addWarning.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-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/warning";
-
-const fields = [{ name: "text", required: true }];
-
-const addWarning = () => async (
-  req: Request,
-  res: Response,
-  next: NextFunction
-) => {
-  try {
-    const warningReceiver = await Profile.findById(req.params.id).exec();
-    if (!warningReceiver) throw new ErrorHandler(404, "User not found!");
-
-    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]);
-    });
-
-    warning.receiver = warningReceiver._id!;
-    warning.date = new Date();
-    warning.given_by = {
-      _id: req.session.user!.id!,
-      name: req.session.user!.name!,
-    };
-
-    await warning.save();
-
-    warningReceiver.warningIds = [
-      ...warningReceiver.warningIds,
-      String(warning._id),
-    ];
-    await warningReceiver.save(async (err) => {
-      if (err) {
-        await warning.remove();
-        throw err;
-      }
-    });
-    res.data.warning = warning;
-    next();
-  } catch (err) {
-    next(err);
-  }
-};
-
-export default addWarning;
diff --git a/src/middlewares/warning/getUserWarningsList.ts b/src/middlewares/warning/getUserWarningsList.ts
deleted file mode 100644
index fdca929ffa57433b1b8dd779184e3e9baf1fdc27..0000000000000000000000000000000000000000
--- a/src/middlewares/warning/getUserWarningsList.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import { NextFunction, Request, Response } from "express";
-
-import Profile from "../../models/ProfileSchema";
-import Warning from "../../models/WarningSchema";
-
-const getUserWarningsList = () => async (
-  req: Request,
-  res: Response,
-  next: NextFunction
-) => {
-  try {
-    if (!res.data.profile)
-      return res.status(404).json({ message: "User not found" });
-
-    res.data.warnings = await Warning.find({
-      _id: { $in: res.data.profile?.warningIds },
-    });
-
-    next();
-  } catch (err) {
-    next(err);
-  }
-};
-
-export default getUserWarningsList;
diff --git a/src/middlewares/warning/getWarning.ts b/src/middlewares/warning/getWarning.ts
deleted file mode 100644
index f1d59c34f7a3262c0127d6efbdf4beea624cb95c..0000000000000000000000000000000000000000
--- a/src/middlewares/warning/getWarning.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-import { NextFunction, Request, Response } from "express";
-
-import Warning from "../../models/WarningSchema";
-
-const getWarning = () => async (
-  req: Request,
-  res: Response,
-  next: NextFunction
-) => {
-  try {
-    res.data.warning = await Warning.findById(req.params.warningId)
-      .lean()
-      .exec();
-    next();
-  } catch (err) {
-    next(err);
-  }
-};
-
-export default getWarning;
diff --git a/src/middlewares/warning/responseWarning.ts b/src/middlewares/warning/responseWarning.ts
deleted file mode 100644
index e4bbb7c0343081e4e4323188705a2a997df889b7..0000000000000000000000000000000000000000
--- a/src/middlewares/warning/responseWarning.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import { NextFunction, Request, Response, response } from "express";
-
-const responseWarning = () => (req: Request, res: Response) => {
-  if (!res.data.warning) {
-    return res.status(404).json({ message: "Warning not found!" });
-  }
-  res.json(res.data.warning);
-};
-
-export default responseWarning;
diff --git a/src/middlewares/warning/responseWarningList.ts b/src/middlewares/warning/responseWarningList.ts
deleted file mode 100644
index 432a60a5577704941c63ac23436ca8c6f3e13b85..0000000000000000000000000000000000000000
--- a/src/middlewares/warning/responseWarningList.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { NextFunction, Request, Response, response } from "express";
-
-const responseWarningList = () => (req: Request, res: Response) => {
-  return res.json(res.data.warnings);
-};
-
-export default responseWarningList;
diff --git a/src/middlewares/warning/updateWarning.ts b/src/middlewares/warning/updateWarning.ts
deleted file mode 100644
index 5d819d499181577bc6fd9ed73928bd4b1e6cf9f8..0000000000000000000000000000000000000000
--- a/src/middlewares/warning/updateWarning.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-import { NextFunction, Request, Response } from "express";
-
-import Warning from "../../models/WarningSchema";
-
-// Valid fields to update
-const validFields = ["text"];
-
-const updateWarning = () => async (
-  req: Request,
-  res: Response,
-  next: NextFunction
-) => {
-  try {
-    const warning = await Warning.findById(req.params.warnmingId).exec();
-
-    if (warning) {
-      validFields.forEach((field) => {
-        const value = req.body[field];
-        if (value) warning.set(field, value);
-      });
-      await warning.save();
-    }
-    res.data.warning = warning;
-
-    next();
-  } catch (err) {
-    next(err);
-  }
-};
-
-export default updateWarning;
diff --git a/src/models/ApplicantSchema.ts b/src/models/ApplicantSchema.ts
deleted file mode 100644
index 98395cfd521d8183ffb7d24b689d6945f7fb9eda..0000000000000000000000000000000000000000
--- a/src/models/ApplicantSchema.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import { Document, Schema, model } from "mongoose";
-import { IProfile } from "./ProfileSchema";
-
-export enum CardStatus {
-  Requested,
-  Printed,
-  Received,
-}
-
-export interface IApplicant extends Document {
-  cardStatus: CardStatus;
-  profile: {
-    name: string;
-    id: IProfile["_id"];
-  };
-}
-
-const ApplicationSchema = new Schema({
-  cardStatus: { type: String, required: true },
-  profile: {
-    id: { type: Schema.Types.ObjectId, required: true },
-    name: { type: String, required: true },
-  },
-});
-
-export default model<IApplicant>("Applicant", ApplicationSchema);
diff --git a/src/models/ApplicationPeriodSchema.ts b/src/models/ApplicationPeriodSchema.ts
deleted file mode 100644
index ce974cbabdd47d5a10436312ffa5e79086268c53..0000000000000000000000000000000000000000
--- a/src/models/ApplicationPeriodSchema.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import { Document, Schema, model } from "mongoose";
-import ApplicantSchema, { IApplicant } from "./ApplicantSchema";
-
-export interface IApplicationPeriod extends Document {
-  startAt: Date;
-  endAt: Date;
-  deadline: Date;
-  name: string;
-  applicants: IApplicant[];
-}
-
-const ApplicationPeriodSchema = new Schema({
-  startedAt: { type: Date, required: true },
-  endAt: { type: Date, required: true },
-  deadline: { type: Date, required: true },
-  name: { type: String, required: true },
-  applicants: [ApplicantSchema],
-});
-
-export default model<IApplicationPeriod>(
-  "Application period",
-  ApplicationPeriodSchema
-);
diff --git a/src/models/CardImageSchema.ts b/src/models/CardImageSchema.ts
deleted file mode 100644
index 17bfdb35a20d76ee72e7e4beea1b0d6d68b65071..0000000000000000000000000000000000000000
--- a/src/models/CardImageSchema.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import { Document, Schema, model } from "mongoose";
-
-export interface ICardImage extends Document {
-  imageId: String;
-}
-
-const CardImageSchema = new Schema({
-  imageId: { type: Schema.Types.ObjectId, ref: "File", required: true },
-});
-
-export default model<ICardImage>("CardImage", CardImageSchema);
diff --git a/src/models/CardSchema.ts b/src/models/CardSchema.ts
deleted file mode 100644
index aaec08da2909f654b739b7a4909a3d873f7abe1f..0000000000000000000000000000000000000000
--- a/src/models/CardSchema.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import CounterSchema, { ICounter } from "./CounterSchema";
-import { Document, Schema, model } from "mongoose";
-
-import ProfileSchema from "./ProfileSchema";
-
-export interface ICard extends Document {
-  userId: string;
-  fullName: string;
-  roomNumber: Number;
-  cardId: Number;
-  createDate: Date;
-  expirationDate: Date;
-  isTaken: boolean;
-}
-
-const CardSchema = new Schema({
-  userId: { type: Schema.Types.ObjectId, ref: "User" },
-  fullName: { type: String, required: true },
-  roomNumber: { type: Number, required: true },
-  cardId: { type: Number },
-  createDate: { type: Date, required: true, default: new Date() },
-  expirationDate: { type: Date, required: true },
-  isTaken: { type: Boolean, required: true, default: false },
-});
-
-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<ICard>("Card", CardSchema);
diff --git a/src/models/FileSchema.ts b/src/models/FileSchema.ts
index fa6679432e7e646cfbd5a2eeab62514ef56ff892..268514c62f9c86758e653e11a99cf5573d7562d3 100644
--- a/src/models/FileSchema.ts
+++ b/src/models/FileSchema.ts
@@ -3,7 +3,6 @@ import { Document, Schema, model } from "mongoose";
 export interface IFile extends Document {
   path: string;
   originalName: string;
-  encoding: string;
   mimeType: string;
   uploadDate: Date;
 }
diff --git a/src/models/NewsSchema.ts b/src/models/NewsSchema.ts
index e82064d5e6817af472547b8b25a518b3bf285f5f..72d32c23ea500a05c3402f1dc2426a2b7c9a6419 100644
--- a/src/models/NewsSchema.ts
+++ b/src/models/NewsSchema.ts
@@ -4,12 +4,16 @@ export interface INews extends Document {
   title: string;
   text: string;
   publishedAt: Date;
+  publishedBy: string;
+  updatedBy?: string;
 }
 
 const NewsSchema = new Schema({
   title: { type: String, required: true },
   text: { type: String, required: true },
   publishedAt: { type: Date, required: true },
+  publishedBy: { type: Schema.Types.ObjectId, ref: "Profile", required: true },
+  updatedBy: { type: Schema.Types.ObjectId, ref: "Profile", required: false },
 });
 
 export default model<INews>("News", NewsSchema);
diff --git a/src/models/ProfileSchema.ts b/src/models/ProfileSchema.ts
index e01b02d010952d14475116aa0d02ef42bdb72a80..011a4a4d7b203dcbac12c70f2c4a7bc8c976ae61 100644
--- a/src/models/ProfileSchema.ts
+++ b/src/models/ProfileSchema.ts
@@ -1,41 +1,76 @@
 import { Document, Schema, model } from "mongoose";
-import { IWarning, WarningSchema } from "./WarningSchema";
-
-import { Admin } from "mongodb";
 
 export enum Role {
-  Admin,
-  Staff,
-  User,
+  Admin = "ADMIN",
+  User = "USER",
+}
+
+export interface INotice {
+  _id: string;
+  text: string;
+  redirect?: string;
+  isSeen: boolean;
+}
+
+export interface IWarning {
+  _id: string;
+  text: string;
+  date: Date;
+  givenBy: string;
 }
 
 export interface IProfile extends Document {
-  external_id: string;
-  studentCardNumber: string;
-  roomNumber: Number;
-  pictureId: string;
+  externalId: string;
+  studentCardNumber?: string;
+  roomNumber?: Number;
+  newPicture?: string;
+  acceptedPicture?: string;
   role: Role;
   email: string;
   name: string;
-  warningIds: string[] | [];
+  isStaffMember?: boolean;
+  staffMemberText?: string;
+  warnings: IWarning[];
+  notices: INotice[];
 }
 
 const ProfileSchema = new Schema({
-  external_id: { type: String, required: true, unique: true, dropDups: true },
+  externalId: { type: String, required: true, unique: true, dropDups: true },
   studentCardNumber: { type: String, required: false },
-  roomNumber: { type: Number },
-  pictureId: { type: Schema.Types.ObjectId, ref: "File", required: false },
+  roomNumber: { type: Number, required: false },
+  newPicture: { type: Schema.Types.ObjectId, ref: "File", required: false },
+  acceptedPicture: {
+    type: Schema.Types.ObjectId,
+    ref: "File",
+    required: false,
+  },
   role: {
     type: String,
-    enum: Object.keys(Role).map((k) => Role[k as any]),
+    enum: Object.keys(Role).map((k) => Role[k as keyof typeof Role]),
     required: true,
     default: Role.User,
   },
   email: { type: String, required: true },
   name: { type: String, required: true },
-  warningIds: [
-    { type: Schema.Types.ObjectId, ref: "Warning", required: false },
+  isStaffMember: { type: Boolean, required: false, default: false },
+  staffMemberText: { type: String, required: false },
+  notices: [
+    {
+      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 },
+    },
   ],
 });
 
-export default model<IProfile>("Profile", ProfileSchema);
+export default model<IProfile & { noticesNum: number }>(
+  "Profile",
+  ProfileSchema
+);
diff --git a/src/models/TermSchema.ts b/src/models/TermSchema.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a71858c11aab39933ac98eb2ee9679d5547c33e0
--- /dev/null
+++ b/src/models/TermSchema.ts
@@ -0,0 +1,65 @@
+import { Document, Schema, model } from "mongoose";
+
+export enum MemberState {
+  Accepted = "ACCEPTED",
+  Applied = "APPLIED",
+  Rejected = "REJECTED",
+}
+
+export enum CardState {
+  Created = "CREATED",
+  Printed = "PRINTD",
+  Given = "GIVEN",
+}
+
+export interface IMember {
+  user: string;
+  memberState: MemberState;
+  cardState: CardState;
+  cardNumber: number;
+  cardReceiveDate?: Date;
+}
+
+export interface ITerm extends Document {
+  backgroundFile?: string;
+  name: string;
+  createDate?: Date;
+  startDate: Date;
+  endDate: Date;
+  deadline: Date;
+  members: IMember[];
+}
+
+const TermSchema = new Schema({
+  backgroundFile: { type: Schema.Types.ObjectId, ref: "File", required: false },
+  name: { type: String, required: true },
+  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 },
+      memberState: {
+        type: String,
+        enum: Object.keys(MemberState).map(
+          (k) => MemberState[k as keyof typeof MemberState]
+        ),
+        required: true,
+        default: MemberState.Applied,
+      },
+      cardState: {
+        type: String,
+        enum: Object.keys(CardState).map(
+          (k) => CardState[k as keyof typeof CardState]
+        ),
+        required: true,
+        default: CardState.Created,
+      },
+      cardNumber: { type: Number, required: true },
+      cardReceiveDate: { type: Date, required: false },
+    },
+  ],
+});
+
+export default model<ITerm>("Term", TermSchema);
diff --git a/src/models/WarningSchema.ts b/src/models/WarningSchema.ts
deleted file mode 100644
index 61dfef1c0a6ec1b8a562afd0e33550c8e852edbd..0000000000000000000000000000000000000000
--- 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;
-  given_by: {
-    _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 },
-  given_by: {
-    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/models/user.interface.ts b/src/models/user.interface.ts
index 1ec9320854428325a3fde3455b3891aa152ed57b..2981e326b9dde5134f7c6c93f1ef60dd0e14cf50 100644
--- a/src/models/user.interface.ts
+++ b/src/models/user.interface.ts
@@ -1,9 +1,11 @@
+import { Role } from "./ProfileSchema";
 import { Token } from "simple-oauth2";
 
 export interface User {
   email: string;
   name: string;
   id?: string;
-  external_id: string;
+  externalId: string;
   token: Token;
+  role?: Role;
 }
diff --git a/src/routes/auth.ts b/src/routes/auth.ts
index 1202f644070fe274bffa1637f1ce052217406781..f05d3027b540d058e570d96ec6879604bed99baf 100644
--- a/src/routes/auth.ts
+++ b/src/routes/auth.ts
@@ -1,16 +1,15 @@
 import { Application } from "express";
 import complete from "../middlewares/auth/complete";
-import isAuthenticated from "../middlewares/auth/isAuthenticated";
 import isLoggedIn from "../middlewares/auth/isLoggedIn";
 import login from "../middlewares/auth/login";
 import logout from "../middlewares/auth/logout";
 
-const authRoute = (app: Application): void => {
-  app.get("/api/v1/login", login());
+const authRoute = (prefix: string, app: Application): void => {
+  app.get(`${prefix}/login`, login());
 
-  app.get("/api/v1/complete", complete());
+  app.get(`${prefix}/complete`, complete());
 
-  app.get("/api/v1/logout", isLoggedIn(), logout());
+  app.get(`${prefix}/logout`, isLoggedIn(), logout());
 };
 
 export default authRoute;
diff --git a/src/routes/card.ts b/src/routes/card.ts
deleted file mode 100644
index 5532d735ba013e921b8b2e0c5b7ca963e261e9fa..0000000000000000000000000000000000000000
--- a/src/routes/card.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import { Application } from "express";
-import addCard from "../middlewares/cards/addCard";
-import getCard from "../middlewares/cards/getCard";
-import getCardList from "../middlewares/cards/getCardList";
-import getCardListValid from "../middlewares/cards/getCardListValid";
-import isAuthenticated from "../middlewares/auth/isAuthenticated";
-import responseCard from "../middlewares/cards/responseCard";
-import responseCardList from "../middlewares/cards/responseCardList";
-
-const cardRoute = (app: Application): void => {
-  app.get("/api/v1/card/:id", isAuthenticated(), getCard(), responseCard());
-
-  app.get(
-    "/api/v1/cards",
-    isAuthenticated(),
-    getCardList(),
-    responseCardList()
-  );
-
-  app.get(
-    "/api/v1/cards/valid",
-    isAuthenticated(),
-    getCardListValid(),
-    responseCardList()
-  );
-
-  app.post("/api/v1/cards", isAuthenticated(), addCard(), responseCard());
-};
-
-export default cardRoute;
diff --git a/src/routes/file.ts b/src/routes/file.ts
deleted file mode 100644
index 720de10bb00cf6f8dbb837870fd3a98207afc9d9..0000000000000000000000000000000000000000
--- a/src/routes/file.ts
+++ /dev/null
@@ -1,67 +0,0 @@
-import { Application } from "express";
-import cardImageStorage from "../middlewares/files/card/cardImageStorage";
-import { fileFilter } from "../middlewares/files/fileFilter";
-import getCardImage from "../middlewares/files/card/getCardImage";
-import getProfilePicture from "../middlewares/files/profile/getProfilePicture";
-import getUser from "../middlewares/user/getUser";
-import handleFileValidationError from "../middlewares/files/handleFileValidationError";
-import isAuthenticated from "../middlewares/auth/isAuthenticated";
-import multer from "multer";
-import profilePictureStorage from "../middlewares/files/profile/profilePictureStorage";
-import responseCardImage from "../middlewares/files/card/responseCardImage";
-import setOwnUserId from "../middlewares/user/setOwnUserId";
-import uploadCardImage from "../middlewares/files/card/uploadCardImage";
-import uploadProfilePicture from "../middlewares/files/profile/uploadProfilePicture";
-
-const profilePictureUpload = multer({
-  storage: profilePictureStorage,
-  fileFilter,
-});
-
-const CardImageUpload = multer({
-  storage: cardImageStorage,
-  fileFilter,
-});
-
-const fileRoute = (app: Application): void => {
-  app.post(
-    "/api/v1/files/profile/picture/me",
-    isAuthenticated(),
-    profilePictureUpload.single("profile_picture"),
-    handleFileValidationError(),
-    setOwnUserId(),
-    getUser(),
-    uploadProfilePicture()
-  );
-  app.post(
-    "/api/v1/files/profile/picture/:id",
-    isAuthenticated(),
-    profilePictureUpload.single("profile_picture"),
-    handleFileValidationError(),
-    getUser(),
-    uploadProfilePicture()
-  );
-  app.get(
-    "/api/v1/files/profile",
-    isAuthenticated(),
-    setOwnUserId(),
-    getUser(),
-    getProfilePicture()
-  );
-
-  app.post(
-    "/api/v1/files/card",
-    isAuthenticated(),
-    CardImageUpload.single("card_image"),
-    handleFileValidationError(),
-    uploadCardImage()
-  );
-  app.get(
-    "/api/v1/files/card",
-    isAuthenticated(),
-    getCardImage(),
-    responseCardImage()
-  );
-};
-
-export default fileRoute;
diff --git a/src/routes/files.ts b/src/routes/files.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3083e6f7133c77bd0bd1a4d8de6229a2d0d90948
--- /dev/null
+++ b/src/routes/files.ts
@@ -0,0 +1,155 @@
+import { Application } from "express";
+import createFile from "../middlewares/files/createFile";
+import createdResponse from "../middlewares/utils/createdResponse";
+import getFieldValue from "../middlewares/utils/getFieldValue";
+import getTerm from "../middlewares/term/getTerm";
+import getTermWithQuery from "../middlewares/term/getTermImage";
+import getUser from "../middlewares/user/getUser";
+import { imageFilter } from "../middlewares/files/imageFilter";
+import { imageStorage } from "../middlewares/files/imageStorage";
+import isAdmin from "../middlewares/auth/isAdmin";
+import isRegistered from "../middlewares/auth/isRegistered";
+import multer from "multer";
+import sendFile from "../middlewares/files/sendFile";
+import sendUserCard from "../middlewares/files/sendUserCard";
+import setOwnUserId from "../middlewares/user/setOwnUserId";
+import updateProfilePicture from "../middlewares/files/updateProfilePicture";
+import updateTermCardBg from "../middlewares/files/updateTermCardBg";
+import userIsStaff from "../middlewares/user/userIsStaff";
+
+const profilePictureUpload = multer({
+  storage: imageStorage("uploads/profile_pictures/"),
+  fileFilter: imageFilter,
+});
+
+const CardImageUpload = multer({
+  storage: imageStorage("uploads/card_image/"),
+  fileFilter: imageFilter,
+});
+
+// TODO in Future: OwnTermCardPreview(termId)
+
+const filesRoute = (prefix: string, app: Application): void => {
+  /**
+   * Get Own New Profile picture
+   * Role: Normal
+   */
+  app.get(
+    `${prefix}/me/picture/new`,
+    isRegistered(),
+    setOwnUserId(),
+    getUser("_id newPicture"),
+    getFieldValue("profile", "newPicture"),
+    sendFile()
+  );
+
+  /**
+   * Upload Own New Profile picture
+   * Role: Normal
+   */
+  app.post(
+    `${prefix}/me/picture/new`,
+    isRegistered(),
+    setOwnUserId(),
+    getUser("_id newPicture"),
+    profilePictureUpload.single("profile_picture"),
+    createFile(),
+    updateProfilePicture(),
+    createdResponse()
+  );
+
+  /**
+   * Get Own Accepted Profile picture
+   * Role: Normal
+   */
+  app.get(
+    `${prefix}/me/picture/accepted`,
+    isRegistered(),
+    setOwnUserId(),
+    getUser("_id acceptedPicture"),
+    getFieldValue("profile", "acceptedPicture"),
+    sendFile()
+  );
+
+  /**
+   * Get a Users New Profile picture
+   * Role: Admin
+   */
+  app.get(
+    `${prefix}/user/:userId/picture/new`,
+    isRegistered(),
+    isAdmin(),
+    getUser("_id newPicture"),
+    getFieldValue("profile", "newPicture"),
+    sendFile()
+  );
+
+  /**
+   * Get a Users Accepted Profile picture
+   * Role: Admin
+   */
+  app.get(
+    `${prefix}/user/:userId/picture/accepted`,
+    isRegistered(),
+    isAdmin(),
+    getUser("_id acceptedPicture"),
+    getFieldValue("profile", "acceptedPicture"),
+    sendFile()
+  );
+
+  /**
+   * Get Staff members picture
+   * Role: Normal
+   */
+  app.get(
+    `${prefix}/staff/:userId/picture`,
+    isRegistered(),
+    getUser("_id acceptedPicture isStaffMember staffMemberText"),
+    userIsStaff(),
+    getFieldValue("profile", "acceptedPicture"),
+    sendFile()
+  );
+
+  /**
+   * Get Card SVG of User
+   * Role: Admin
+   */
+  app.get(
+    `${prefix}/term/:termId/user/:userId/card`,
+    isRegistered(),
+    isAdmin(),
+    getUser("_id acceptedPicture name roomNumber"),
+    getTerm(true),
+    sendUserCard()
+  );
+
+  /**
+   * Get Term Card Image
+   * Role: Admin
+   */
+  app.get(
+    `${prefix}/term/:termId/card`,
+    isRegistered(),
+    isAdmin(),
+    getTermWithQuery("_id backgroundFile"),
+    getFieldValue("term", "backgroundFile"),
+    sendFile()
+  );
+
+  /**
+   * Upload Term Card Image
+   * Role: Admin
+   */
+  app.post(
+    `${prefix}/term/:termId/card`,
+    isRegistered(),
+    isAdmin(),
+    getTermWithQuery("_id backgroundFile"),
+    CardImageUpload.single("card_image"),
+    createFile(),
+    updateTermCardBg(),
+    createdResponse()
+  );
+};
+
+export default filesRoute;
diff --git a/src/routes/news.ts b/src/routes/news.ts
index a5030463e4229ca6e9e845f11b6fb685dccab9fa..77fb7aa80f776b0a3e10baceb3cbc0fd3f9f75e3 100644
--- a/src/routes/news.ts
+++ b/src/routes/news.ts
@@ -1,22 +1,79 @@
-import { Application, Response } from "express";
-
+import { Application } from "express";
 import addNews from "../middlewares/news/addNews";
+import createdResponse from "../middlewares/utils/createdResponse";
 import deleteNews from "../middlewares/news/deleteNews";
-import emptyResponse from "../middlewares/utils/emptyResponse";
-import getNews from "../middlewares/news/getNews";
 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 noContentResponse from "../middlewares/utils/noContentResponse";
 import responseNews from "../middlewares/news/responseNews";
-import responseNewsObject from "../middlewares/news/responseNewsObject";
+import responseOneNews from "../middlewares/news/responseOneNews";
 import updateNews from "../middlewares/news/updateNews";
 
-export default (app: Application): void => {
-  app.get("/api/v1/news", getNewsList(), responseNews());
+const newsRoute = (prefix: string, app: Application): void => {
+  /**
+   * Get All News
+   * Role: None
+   */
+  app.get(
+    `${prefix}/`,
+    getNewsList("_id title text publishedAt"),
+    responseNews()
+  );
 
-  app.post("/api/v1/news", addNews(), responseNewsObject());
+  /**
+   * Get one News
+   * Role: Admin
+   */
+  app.get(
+    `${prefix}/one/:newsId`,
+    isRegistered(),
+    isAdmin(),
+    getOneNews("_id title text publishedAt publishedBy updatedBy"),
+    responseOneNews()
+  );
 
-  app.get("/api/v1/news/:id", getNews(), responseNewsObject());
+  /**
+   * Create one new News
+   * Role: Admin
+   */
+  app.post(
+    `${prefix}/`,
+    isRegistered(),
+    isAdmin(),
+    addNews([
+      { name: "title", required: true },
+      { name: "text", required: true },
+    ]),
+    createdResponse()
+  );
 
-  app.put("/api/v1/news/:id", getNews(), updateNews(), responseNewsObject());
+  /**
+   * Update one News
+   * Role: Admin
+   */
+  app.put(
+    `${prefix}/one/:newsId`,
+    isRegistered(),
+    isAdmin(),
+    getOneNews("_id"),
+    updateNews(["title", "text"]),
+    noContentResponse()
+  );
 
-  app.delete("/api/v1/news/:id", deleteNews(), emptyResponse());
+  /**
+   * Delete one News
+   * Role: Admin
+   */
+  app.delete(
+    `${prefix}/one/:newsId`,
+    isRegistered(),
+    isAdmin(),
+    getOneNews("_id"),
+    deleteNews(),
+    noContentResponse()
+  );
 };
+
+export default newsRoute;
diff --git a/src/routes/setErrorHandler.ts b/src/routes/setErrorHandler.ts
new file mode 100644
index 0000000000000000000000000000000000000000..00f4f36551ae47a4455ed6a0baf03a96228facec
--- /dev/null
+++ b/src/routes/setErrorHandler.ts
@@ -0,0 +1,23 @@
+import { Application, NextFunction, Request, Response } from "express";
+import { ErrorHandler, handleError } from "../middlewares/utils/ErrorHandler";
+
+import { Error as MongooseError } from "mongoose";
+import multer from "multer";
+
+const setErrorHandler = (app: Application): void => {
+  app.use((err: any, req: Request, res: Response, next: NextFunction) => {
+    if (err instanceof ErrorHandler) return handleError(err, res);
+    if (
+      err instanceof MongooseError.CastError ||
+      err instanceof MongooseError.ValidationError ||
+      err instanceof multer.MulterError
+    )
+      return handleError(new ErrorHandler(400, err.message), res);
+
+    //Flush out the stack to the console
+    console.error(err.stack);
+    res.status(500).send("Houston, we have a problem!");
+  });
+};
+
+export default setErrorHandler;
diff --git a/src/routes/setRouters.ts b/src/routes/setRouters.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e70329384931388ef7ece8534e0574a58bcd2e32
--- /dev/null
+++ b/src/routes/setRouters.ts
@@ -0,0 +1,31 @@
+import { Application } from "express";
+import authRoute from "./auth";
+import filesRoute from "./files";
+import newsRoute from "./news";
+import setErrorHandler from "./setErrorHandler";
+import termsRoute from "./terms";
+import userMembershipRoute from "./users/membership";
+import userNotificeRoute from "./users/notice";
+import userWarningsRoute from "./users/warning";
+import usersRoute from "./users/user";
+
+const prefix = "/api/v1";
+
+const setRouters = (app: Application): void => {
+  authRoute(prefix, app);
+
+  filesRoute(`${prefix}/files`, app);
+
+  newsRoute(`${prefix}/news`, app);
+
+  termsRoute(`${prefix}/terms`, app);
+
+  usersRoute(`${prefix}/users`, app);
+  userMembershipRoute(`${prefix}/users`, app);
+  userWarningsRoute(`${prefix}/users`, app);
+  userNotificeRoute(`${prefix}/users`, app);
+
+  setErrorHandler(app);
+};
+
+export default setRouters;
diff --git a/src/routes/terms.ts b/src/routes/terms.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8a22bf5ae4430688d1c3f82179b2abcfd9361f84
--- /dev/null
+++ b/src/routes/terms.ts
@@ -0,0 +1,135 @@
+import { Application } from "express";
+import addMember from "../middlewares/term/addMember";
+import addTerm from "../middlewares/term/addTerm";
+import createdEmptyResponse from "../middlewares/utils/createdEmptyResponse";
+import createdResponse from "../middlewares/utils/createdResponse";
+import deleteFile from "../middlewares/files/deleteFile";
+import deleteTerm from "../middlewares/term/deleteTerm";
+import getFieldValue from "../middlewares/utils/getFieldValue";
+import getTerm from "../middlewares/term/getTerm";
+import getTermMembers from "../middlewares/term/getTermMembers";
+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 noContentResponse from "../middlewares/utils/noContentResponse";
+import responseMembersList from "../middlewares/term/responseMembersList";
+import responseTerm from "../middlewares/term/responseTerm";
+import responseTermsList from "../middlewares/term/responseTermsList";
+import setOwnUserId from "../middlewares/user/setOwnUserId";
+import updateTerm from "../middlewares/term/updateTerm";
+import updateTermMember from "../middlewares/term/updateTermMember";
+
+const termsRoute = (prefix: string, app: Application): void => {
+  /**
+   * Get All terms
+   * Role: NORMAL
+   */
+  app.get(
+    `${prefix}/`,
+    isRegistered(),
+    setOwnUserId(),
+    getTermsList(),
+    responseTermsList()
+  );
+
+  /**
+   * Get a Term
+   * Role: NORMAL
+   */
+  app.get(
+    `${prefix}/term/:termId`,
+    isRegistered(),
+    setOwnUserId(),
+    getTerm(),
+    responseTerm()
+  );
+
+  /**
+   * Apply Own User to a Term
+   * Role: NORMAL
+   */
+  app.post(
+    `${prefix}/apply/me/term/:termId`,
+    isRegistered(),
+    setOwnUserId(),
+    getUser("_id"),
+    getTerm(),
+    isNotMember(),
+    addMember(),
+    createdEmptyResponse()
+  );
+
+  /**
+   * Get term members
+   * Role: ADMIN
+   */
+  app.get(
+    `${prefix}/term/:termId/members`,
+    isRegistered(),
+    isAdmin(),
+    getTermMembers(),
+    responseMembersList()
+  );
+
+  /**
+   * Create a Term
+   * Role: ADMIN
+   */
+  app.post(
+    `${prefix}/`,
+    isRegistered(),
+    isAdmin(),
+    addTerm([
+      { name: "name", required: true },
+      { name: "createDate", required: false },
+      { name: "startDate", required: true },
+      { name: "endDate", required: true },
+      { name: "deadline", required: true },
+    ]),
+    createdResponse()
+  );
+
+  /**
+   * Delete a Term
+   * Role: ADMIN
+   */
+  app.delete(
+    `${prefix}/term/:termId`,
+    isRegistered(),
+    isAdmin(),
+    getFieldValue("term", "backgroundFile"),
+    deleteFile(),
+    deleteTerm(),
+    noContentResponse()
+  );
+
+  /**
+   * Update a Term
+   * Role: ADMIN
+   */
+  app.put(
+    `${prefix}/term/:termId`,
+    isRegistered(),
+    isAdmin(),
+    getTerm(),
+    updateTerm(["name", "startDate", "endDate", "deadline", "createDate"]),
+    noContentResponse()
+  );
+
+  /**
+   * Update Term member
+   * Role: ADMIN
+   */
+  app.put(
+    `${prefix}/term/:termId/user/:userId`,
+    isRegistered(),
+    isAdmin(),
+    getTerm(),
+    updateTermMember(["memberState", "cardState", "cardReceiveDate"]),
+    noContentResponse()
+  );
+};
+
+export default termsRoute;
diff --git a/src/routes/user.ts b/src/routes/user.ts
deleted file mode 100644
index c24d0eab45a7191c1b4da01d687c8a4e719f0403..0000000000000000000000000000000000000000
--- a/src/routes/user.ts
+++ /dev/null
@@ -1,73 +0,0 @@
-import { Application } from "express";
-import addUser from "../middlewares/user/addUser";
-import addWarning from "../middlewares/warning/addWarning";
-import deleteUser from "../middlewares/user/deleteUser";
-import deleteWarning from "../middlewares/warning/deleteWarning";
-import emptyResponse from "../middlewares/utils/emptyResponse";
-import getCardImage from "../middlewares/files/card/getCardImage";
-import getUser from "../middlewares/user/getUser";
-import getUserCard from "../middlewares/files/card/getUserCard";
-import getUsersList from "../middlewares/user/getUsersList";
-import getWarning from "../middlewares/warning/getWarning";
-import getWarningsList from "../middlewares/warning/getUserWarningsList";
-import isAuthenticated from "../middlewares/auth/isAuthenticated";
-import isLoggedIn from "../middlewares/auth/isLoggedIn";
-import responseUser from "../middlewares/user/responseUser";
-import responseUserList from "../middlewares/user/responseUserList";
-import setOwnUserId from "../middlewares/user/setOwnUserId";
-import updateUser from "../middlewares/user/updateUser";
-import updateWarning from "../middlewares/warning/updateWarning";
-
-const usersRoute = (app: Application): void => {
-  app.get(
-    "/api/v1/users",
-    isAuthenticated(),
-    getUsersList(),
-    responseUserList()
-  );
-
-  app.post("/api/v1/users", isLoggedIn(), addUser(), responseUser());
-
-  app.get(
-    "/api/v1/users/me",
-    isAuthenticated(),
-    setOwnUserId(),
-    getUser(),
-    responseUser()
-  );
-
-  app.get(
-    "/api/v1/users/me/card",
-    isAuthenticated(),
-    setOwnUserId(),
-    getUser(),
-    getCardImage(),
-    getUserCard()
-  );
-
-  app.get("/api/v1/users/:id", getUser(), responseUser());
-
-  app.get(
-    "/api/v1/users/:id/card",
-    isAuthenticated(),
-    getUser(),
-    getCardImage(),
-    getUserCard()
-  );
-
-  app.get("/api/v1/users/:id/warnings", getWarningsList());
-
-  app.get("/api/v1/users/:userId/warnings/:warningId", getWarning());
-
-  app.post("/api/v1/users/:id/warnings", addWarning());
-
-  app.put("/api/v1/users/:id", updateUser(), responseUser());
-
-  app.put("/api/v1/users/:userId/warnings/:warningId", updateWarning());
-
-  app.delete("/api/v1/users/:id", deleteUser(), emptyResponse());
-
-  app.delete("/api/v1/users/:userId/warnings/:warningId", deleteWarning());
-};
-
-export default usersRoute;
diff --git a/src/routes/users/membership.ts b/src/routes/users/membership.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0a57b9d1c1acd5c8713e4d95888ddfa61f95de41
--- /dev/null
+++ b/src/routes/users/membership.ts
@@ -0,0 +1,34 @@
+import { Application } from "express";
+import getUserTermMemberships from "../../middlewares/term/getUserTermMemberships";
+import isAdmin from "../../middlewares/auth/isAdmin";
+import isRegistered from "../../middlewares/auth/isRegistered";
+import responseTermsList from "../../middlewares/term/responseTermsList";
+import setOwnUserId from "../../middlewares/user/setOwnUserId";
+
+const userMembershipRoute = (prefix: string, app: Application): void => {
+  /**
+   * Get list of User Term memberships
+   * Role: ADMIN
+   */
+  app.get(
+    `${prefix}/user/:userId/terms`,
+    isRegistered(),
+    isAdmin(),
+    getUserTermMemberships(),
+    responseTermsList()
+  );
+
+  /**
+   * Get list of own Term memberships
+   * Role: NORMAL
+   */
+  app.get(
+    `${prefix}/me/terms`,
+    isRegistered(),
+    setOwnUserId(),
+    getUserTermMemberships(),
+    responseTermsList()
+  );
+};
+
+export default userMembershipRoute;
diff --git a/src/routes/users/notice.ts b/src/routes/users/notice.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a3401a4b30323e3a4b45711663b8d4a7e32162a1
--- /dev/null
+++ b/src/routes/users/notice.ts
@@ -0,0 +1,92 @@
+import { Application } from "express";
+import addNoticeToUser from "../../middlewares/user/notice/addNoticeToUser";
+import deleteNotice from "../../middlewares/user/notice/deleteNotice";
+import example from "../../middlewares/example";
+import getUserNoticeNum from "../../middlewares/user/notice/getUserNoticeNum";
+import getUserNotices from "../../middlewares/user/notice/getUserNotices";
+import isRegistered from "../../middlewares/auth/isRegistered";
+import markNoticeAsSeen from "../../middlewares/user/notice/markNoticeAsSeen";
+import noContentResponse from "../../middlewares/utils/noContentResponse";
+import responseNoticesList from "../../middlewares/user/notice/responseNoticesList";
+import responseNoticesNum from "../../middlewares/user/notice/responseNoticesNum";
+import setOwnUserId from "../../middlewares/user/setOwnUserId";
+
+const userNotificeRoute = (prefix: string, app: Application): void => {
+  /**
+   * Get own notifications
+   * Role: NORMAL
+   */
+  app.get(
+    `${prefix}/me/notices`,
+    isRegistered(),
+    setOwnUserId(),
+    getUserNotices(),
+    responseNoticesList()
+  );
+
+  /**
+   * Get own notification number
+   * Role: NORMAL
+   */
+  app.get(
+    `${prefix}/me/notices/number`,
+    isRegistered(),
+    setOwnUserId(),
+    getUserNoticeNum(),
+    responseNoticesNum()
+  );
+
+  /**
+   * Add notification to User
+   * Role: ADMIN
+   */
+  app.post(
+    `${prefix}/user/:userId/notify`,
+    isRegistered(),
+    addNoticeToUser([
+      { name: "text", required: true },
+      { name: "redirect", required: false },
+    ]),
+    noContentResponse()
+  );
+
+  /**
+   * Remove own notification
+   * Role: NORMAL
+   */
+  app.delete(
+    `${prefix}/me/notice/:noticeId`,
+    isRegistered(),
+    setOwnUserId(),
+    deleteNotice(),
+    noContentResponse()
+  );
+
+  /**
+   * Add notification to Term members
+   * Role: ADMIN
+   */
+  // TODO addTermMembersNotification (termId) { text, redirectUrl}
+  app.post(`${prefix}/term/:termId/notify`, example());
+
+  /**
+   * Add notification to all Users
+   * Role: ADMIN
+   */
+  // TODO addAllusersNotification { text, redirectUrl}
+  app.post(`${prefix}/notify`, example());
+
+  /**
+   * Mark Notice as Seen
+   * Role: NORMAL
+   */
+  app.put(
+    `${prefix}/me/notice/:noticeId`,
+    isRegistered(),
+    setOwnUserId(),
+    markNoticeAsSeen(),
+    noContentResponse()
+  );
+};
+
+export default userNotificeRoute;
diff --git a/src/routes/users/user.ts b/src/routes/users/user.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b54277fd44de97a5f29e70b91c1e211697989eff
--- /dev/null
+++ b/src/routes/users/user.ts
@@ -0,0 +1,197 @@
+import { Application } from "express";
+import acceptPicture from "../../middlewares/user/acceptPicture";
+import createdResponse from "../../middlewares/utils/createdResponse";
+import deleteFile from "../../middlewares/files/deleteFile";
+import deleteUser from "../../middlewares/user/deleteUser";
+import getFieldValue from "../../middlewares/utils/getFieldValue";
+import getUser from "../../middlewares/user/getUser";
+import getUserTermMemberships from "../../middlewares/term/getUserTermMemberships";
+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 noContentResponse from "../../middlewares/utils/noContentResponse";
+import registerOwnUser from "../../middlewares/user/registerOwnUser";
+import rejectPicture from "../../middlewares/user/rejectPicture";
+import responseTermsList from "../../middlewares/term/responseTermsList";
+import responseUser from "../../middlewares/user/responseUser";
+import responseUsersList from "../../middlewares/user/responseUsersList";
+import setOwnUserId from "../../middlewares/user/setOwnUserId";
+import updateUser from "../../middlewares/user/updateUser";
+
+const usersRoute = (prefix: string, app: Application): void => {
+  /**
+   * Register Own User
+   * Role: NORMAL
+   */
+  app.post(
+    `${prefix}/me`,
+    isLoggedIn(),
+    isNotRegistered(),
+    registerOwnUser(),
+    createdResponse()
+  );
+
+  /**
+   * Get list of users
+   * Role: ADMIN
+   */
+  app.get(
+    `${prefix}/`,
+    isRegistered(),
+    isAdmin(),
+    getUsersList("_id name newPicture"),
+    responseUsersList()
+  );
+
+  /**
+   * Get One User
+   * Role: ADMIN
+   */
+  app.get(
+    `${prefix}/user/:userId`,
+    isRegistered(),
+    isAdmin(),
+    getUser(
+      "_id name role email externalId studentCardNumber roomNumber isStaffMember staffMemberText"
+    ),
+    responseUser()
+  );
+
+  /**
+   * Get Own User
+   * Role: NORMAL
+   */
+  app.get(
+    `${prefix}/me`,
+    isRegistered(),
+    setOwnUserId(),
+    getUser("id name role email studentCardNumber roomNumber"),
+    responseUser()
+  );
+
+  /**
+   * Get Own User Short
+   * Role: NORMAL
+   */
+  app.get(
+    `${prefix}/me/short`,
+    isRegistered(),
+    setOwnUserId(),
+    getUser("id name role"),
+    responseUser()
+  );
+
+  /**
+   * Update Own User
+   * Role: NORMAL
+   */
+  app.put(
+    `${prefix}/me`,
+    isRegistered(),
+    setOwnUserId(),
+    updateUser(["studentCardNumber", "roomNumber"]),
+    noContentResponse()
+  );
+
+  /**
+   * Update User
+   * Role: ADMIN
+   */
+  app.put(
+    `${prefix}/user/:userId`,
+    isRegistered(),
+    isAdmin(),
+    getUser("_id"),
+    updateUser([
+      "studentCardNumber",
+      "roomNumber",
+      "isStaffMember",
+      "staffMemberText",
+    ]),
+    noContentResponse()
+  );
+
+  /**
+   * Get list of staff Members
+   * Role: NORMAL
+   */
+  app.get(
+    `${prefix}/staff`,
+    isRegistered(),
+    getUsersList("_id name email staffMemberText", { isStaffMember: true }),
+    responseUsersList()
+  );
+
+  /**
+   * Accept a users Picture
+   * Role: ADMIN
+   */
+  app.post(
+    `${prefix}/user/:userId/picture/accept`,
+    isRegistered(),
+    isAdmin(),
+    getUser("acceptedPicture newPicture"),
+    getFieldValue("profile", "acceptedPicture"),
+    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()
+  );
+
+  /**
+   * Delete a User
+   * Role: ADMIN
+   */
+  app.delete(
+    `${prefix}/user/:userId`,
+    isRegistered(),
+    isAdmin(),
+    getFieldValue("profile", "newPicture"),
+    deleteFile(),
+    getFieldValue("profile", "acceptedPicture"),
+    deleteFile(),
+    deleteUser(),
+    noContentResponse()
+  );
+
+  /**
+   * Get list of User Term memberships
+   * Role: ADMIN
+   */
+  app.get(
+    `${prefix}/user/:userId/terms`,
+    isRegistered(),
+    isAdmin(),
+    getUserTermMemberships(),
+    responseTermsList()
+  );
+
+  /**
+   * Get list of own Term memberships
+   * Role: NORMAL
+   */
+  app.get(
+    `${prefix}/me/terms`,
+    isRegistered(),
+    setOwnUserId(),
+    getUserTermMemberships(),
+    responseTermsList()
+  );
+};
+
+export default usersRoute;
diff --git a/src/routes/users/warning.ts b/src/routes/users/warning.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3f4cb21c8ba006bdc218175a897cd927b19d63cb
--- /dev/null
+++ b/src/routes/users/warning.ts
@@ -0,0 +1,71 @@
+import { Application } from "express";
+import addWarning from "../../middlewares/user/warning/addWarning";
+import deleteWarning from "../../middlewares/user/warning/deleteWarning";
+import getUserWarningsList from "../../middlewares/user/warning/getUserWarningsList";
+import isAdmin from "../../middlewares/auth/isAdmin";
+import isRegistered from "../../middlewares/auth/isRegistered";
+import noContentResponse from "../../middlewares/utils/noContentResponse";
+import responseWarningsList from "../../middlewares/user/warning/responseWarningsList";
+import setOwnUserId from "../../middlewares/user/setOwnUserId";
+import updateWarning from "../../middlewares/user/warning/updateWarning";
+
+const userWarningsRoute = (prefix: string, app: Application): void => {
+  /**
+   * Add new warning
+   * Role: Admin
+   */
+  app.post(
+    `${prefix}/user/:userId/warnings`,
+    isRegistered(),
+    isAdmin(),
+    addWarning([{ name: "text", required: true }]),
+    noContentResponse()
+  );
+
+  /**
+   * Get user warnings
+   * Role: Admin
+   */
+  app.get(
+    `${prefix}/user/:userId/warnings`,
+    isRegistered(),
+    isAdmin(),
+    getUserWarningsList(),
+    responseWarningsList()
+  );
+  /**
+   * Get Own warnings
+   * Role: Normal
+   */
+  app.get(
+    `${prefix}/me/warnings`,
+    isRegistered(),
+    setOwnUserId(),
+    getUserWarningsList(),
+    responseWarningsList()
+  );
+  /**
+   * Delete Warning
+   * Role: Admin
+   */
+  app.delete(
+    `${prefix}/user/:userId/warning/:warningId`,
+    isRegistered(),
+    isAdmin(),
+    deleteWarning(),
+    noContentResponse()
+  );
+  /**
+   * Update Warning
+   * Role: Admin
+   */
+  app.put(
+    `${prefix}/user/:userId/warning/:warningId`,
+    isRegistered(),
+    isAdmin(),
+    updateWarning(["text"]),
+    noContentResponse()
+  );
+};
+
+export default userWarningsRoute;
diff --git a/src/routes/warning.ts b/src/routes/warning.ts
deleted file mode 100644
index be2afb970128c66f8bb150b29ff7ded0e2c1e975..0000000000000000000000000000000000000000
--- a/src/routes/warning.ts
+++ /dev/null
@@ -1,61 +0,0 @@
-import { Application } from "express";
-import addWarning from "../middlewares/warning/addWarning";
-import deleteWarning from "../middlewares/warning/deleteWarning";
-import emptyResponse from "../middlewares/utils/emptyResponse";
-import getUser from "../middlewares/user/getUser";
-import getUserWarningsList from "../middlewares/warning/getUserWarningsList";
-import getWarning from "../middlewares/warning/getWarning";
-import isAuthenticated from "../middlewares/auth/isAuthenticated";
-import responseWarning from "../middlewares/warning/responseWarning";
-import responseWarningList from "../middlewares/warning/responseWarningList";
-import setOwnUserId from "../middlewares/user/setOwnUserId";
-import updateWarning from "../middlewares/warning/updateWarning";
-
-const warningsRoute = (app: Application): void => {
-  app.get(
-    "/api/v1/warnings/warning/:warningId",
-    isAuthenticated(),
-    getWarning(),
-    responseWarning()
-  );
-
-  app.get(
-    "/api/v1/warnings/me",
-    isAuthenticated(),
-    setOwnUserId(),
-    getUser(),
-    getUserWarningsList(),
-    responseWarningList()
-  );
-
-  app.get(
-    "/api/v1/warnings/user/:id",
-    isAuthenticated(),
-    getUser(),
-    getUserWarningsList(),
-    responseWarningList()
-  );
-
-  app.post(
-    "/api/v1/warnings/user/:id",
-    isAuthenticated(),
-    addWarning(),
-    responseWarning()
-  );
-
-  app.put(
-    "/api/v1/warnings/warning/:warningId",
-    isAuthenticated(),
-    updateWarning(),
-    responseWarning()
-  );
-
-  app.delete(
-    "/api/v1/warnings/warning/:warningId",
-    isAuthenticated(),
-    deleteWarning(),
-    emptyResponse()
-  );
-};
-
-export default warningsRoute;
diff --git a/src/utils/declarations/response.d.ts b/src/utils/declarations/response.d.ts
index 9c759230da7b0a3bde9f9393862b23ba0f34d185..4b8f59d33f95e7075394fe2bba28222ce6244847 100644
--- a/src/utils/declarations/response.d.ts
+++ b/src/utils/declarations/response.d.ts
@@ -1,25 +1,26 @@
 import { INews } from "../../models/NewsSchema";
-import { IProfile } from "../../models/ProfileSchema";
-import { IFile } from "../../models/FileSchema";
-import { ICard } from "../../models/CardSchema";
-import { ICardImage } from "../../models/CardImageSchema";
-import { IWarning } from "../../models/WarningSchema";
+import { INotice, IProfile, IWarning } from "../../models/ProfileSchema";
+import { IMember, ITerm } from "../../models/TermSchema";
 
 declare global {
   namespace Express {
     export interface Response {
       data: {
-        news?: Partial<INews>[] | null;
-        newsObject?: Partial<INews> | null;
         profile?: Partial<IProfile> | null;
-        card?: Partial<ICard> | null;
-        cards?: Partial<ICard>[] | null;
-        cardImage?: Partial<ICardImage> | null;
         profiles?: Partial<IProfile>[] | null;
-        error?: string | null;
-        files?: Partial<IFile>[] | null;
         warning?: Partial<IWarning> | null;
         warnings?: Partial<IWarning>[] | null;
+        newObjectId?: string | null;
+        term?: Partial<ITerm> | null;
+        terms?: Partial<ITerm>[] | null;
+        member?: Partial<IMember> | null;
+        members?: Partial<IMember>[] | null;
+        news?: Partial<INews>[] | null;
+        oneNews?: Partial<INews> | null;
+        notice?: Partial<INotice> | null;
+        notices?: Partial<INotice>[] | null;
+        value?: string | null;
+        number?: number | null;
       };
     }
   }
diff --git a/src/utils/declarations/session.d.ts b/src/utils/declarations/session.d.ts
index be2d691845e23779a3da67227a58a65203b56045..e25eb62242301c3c340071088687aa712f93c8bd 100644
--- a/src/utils/declarations/session.d.ts
+++ b/src/utils/declarations/session.d.ts
@@ -1,4 +1,3 @@
-import { AccessToken } from "simple-oauth2";
 import { User } from "../../models/user.interface";
 
 declare module "express-session" {
diff --git a/src/utils/strings/.gitignore b/src/utils/strings/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..a64fc4577cfc05bff6e0695ba24b61311a2e453b
--- /dev/null
+++ b/src/utils/strings/.gitignore
@@ -0,0 +1 @@
+notifications.ts
\ No newline at end of file
diff --git a/src/utils/strings/notifications.example.ts b/src/utils/strings/notifications.example.ts
new file mode 100644
index 0000000000000000000000000000000000000000..df893c4fe420b1d3421c2f3c2b0b934608965079
--- /dev/null
+++ b/src/utils/strings/notifications.example.ts
@@ -0,0 +1,6 @@
+export const REGISTER = "Please register";
+export const MISSING_PROFILE_PICTURE = "Add a profile picture";
+export const NEW_WARNING = "You got a new warning";
+export const DELETED_WARNING = "One of your warning was deleted";
+export const TERM_MEMBER_ACCEPTED = "You've been accepted to a Term";
+export const TERM_MEMBER_REJECTED = "You've been rejected to a Term";
diff --git a/tsconfig.json b/tsconfig.json
index 004e8b06f8bc7edeed072b9a0bcfdd7a227721c6..a5ae5c396b413363d471a74581e4a7765f653f82 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -10,7 +10,6 @@
   "compilerOptions": {
     "module": "commonjs",
     "strict": true,
-    "baseUrl": "./",
     "outDir": "build",
     "removeComments": true,
     "experimentalDecorators": true,
diff --git a/tslint.json b/tslint.json
index e9628e637c18ef66e5a79f765fcd60e2f2e984ef..8ed07bbc1b9f8b8e995eee67133b39cc0ef0a6e1 100644
--- a/tslint.json
+++ b/tslint.json
@@ -9,6 +9,16 @@
     "object-literal-sort-keys": false,
     "ordered-imports": false,
     "quotemark": [true, "single"],
-    "variable-name": [true, "allow-leading-underscore"]
+    "variable-name": [true, "allow-leading-underscore"],
+    "no-unused-declaration": {
+      "options": [
+        {
+          "declarations": true,
+          "ignored": {},
+          "imports": true
+        }
+      ],
+      "severity": "error"
+    }
   }
 }