diff --git a/server/app/api/users.py b/server/app/api/users.py
index db7859f264c3af31d346b2b1f42cebd2f8d4574a..0d92ee52ca97406b99b98939bdc5bea54411c787 100644
--- a/server/app/api/users.py
+++ b/server/app/api/users.py
@@ -5,6 +5,7 @@ from app.api import api_blueprint
 from app.database.models import Blacklist, User
 from app.utils.validator import edit_user_schema, login_schema, register_schema, validateObject
 from flask import request
+from flask.globals import session
 from flask_jwt_extended import (
     create_access_token,
     create_refresh_token,
diff --git a/server/app/database/__init__.py b/server/app/database/__init__.py
index d755b84e4ed716e143e95b5b50503a52e98f04a9..4a1dc8b75fcd414adf91d242e8367c98d763db55 100644
--- a/server/app/database/__init__.py
+++ b/server/app/database/__init__.py
@@ -1,13 +1,10 @@
-from flask_sqlalchemy.model import Model
 import sqlalchemy as sa
+from flask_sqlalchemy.model import Model
 from sqlalchemy.ext.declarative import declared_attr
 from sqlalchemy.sql import func
 
 
 class Base(Model):
-    @declared_attr
-    def __tablename__(self):
-        return self.__class__.__name__.replace("Model", "s").lower()
-
+    __abstract__ = True
     created = sa.Column(sa.DateTime(timezone=True), server_default=func.now())
     updated = sa.Column(sa.DateTime(timezone=True), onupdate=func.now())
diff --git a/server/app/database/models.py b/server/app/database/models.py
index bd486a144d28f46c358ab8979d274ed1b3cd83e7..5452ce3d7e5a1373af783c57dd2453ede892392c 100644
--- a/server/app/database/models.py
+++ b/server/app/database/models.py
@@ -1,22 +1,38 @@
-from sqlalchemy.ext.hybrid import hybrid_property, hybrid_method
+from app import bcrypt, db
 from sqlalchemy.ext.declarative import declared_attr
+from sqlalchemy.ext.hybrid import hybrid_method, hybrid_property
 
-from app import bcrypt, db
-from app.database import Base
+STRING_SIZE = 254
 
 
 class Blacklist(db.Model):
     id = db.Column(db.Integer, primary_key=True)
     jti = db.Column(db.String, unique=True, nullable=False)
 
-    @declared_attr
-    def __tablename__(self):
-        return "blacklist"
-
     def __init__(self, jti):
         self.jti = jti
 
 
+class Role(db.Model):
+    id = db.Column(db.Integer, primary_key=True)
+    name = db.Column(db.String(STRING_SIZE), unique=True)
+
+    users = db.relationship("User", backref="role")
+
+    def __init__(self, name):
+        self.name = name
+
+
+class City(db.Model):
+    id = db.Column(db.Integer, primary_key=True)
+    name = db.Column(db.String(STRING_SIZE), unique=True)
+
+    users = db.relationship("User", backref="city")
+
+    def __init__(self, name):
+        self.name = name
+
+
 class User(db.Model):
     id = db.Column(db.Integer, primary_key=True)
     email = db.Column(db.String(254), unique=True, nullable=False)
@@ -28,9 +44,16 @@ class User(db.Model):
     twoAuthConfirmed = db.Column(db.Boolean, default=True)  # Change to false for Two factor authen
     twoAuthCode = db.Column(db.String(100), nullable=True)
 
-    def __init__(self, email, plaintext_password, name=""):
+    role_id = db.Column(db.Integer, db.ForeignKey("role.id"), nullable=True)  # Change to false
+    city_id = db.Column(db.Integer, db.ForeignKey("city.id"), nullable=True)  # Change to false
+
+    media = db.relationship("Media", backref="upload_by")
+
+    def __init__(self, email, plaintext_password, role_id=None, city_id=None, name=None):
         self._password = bcrypt.generate_password_hash(plaintext_password)
         self.email = email
+        self.role_id = role_id
+        self.city_id = city_id
         self.name = name
         self.authenticated = False
 
@@ -48,3 +71,164 @@ class User(db.Model):
     @hybrid_method
     def is_correct_password(self, plaintext_password):
         return bcrypt.check_password_hash(self._password, plaintext_password)
+
+
+class Media(db.Model):
+    id = db.Column(db.Integer, primary_key=True)
+    filename = db.Column(db.String(STRING_SIZE), unique=True)
+    type = db.Column(db.String(STRING_SIZE), nullable=False)
+    upload_by_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)
+
+    def __init__(self, filename, type, upload_by_id):
+        self.filename = filename
+        self.type = type
+        self.upload_by_id = upload_by_id
+
+
+class Style(db.Model):
+    id = db.Column(db.Integer, primary_key=True)
+    name = db.Column(db.String(STRING_SIZE), unique=True)
+    css = db.Column(db.Text, nullable=True)
+    bg_image_id = db.Column(db.Integer, db.ForeignKey("media.id"), nullable=True)
+
+    bg_image = db.relationship("Media", foreign_keys=[bg_image_id], uselist=False)
+
+    def __init__(self, name, css=None, bg_image_id=None):
+        self.name = name
+        self.css = css
+        self.bg_image_id = bg_image_id
+
+
+class Competition(db.Model):
+    id = db.Column(db.Integer, primary_key=True)
+    name = db.Column(db.String(STRING_SIZE), unique=True)
+    style_id = db.Column(db.Integer, db.ForeignKey("style.id"), nullable=False)
+    city_id = db.Column(db.Integer, db.ForeignKey("city.id"), nullable=False)
+
+    style = db.relationship("Style", foreign_keys=[style_id], uselist=False)
+    city = db.relationship("City", foreign_keys=[city_id], uselist=False)
+
+    def __init__(self, name, style_id, city_id):
+        self.name = name
+        self.style_id = style_id
+        self.city_id = city_id
+
+
+class Team(db.Model):
+    id = db.Column(db.Integer, primary_key=True)
+    name = db.Column(db.String(STRING_SIZE), unique=True)
+    competition_id = db.Column(db.Integer, db.ForeignKey("competition.id"), nullable=False)
+    competition = db.relationship("Competition", foreign_keys=[competition_id], uselist=False)
+
+    def __init__(self, name, competition_id):
+        self.name = name
+        self.competition_id = competition_id
+
+
+class Slide(db.Model):
+    id = db.Column(db.Integer, primary_key=True)
+    name = db.Column(db.String(STRING_SIZE), unique=True)
+    order = db.Column(db.Integer, nullable=False)
+    tweak_settings = db.Column(db.Text, nullable=True)
+    competition_id = db.Column(db.Integer, db.ForeignKey("competition.id"), nullable=False)
+
+    competition = db.relationship("Competition", foreign_keys=[competition_id], uselist=False)
+
+    def __init__(self, name, order, competition_id, tweak_settings=None):
+        self.name = name
+        self.order = order
+        self.competition_id = competition_id
+        self.tweak_settings = tweak_settings
+
+
+class Question(db.Model):
+    id = db.Column(db.Integer, primary_key=True)
+    name = db.Column(db.String(STRING_SIZE), unique=True)
+    title = db.Column(db.String(STRING_SIZE), nullable=False)
+    timer = db.Column(db.Integer, nullable=False)
+    slide_id = db.Column(db.Integer, db.ForeignKey("slide.id"), nullable=False)
+
+    slide = db.relationship("Slide", foreign_keys=[slide_id], uselist=False)
+
+    def __init__(self, name, title, timer, slide_id):
+        self.name = name
+        self.title = title
+        self.timer = timer
+        self.slide_id = slide_id
+
+
+class TrueFalseQuestion(db.Model):
+    id = db.Column(db.Integer, primary_key=True)
+    true_false = db.Column(db.Boolean, nullable=False, default=False)
+    question_id = db.Column(db.Integer, db.ForeignKey("question.id"), nullable=False)
+
+    question = db.relationship("Question", foreign_keys=[question_id], uselist=False)
+
+    def __init__(self, true_false, question_id):
+        self.true_false = true_false
+        self.question_id = question_id
+
+
+class TextQuestion(db.Model):
+    id = db.Column(db.Integer, primary_key=True)
+    question_id = db.Column(db.Integer, db.ForeignKey("question.id"), nullable=False)
+    question = db.relationship("Question", foreign_keys=[question_id], uselist=False)
+
+    def __init__(self, question_id):
+        self.question_id = question_id
+
+
+class TextQuestionAlternative(db.Model):
+    id = db.Column(db.Integer, primary_key=True)
+    text = db.Column(db.String(STRING_SIZE), nullable=False)
+    text_question_id = db.Column(db.Integer, db.ForeignKey("text_question.id"), nullable=False)
+    text_question = db.relationship("TextQuestion", foreign_keys=[text_question_id], uselist=False)
+
+    def __init__(self, text, text_question_id):
+        self.text = text
+        self.text_question_id = text_question_id
+
+
+class MCQuestion(db.Model):
+    id = db.Column(db.Integer, primary_key=True)
+    title = db.Column(db.String(STRING_SIZE), nullable=False)
+    timer = db.Column(db.Integer, nullable=False)
+    question_id = db.Column(db.Integer, db.ForeignKey("question.id"), nullable=False)
+
+    question = db.relationship("Question", foreign_keys=[question_id], uselist=False)
+
+    def __init__(self, title, timer, slide_id):
+        self.title = title
+        self.timer = timer
+        self.slide_id = slide_id
+
+
+class MCQuestionAlternative(db.Model):
+    id = db.Column(db.Integer, primary_key=True)
+    text = db.Column(db.String(STRING_SIZE), nullable=False)
+    true_false = db.Column(db.Boolean, nullable=False, default=False)
+    mc_id = db.Column(db.Integer, db.ForeignKey("mc_question.id"), nullable=False)
+
+    mc = db.relationship("MCQuestion", foreign_keys=[mc_id], uselist=False)
+
+    def __init__(self, text, true_false, mc_id):
+        self.text = text
+        self.true_false = true_false
+        self.mc_id = mc_id
+
+
+class AnsweredQuestion(db.Model):
+    id = db.Column(db.Integer, primary_key=True)
+    data = db.Column(db.Text, nullable=False)
+    score = db.Column(db.Integer, nullable=False)
+    question_id = db.Column(db.Integer, db.ForeignKey("question.id"), nullable=False)
+    team_id = db.Column(db.Integer, db.ForeignKey("team.id"), nullable=False)
+
+    question = db.relationship("Question", foreign_keys=[question_id], uselist=False)
+    team = db.relationship("Team", foreign_keys=[team_id], uselist=False)
+
+    def __init__(self, data, score, question_id, team_id):
+        self.data = data
+        self.score = score
+        self.question_id = question_id
+        self.team_id = team_id