diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..549e00a2a96fa9d7c5dbc9859664a78d980158c2
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,33 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..997894c322fef088a7ff37136b44d788d0aab02e
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,29 @@
+stages:
+- ".pre"
+- build
+- test
+- deploy
+- ".post"
+build-job:
+  stage: build
+  script:
+  - echo "Compiling the code..."
+  - echo "Compile complete."
+unit-test-job:
+  stage: test
+  script:
+  - echo "Running unit tests... This will take about 60 seconds."
+  - sleep 60
+  - echo "Code coverage is 90%"
+lint-test-job:
+  stage: test
+  script:
+  - echo "Linting code... This will take about 10 seconds."
+  - sleep 10
+  - echo "No lint issues found."
+deploy-job:
+  stage: deploy
+  environment: production
+  script:
+  - echo "Deploying application..."
+  - echo "Application successfully deployed."
diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000000000000000000000000000000000000..cb28b0e37c7d206feb564310fdeec0927af4123a
Binary files /dev/null and b/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000000000000000000000000000000000000..5f0536eb74343e6e1e0aa69e3aacbc51e015f97e
--- /dev/null
+++ b/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,2 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar
diff --git a/mvnw b/mvnw
new file mode 100644
index 0000000000000000000000000000000000000000..66df2854281f4cb6869e4830dd1a7abd1e946c18
--- /dev/null
+++ b/mvnw
@@ -0,0 +1,308 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#    https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Apache Maven Wrapper startup batch script, version 3.2.0
+#
+# Required ENV vars:
+# ------------------
+#   JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+#   MAVEN_OPTS - parameters passed to the Java VM when running Maven
+#     e.g. to debug Maven itself, use
+#       set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+#   MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+  if [ -f /usr/local/etc/mavenrc ] ; then
+    . /usr/local/etc/mavenrc
+  fi
+
+  if [ -f /etc/mavenrc ] ; then
+    . /etc/mavenrc
+  fi
+
+  if [ -f "$HOME/.mavenrc" ] ; then
+    . "$HOME/.mavenrc"
+  fi
+
+fi
+
+# OS specific support.  $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "$(uname)" in
+  CYGWIN*) cygwin=true ;;
+  MINGW*) mingw=true;;
+  Darwin*) darwin=true
+    # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+    # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+    if [ -z "$JAVA_HOME" ]; then
+      if [ -x "/usr/libexec/java_home" ]; then
+        JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME
+      else
+        JAVA_HOME="/Library/Java/Home"; export JAVA_HOME
+      fi
+    fi
+    ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+  if [ -r /etc/gentoo-release ] ; then
+    JAVA_HOME=$(java-config --jre-home)
+  fi
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+  [ -n "$JAVA_HOME" ] &&
+    JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
+  [ -n "$CLASSPATH" ] &&
+    CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+  [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] &&
+    JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+  javaExecutable="$(which javac)"
+  if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then
+    # readlink(1) is not available as standard on Solaris 10.
+    readLink=$(which readlink)
+    if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then
+      if $darwin ; then
+        javaHome="$(dirname "\"$javaExecutable\"")"
+        javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac"
+      else
+        javaExecutable="$(readlink -f "\"$javaExecutable\"")"
+      fi
+      javaHome="$(dirname "\"$javaExecutable\"")"
+      javaHome=$(expr "$javaHome" : '\(.*\)/bin')
+      JAVA_HOME="$javaHome"
+      export JAVA_HOME
+    fi
+  fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+  if [ -n "$JAVA_HOME"  ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+      # IBM's JDK on AIX uses strange locations for the executables
+      JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+      JAVACMD="$JAVA_HOME/bin/java"
+    fi
+  else
+    JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)"
+  fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+  echo "Error: JAVA_HOME is not defined correctly." >&2
+  echo "  We cannot execute $JAVACMD" >&2
+  exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+  echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+  if [ -z "$1" ]
+  then
+    echo "Path not specified to find_maven_basedir"
+    return 1
+  fi
+
+  basedir="$1"
+  wdir="$1"
+  while [ "$wdir" != '/' ] ; do
+    if [ -d "$wdir"/.mvn ] ; then
+      basedir=$wdir
+      break
+    fi
+    # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+    if [ -d "${wdir}" ]; then
+      wdir=$(cd "$wdir/.." || exit 1; pwd)
+    fi
+    # end of workaround
+  done
+  printf '%s' "$(cd "$basedir" || exit 1; pwd)"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+  if [ -f "$1" ]; then
+    # Remove \r in case we run on Windows within Git Bash
+    # and check out the repository with auto CRLF management
+    # enabled. Otherwise, we may read lines that are delimited with
+    # \r\n and produce $'-Xarg\r' rather than -Xarg due to word
+    # splitting rules.
+    tr -s '\r\n' ' ' < "$1"
+  fi
+}
+
+log() {
+  if [ "$MVNW_VERBOSE" = true ]; then
+    printf '%s\n' "$1"
+  fi
+}
+
+BASE_DIR=$(find_maven_basedir "$(dirname "$0")")
+if [ -z "$BASE_DIR" ]; then
+  exit 1;
+fi
+
+MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR
+log "$MAVEN_PROJECTBASEDIR"
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar"
+if [ -r "$wrapperJarPath" ]; then
+    log "Found $wrapperJarPath"
+else
+    log "Couldn't find $wrapperJarPath, downloading it ..."
+
+    if [ -n "$MVNW_REPOURL" ]; then
+      wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+    else
+      wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+    fi
+    while IFS="=" read -r key value; do
+      # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' )
+      safeValue=$(echo "$value" | tr -d '\r')
+      case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;;
+      esac
+    done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
+    log "Downloading from: $wrapperUrl"
+
+    if $cygwin; then
+      wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
+    fi
+
+    if command -v wget > /dev/null; then
+        log "Found wget ... using wget"
+        [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet"
+        if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+            wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+        else
+            wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+        fi
+    elif command -v curl > /dev/null; then
+        log "Found curl ... using curl"
+        [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent"
+        if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+            curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
+        else
+            curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
+        fi
+    else
+        log "Falling back to using Java to download"
+        javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java"
+        javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class"
+        # For Cygwin, switch paths to Windows format before running javac
+        if $cygwin; then
+          javaSource=$(cygpath --path --windows "$javaSource")
+          javaClass=$(cygpath --path --windows "$javaClass")
+        fi
+        if [ -e "$javaSource" ]; then
+            if [ ! -e "$javaClass" ]; then
+                log " - Compiling MavenWrapperDownloader.java ..."
+                ("$JAVA_HOME/bin/javac" "$javaSource")
+            fi
+            if [ -e "$javaClass" ]; then
+                log " - Running MavenWrapperDownloader.java ..."
+                ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath"
+            fi
+        fi
+    fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+# If specified, validate the SHA-256 sum of the Maven wrapper jar file
+wrapperSha256Sum=""
+while IFS="=" read -r key value; do
+  case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;;
+  esac
+done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
+if [ -n "$wrapperSha256Sum" ]; then
+  wrapperSha256Result=false
+  if command -v sha256sum > /dev/null; then
+    if echo "$wrapperSha256Sum  $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then
+      wrapperSha256Result=true
+    fi
+  elif command -v shasum > /dev/null; then
+    if echo "$wrapperSha256Sum  $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then
+      wrapperSha256Result=true
+    fi
+  else
+    echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available."
+    echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties."
+    exit 1
+  fi
+  if [ $wrapperSha256Result = false ]; then
+    echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2
+    echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2
+    echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2
+    exit 1
+  fi
+fi
+
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+  [ -n "$JAVA_HOME" ] &&
+    JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
+  [ -n "$CLASSPATH" ] &&
+    CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
+  [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+    MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+# shellcheck disable=SC2086 # safe args
+exec "$JAVACMD" \
+  $MAVEN_OPTS \
+  $MAVEN_DEBUG_OPTS \
+  -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+  "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+  ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/mvnw.cmd b/mvnw.cmd
new file mode 100644
index 0000000000000000000000000000000000000000..95ba6f54ac526de46248af840bab26f33f946b93
--- /dev/null
+++ b/mvnw.cmd
@@ -0,0 +1,205 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements.  See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership.  The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License.  You may obtain a copy of the License at
+@REM
+@REM    https://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied.  See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Apache Maven Wrapper startup batch script, version 3.2.0
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM     e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on"  echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
+if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+
+FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+    IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+    if "%MVNW_VERBOSE%" == "true" (
+        echo Found %WRAPPER_JAR%
+    )
+) else (
+    if not "%MVNW_REPOURL%" == "" (
+        SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+    )
+    if "%MVNW_VERBOSE%" == "true" (
+        echo Couldn't find %WRAPPER_JAR%, downloading it ...
+        echo Downloading from: %WRAPPER_URL%
+    )
+
+    powershell -Command "&{"^
+		"$webclient = new-object System.Net.WebClient;"^
+		"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+		"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+		"}"^
+		"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^
+		"}"
+    if "%MVNW_VERBOSE%" == "true" (
+        echo Finished downloading %WRAPPER_JAR%
+    )
+)
+@REM End of extension
+
+@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file
+SET WRAPPER_SHA_256_SUM=""
+FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+    IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B
+)
+IF NOT %WRAPPER_SHA_256_SUM%=="" (
+    powershell -Command "&{"^
+       "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^
+       "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^
+       "  Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^
+       "  Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^
+       "  Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^
+       "  exit 1;"^
+       "}"^
+       "}"
+    if ERRORLEVEL 1 goto error
+)
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% ^
+  %JVM_CONFIG_MAVEN_PROPS% ^
+  %MAVEN_OPTS% ^
+  %MAVEN_DEBUG_OPTS% ^
+  -classpath %WRAPPER_JAR% ^
+  "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
+  %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
+if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%"=="on" pause
+
+if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
+
+cmd /C exit /B %ERROR_CODE%
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7427f5eb4c5713ba283696bbec8d7a41e35a9dc0
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>org.springframework.boot</groupId>
+		<artifactId>spring-boot-starter-parent</artifactId>
+		<version>3.2.4</version>
+		<relativePath/> <!-- lookup parent from repository -->
+	</parent>
+	<groupId>idatt2105.group11</groupId>
+	<artifactId>idatt2105-project-backend</artifactId>
+	<version>0.0.1-SNAPSHOT</version>
+	<name>idatt2105-project-backend</name>
+	<description>Backend for IDATT2105 project</description>
+	<properties>
+		<java.version>21</java.version>
+	</properties>
+	<dependencies>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-data-jpa</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-web</artifactId>
+		</dependency>
+
+		<dependency>
+			<groupId>com.h2database</groupId>
+			<artifactId>h2</artifactId>
+			<scope>runtime</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-test</artifactId>
+			<scope>test</scope>
+		</dependency>
+		<!-- Spring Security -->
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-security</artifactId>
+		</dependency>
+
+		<dependency>
+			<groupId>io.jsonwebtoken</groupId>
+			<artifactId>jjwt-api</artifactId>
+			<version>0.11.5</version>
+		</dependency>
+
+		<dependency>
+			<groupId>io.jsonwebtoken</groupId>
+			<artifactId>jjwt-impl</artifactId>
+			<version>0.11.5</version>
+		</dependency>
+
+		<dependency>
+			<groupId>io.jsonwebtoken</groupId>
+			<artifactId>jjwt-jackson</artifactId>
+			<version>0.11.5</version>
+		</dependency>
+
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
+		</dependency>
+	</dependencies>
+
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.springframework.boot</groupId>
+				<artifactId>spring-boot-maven-plugin</artifactId>
+			</plugin>
+		</plugins>
+	</build>
+
+</project>
diff --git a/src/main/java/idatt2105/group11/idatt2105projectbackend/Idatt2105ProjectBackendApplication.java b/src/main/java/idatt2105/group11/idatt2105projectbackend/Idatt2105ProjectBackendApplication.java
new file mode 100644
index 0000000000000000000000000000000000000000..8205825790b4a80b7ed1536b977c830baa8b44e4
--- /dev/null
+++ b/src/main/java/idatt2105/group11/idatt2105projectbackend/Idatt2105ProjectBackendApplication.java
@@ -0,0 +1,13 @@
+package idatt2105.group11.idatt2105projectbackend;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Idatt2105ProjectBackendApplication {
+
+	public static void main(String[] args) {
+		SpringApplication.run(Idatt2105ProjectBackendApplication.class, args);
+	}
+
+}
diff --git a/src/main/java/idatt2105/group11/idatt2105projectbackend/QuizCreationAndTest.java b/src/main/java/idatt2105/group11/idatt2105projectbackend/QuizCreationAndTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..88c0eb6dce44242e91c01029edfaac99c2c48ccb
--- /dev/null
+++ b/src/main/java/idatt2105/group11/idatt2105projectbackend/QuizCreationAndTest.java
@@ -0,0 +1,73 @@
+package idatt2105.group11.idatt2105projectbackend;
+
+import idatt2105.group11.idatt2105projectbackend.model.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+
+public class QuizCreationAndTest {
+
+  // Initialize the logger for the class
+  private static final Logger logger = LoggerFactory.getLogger(QuizCreationAndTest.class);
+
+  public static void main(String[] args) {
+    logger.info("Quiz creation and test started.");
+
+    //Step 0: Create a User
+    Role admin = new Role("ROLE_ADMIN");
+    HashSet<Role> roles = new HashSet<>(Arrays.asList(admin));
+
+    User JohnDoe = new User("John Doe", "password", roles);
+    logger.info("Created user: {}", JohnDoe.getName());
+
+    // Step 1: Create questions with assigned scores
+    MultipleChoiceQuestion question1 = new MultipleChoiceQuestion(null,
+            "What is the capital of France?",
+            2,
+            Arrays.asList("1. Paris", "2. London", "3. Berlin", "4. Madrid"),
+            0
+    );
+    logger.info("Created question: {}", question1.getQuestionText());
+
+    MultipleChoiceQuestion question2 = new MultipleChoiceQuestion(null,
+            "Which language is primarily spoken in Brazil?",
+            3,
+            Arrays.asList("1. Spanish", "2. Portuguese", "3. French", "4. English"),
+            1
+    );
+    logger.info("Created question: {}", question2.getQuestionText());
+
+    // Step 2: Create a quiz and add questions
+    List<Question> questions = new ArrayList<>();
+    questions.add(question1);
+    questions.add(question2);
+    Quiz quiz = new Quiz("Sample Quiz", questions, JohnDoe, QuizCategory.GEOGRAPHY, QuizDifficulty.EASY);
+    questions.forEach(question -> question.setQuiz(quiz));
+    logger.info("Created quiz: {}", quiz.getTitle());
+
+    // Step 3: Simulate answers from a user
+    QuestionAnswer answer1 = new QuestionAnswer(question1, "2");
+    QuestionAnswer answer2 = new QuestionAnswer(question2, "2");
+    logger.info("Simulated answers for the quiz.");
+
+    // Step 4: Create a QuizResult and add answers
+    QuizResult quizResult = new QuizResult(quiz, new ArrayList<>(), JohnDoe, "påbegynt", LocalDateTime.now(), null); // Initialize with an empty answers list
+    quizResult.addQuestionAnswer(answer1);
+    quizResult.addQuestionAnswer(answer2);
+    logger.info("Created quiz result for user: {}", JohnDoe.getName());
+
+    // Output results
+    quizResult.getAnswers().forEach(answer -> {
+      logger.info("Question: {} - Your Answer: {} - Correct? {}", answer.getQuestion().getQuestionText(), answer.getGivenAnswer(), answer.isCorrect());
+    });
+
+    logger.info("Quiz completed!");
+    int totalPossibleScore = questions.stream().mapToInt(Question::getScore).sum();
+    logger.info("Your score: {}/{}", quizResult.getScore(), totalPossibleScore);
+  }
+}
diff --git a/src/main/java/idatt2105/group11/idatt2105projectbackend/configuration/SecurityConfiguration.java b/src/main/java/idatt2105/group11/idatt2105projectbackend/configuration/SecurityConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..0679b4aee4995f4187d4077db753f15e1a5e867a
--- /dev/null
+++ b/src/main/java/idatt2105/group11/idatt2105projectbackend/configuration/SecurityConfiguration.java
@@ -0,0 +1,93 @@
+package idatt2105.group11.idatt2105projectbackend.configuration;
+
+
+import com.nimbusds.jose.jwk.JWK;
+import com.nimbusds.jose.jwk.JWKSet;
+import com.nimbusds.jose.jwk.RSAKey;
+import com.nimbusds.jose.jwk.source.ImmutableJWKSet;
+import com.nimbusds.jose.jwk.source.JWKSource;
+import com.nimbusds.jose.proc.SecurityContext;
+import idatt2105.group11.idatt2105projectbackend.utils.RSAKeyProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.ProviderManager;
+import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.oauth2.jwt.JwtDecoder;
+import org.springframework.security.oauth2.jwt.JwtEncoder;
+import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
+import org.springframework.security.oauth2.jwt.NimbusJwtEncoder;
+import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
+import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;
+import org.springframework.security.web.SecurityFilterChain;
+
+@Configuration
+public class SecurityConfiguration {
+
+  private final RSAKeyProperties keys;
+
+  public SecurityConfiguration(RSAKeyProperties keys) {
+    this.keys = keys;
+  }
+
+  @Bean
+  public PasswordEncoder passwordEncoder() {
+    return new BCryptPasswordEncoder();
+  }
+
+  @Bean
+  public AuthenticationManager authenticationManager(UserDetailsService userDetailsService, PasswordEncoder encoder) {
+    DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
+    daoAuthenticationProvider.setUserDetailsService(userDetailsService);
+    daoAuthenticationProvider.setPasswordEncoder(encoder);
+    return new ProviderManager(daoAuthenticationProvider);
+  }
+
+  @Bean
+  public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
+    return httpSecurity
+            .csrf(AbstractHttpConfigurer::disable)
+            .authorizeHttpRequests(auth -> {
+              auth.requestMatchers("/api/").permitAll();
+              auth.anyRequest().authenticated();
+
+            })
+            .oauth2ResourceServer((configurer) ->
+                    configurer.jwt(
+                            jwtConfigurer -> jwtConfigurer.jwtAuthenticationConverter(jwtAuthenticationConverter())
+                    )
+            )
+            .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
+            .build();
+  }
+
+  @Bean
+  public JwtDecoder jwtDecoder() {
+    return NimbusJwtDecoder.withPublicKey(keys.getPublicKey()).build();
+  }
+
+  @Bean
+  public JwtEncoder jwtEncoder() {
+    JWK jwk = new RSAKey.Builder(keys.getPublicKey()).privateKey(keys.getPrivateKey()).build();
+    JWKSource<SecurityContext> jwkSource = new ImmutableJWKSet<>(new JWKSet(jwk));
+    return new NimbusJwtEncoder(jwkSource);
+  }
+
+  @Bean
+  public JwtAuthenticationConverter jwtAuthenticationConverter() {
+    JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
+    jwtGrantedAuthoritiesConverter.setAuthoritiesClaimName("roles");
+    jwtGrantedAuthoritiesConverter.setAuthorityPrefix("ROLE_");
+
+    JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
+    jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(jwtGrantedAuthoritiesConverter);
+
+    return jwtAuthenticationConverter;
+  }
+}
diff --git a/src/main/java/idatt2105/group11/idatt2105projectbackend/controller/AuthenticationController.java b/src/main/java/idatt2105/group11/idatt2105projectbackend/controller/AuthenticationController.java
new file mode 100644
index 0000000000000000000000000000000000000000..ccd2d1d24d4b3fc9f8506f03bfa59a0606f0e561
--- /dev/null
+++ b/src/main/java/idatt2105/group11/idatt2105projectbackend/controller/AuthenticationController.java
@@ -0,0 +1,44 @@
+package idatt2105.group11.idatt2105projectbackend.controller;
+
+
+import idatt2105.group11.idatt2105projectbackend.dto.LoginResponseDTO;
+import idatt2105.group11.idatt2105projectbackend.dto.TokenDTO;
+import idatt2105.group11.idatt2105projectbackend.dto.UserRegistrationDTO;
+import idatt2105.group11.idatt2105projectbackend.model.User;
+import idatt2105.group11.idatt2105projectbackend.service.AuthenticationService;
+import org.springframework.web.bind.annotation.*;
+
+
+@RestController
+@RequestMapping("/api/auth")
+@CrossOrigin(origins = "http://localhost:5173")
+public class AuthenticationController {
+
+  private final AuthenticationService authService;
+
+  public AuthenticationController(AuthenticationService authService) {
+    this.authService = authService;
+  }
+
+  @PostMapping("/register")
+  public User registerUser(@RequestBody UserRegistrationDTO registrationDTO) {
+    //TODO: Remove return of password, use DTO
+    return authService.registerUser(registrationDTO.getName(), registrationDTO.getPassword());
+  }
+
+  @PostMapping("/login")
+  public LoginResponseDTO loginUser(@RequestBody UserRegistrationDTO registrationDTO) {
+    return authService.loginUser(registrationDTO.getName(), registrationDTO.getPassword());
+  }
+
+  @PostMapping("/refresh")
+  public TokenDTO refreshJWT(@RequestBody TokenDTO existingToken) throws InterruptedException {
+    Thread.sleep(500);
+    System.out.println("OLD TOKEN1: " + existingToken);
+    String token = authService.refreshJWT(existingToken.getToken());
+    System.out.println("OLD TOKEN2: " + existingToken);
+    System.out.println("NEW TOKEN MAYBE: " + token);
+
+    return new TokenDTO(token);
+  }
+}
diff --git a/src/main/java/idatt2105/group11/idatt2105projectbackend/controller/QuestionAnswerController.java b/src/main/java/idatt2105/group11/idatt2105projectbackend/controller/QuestionAnswerController.java
new file mode 100644
index 0000000000000000000000000000000000000000..2ba6e67ab3ee5fedffa956a9a36859af55ddb0d2
--- /dev/null
+++ b/src/main/java/idatt2105/group11/idatt2105projectbackend/controller/QuestionAnswerController.java
@@ -0,0 +1,37 @@
+package idatt2105.group11.idatt2105projectbackend.controller;
+
+import idatt2105.group11.idatt2105projectbackend.dto.QuestionAnswerDTO;
+import idatt2105.group11.idatt2105projectbackend.model.QuestionAnswer;
+import idatt2105.group11.idatt2105projectbackend.service.QuestionAnswerService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+@RestController
+@RequestMapping("/question-answers")
+public class QuestionAnswerController {
+
+  private final QuestionAnswerService questionAnswerService;
+
+  @Autowired
+  public QuestionAnswerController(QuestionAnswerService questionAnswerService) {
+    this.questionAnswerService = questionAnswerService;
+  }
+
+  @PostMapping("/save")
+  public QuestionAnswerDTO saveAnswer(@RequestParam Integer quizResultId,
+                                      @RequestBody QuestionAnswerDTO answerDTO) {
+    QuestionAnswer savedAnswer = questionAnswerService.saveAnswer(quizResultId, answerDTO);
+    return convertToQuestionAnswerDTO(savedAnswer);
+  }
+
+  private QuestionAnswerDTO convertToQuestionAnswerDTO(QuestionAnswer questionAnswer) {
+    QuestionAnswerDTO dto = new QuestionAnswerDTO();
+    dto.setId(questionAnswer.getId());
+    dto.setQuestionId(questionAnswer.getQuestion().getId());
+    dto.setGivenAnswer(questionAnswer.getGivenAnswer());
+    dto.setCorrect(questionAnswer.isCorrect());
+    return dto;
+  }
+}
diff --git a/src/main/java/idatt2105/group11/idatt2105projectbackend/controller/QuestionController.java b/src/main/java/idatt2105/group11/idatt2105projectbackend/controller/QuestionController.java
new file mode 100644
index 0000000000000000000000000000000000000000..96580e013fc370959124d5f4c683addd42223b27
--- /dev/null
+++ b/src/main/java/idatt2105/group11/idatt2105projectbackend/controller/QuestionController.java
@@ -0,0 +1,57 @@
+package idatt2105.group11.idatt2105projectbackend.controller;
+
+import idatt2105.group11.idatt2105projectbackend.dto.QuestionDTO;
+import idatt2105.group11.idatt2105projectbackend.model.MultipleChoiceQuestion;
+import idatt2105.group11.idatt2105projectbackend.model.Question;
+import idatt2105.group11.idatt2105projectbackend.service.QuestionService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@RestController
+@RequestMapping("/api/questions")
+public class QuestionController {
+
+  private final QuestionService questionService;
+
+  @Autowired
+  public QuestionController(QuestionService questionService) {
+    this.questionService = questionService;
+  }
+
+  @PostMapping
+  public QuestionDTO createMCQuestion(@RequestBody QuestionDTO questionDTO) {
+    MultipleChoiceQuestion question = questionService.createMCQuestion(questionDTO);
+    return convertToDTO(question);
+  }
+
+  @PostMapping("/update")
+  public QuestionDTO updateQuestion(@RequestBody QuestionDTO questionDTO) {
+    return questionService.updateQuestion(questionDTO);
+  }
+
+  @PostMapping("/delete")
+  public void deleteQuestion(@RequestBody Map<String, Integer> payload) {
+    questionService.deleteQuestion(payload.get("id"));
+  }
+
+  @GetMapping("/list")
+  public List<QuestionDTO> getQuestionsByQuizId(@RequestParam Integer quizId) {
+    return questionService.findAllQuestionsByQuizId(quizId).stream()
+            .map((Question question) -> convertToDTO((MultipleChoiceQuestion) question))
+            .collect(Collectors.toList());
+  }
+
+  public QuestionDTO convertToDTO(MultipleChoiceQuestion question) {
+    QuestionDTO questionDTO = new QuestionDTO();
+    questionDTO.setId(question.getId());
+    questionDTO.setQuestionText(question.getQuestionText());
+    questionDTO.setScore(question.getScore());
+    questionDTO.setAnswerOptions(question.getAnswerOptions());
+    questionDTO.setCorrectAnswerIndex(question.getCorrectAnswerIndex());
+    return questionDTO;
+  }
+}
diff --git a/src/main/java/idatt2105/group11/idatt2105projectbackend/controller/QuizController.java b/src/main/java/idatt2105/group11/idatt2105projectbackend/controller/QuizController.java
new file mode 100644
index 0000000000000000000000000000000000000000..efb1ecd213e77191a5a30cd05d930b4a5416f021
--- /dev/null
+++ b/src/main/java/idatt2105/group11/idatt2105projectbackend/controller/QuizController.java
@@ -0,0 +1,90 @@
+package idatt2105.group11.idatt2105projectbackend.controller;
+
+import idatt2105.group11.idatt2105projectbackend.dto.*;
+import idatt2105.group11.idatt2105projectbackend.exception.UserNotFoundException;
+import idatt2105.group11.idatt2105projectbackend.model.*;
+import idatt2105.group11.idatt2105projectbackend.service.QuizService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+
+@RestController
+@RequestMapping("/api/quiz")
+public class QuizController {
+
+  private final QuizService quizService;
+
+  @Autowired
+  public QuizController(QuizService quizService) {
+    this.quizService = quizService;
+  }
+
+  @PostMapping("/create")
+  public QuizDTO createQuiz(@RequestBody QuizDTO quizDTO) {
+    Quiz quiz = quizService.createQuiz(quizDTO);
+    return convertToDTO(quiz);
+  }
+
+  @PostMapping("/update")
+  public QuizDTO updateQuiz(@RequestBody QuizDTO quizDTO) {
+    return quizService.updateQuiz(quizDTO);
+  }
+
+  @PostMapping("/delete")
+  public void deleteQuiz(@RequestBody Map<String, Integer> payload) {
+    quizService.deleteQuiz(payload.get("id"));
+  }
+
+  @GetMapping("/quiz")
+  public QuizDTO getQuizById(@RequestParam Integer quizId) {
+    return convertToDTO(quizService.findQuizById(quizId));
+  }
+
+
+  @GetMapping("/")
+  public List<QuizDTO> getQuizzes() {
+    return quizService.findAllQuizzes().stream()
+            .map(this::convertToDTO)
+            .collect(Collectors.toList());
+  }
+
+  @GetMapping("/category")
+  public List<QuizDTO> getQuizzesByCategory(@RequestParam String category) {
+    return quizService.findAllQuizzesByCategory(QuizCategory.valueOf(category)).stream()
+            .map(this::convertToDTO)
+            .collect(Collectors.toList());
+  }
+
+  @GetMapping("/difficulty")
+  public List<QuizDTO> getQuizzesByDifficulty(@RequestParam String difficulty) {
+    return quizService.findAllQuizzesByDifficulty(QuizDifficulty.valueOf(difficulty)).stream()
+            .map(this::convertToDTO)
+            .collect(Collectors.toList());
+  }
+
+  @GetMapping("/creator")
+  public List<QuizDTO> getQuizzesByCreatorId(@RequestParam Integer creatorId) {
+    return quizService.findAllQuizzesByCreatorId(creatorId).stream()
+            .map(this::convertToDTO)
+            .collect(Collectors.toList());
+  }
+
+  public QuizDTO convertToDTO(Quiz quiz) {
+    QuizDTO quizDTO = new QuizDTO();
+    quizDTO.setId(quiz.getId());
+    quizDTO.setTitle(quiz.getTitle());
+    quizDTO.setCategory(quiz.getCategory());
+    List<Integer> questionIds = quiz.getQuestions().stream()
+            .map(Question::getId)
+            .collect(Collectors.toList());
+    quizDTO.setQuestionIds(questionIds);
+    return quizDTO;
+  }
+
+}
diff --git a/src/main/java/idatt2105/group11/idatt2105projectbackend/controller/QuizResultController.java b/src/main/java/idatt2105/group11/idatt2105projectbackend/controller/QuizResultController.java
new file mode 100644
index 0000000000000000000000000000000000000000..e301efabc8abaf1aa8d33d2a882e4ba72fb36c5e
--- /dev/null
+++ b/src/main/java/idatt2105/group11/idatt2105projectbackend/controller/QuizResultController.java
@@ -0,0 +1,61 @@
+package idatt2105.group11.idatt2105projectbackend.controller;
+
+import idatt2105.group11.idatt2105projectbackend.dto.QuizResultDTO;
+import idatt2105.group11.idatt2105projectbackend.model.QuizResult;
+import idatt2105.group11.idatt2105projectbackend.service.QuizResultService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@RestController
+@RequestMapping("/api/results")
+public class QuizResultController {
+
+  private final QuizResultService quizResultService;
+
+  @Autowired
+  public QuizResultController(QuizResultService quizResultService) {
+    this.quizResultService = quizResultService;
+  }
+
+  @PostMapping("/create")
+  public QuizResultDTO startQuizResult(@RequestBody QuizResultDTO quizResultDTO) {
+    return convertToQuizResultDTO(quizResultService.startQuizResult(quizResultDTO));
+  }
+
+  @PostMapping("/complete/")
+  public QuizResultDTO completeQuiz(@RequestParam Integer quizResultId) {
+    return quizResultService.completeQuiz(quizResultId);
+  }
+
+  @GetMapping("/latest-result")
+  public QuizResultDTO getLatestQuizResultForUser(@RequestParam Integer userId) {
+    return quizResultService.findLatestQuizResultForUser(userId);
+  }
+
+
+  @GetMapping("/results")
+  public List<QuizResultDTO> getQuizResultsForUser(@RequestParam("userId") Integer userId) {
+    List<QuizResult> quizResults = quizResultService.findAllResultsForUserId(userId);
+    return quizResults.stream()
+            .map(this::convertToQuizResultDTO)
+            .collect(Collectors.toList());
+  }
+
+  public QuizResultDTO convertToQuizResultDTO(QuizResult quizResult) {
+    QuizResultDTO quizResultDTO = new QuizResultDTO();
+    quizResultDTO.setQuizId(quizResult.getQuiz().getId());
+    quizResultDTO.setUserId(quizResult.getUser().getId());
+    quizResultDTO.setScore(quizResult.getScore());
+    quizResultDTO.setStatus(quizResult.getStatus());
+    quizResultDTO.setStartedAt(quizResult.getStartedAt());
+    quizResultDTO.setCompletedAt(quizResult.getCompletedAt());
+
+    return quizResultDTO;
+  }
+
+
+}
diff --git a/src/main/java/idatt2105/group11/idatt2105projectbackend/controller/UserController.java b/src/main/java/idatt2105/group11/idatt2105projectbackend/controller/UserController.java
new file mode 100644
index 0000000000000000000000000000000000000000..8aed1a6f88950a2b4ce9e05db96843d80f541830
--- /dev/null
+++ b/src/main/java/idatt2105/group11/idatt2105projectbackend/controller/UserController.java
@@ -0,0 +1,27 @@
+package idatt2105.group11.idatt2105projectbackend.controller;
+
+
+import idatt2105.group11.idatt2105projectbackend.model.User;
+import idatt2105.group11.idatt2105projectbackend.service.UserService;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+
+@RestController
+@RequestMapping("/api/user")
+@CrossOrigin(origins = "http://localhost:5173")
+public class UserController {
+
+  private final UserService userService;
+
+  public UserController(UserService userService) {
+    this.userService = userService;
+  }
+
+
+  @GetMapping("/")
+  public List<User> getAppUsers() {
+    return userService.findAllAppUsers();
+  }
+}
diff --git a/src/main/java/idatt2105/group11/idatt2105projectbackend/dto/LoginResponseDTO.java b/src/main/java/idatt2105/group11/idatt2105projectbackend/dto/LoginResponseDTO.java
new file mode 100644
index 0000000000000000000000000000000000000000..6abc9a4b701dd234a38844cbe35e8c2337ee5e0e
--- /dev/null
+++ b/src/main/java/idatt2105/group11/idatt2105projectbackend/dto/LoginResponseDTO.java
@@ -0,0 +1,53 @@
+package idatt2105.group11.idatt2105projectbackend.dto;
+
+import idatt2105.group11.idatt2105projectbackend.model.User;
+
+public class LoginResponseDTO {
+
+  private String name;
+  private String password;
+  private String jwt;
+
+  public LoginResponseDTO() {
+    super();
+  }
+
+  public LoginResponseDTO(User user, String jwt) {
+    this.name = user.getName();
+    this.password = user.getPassword();
+    this.jwt = jwt;
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public void setName(String username) {
+    this.name = name;
+  }
+
+  public String getPassword() {
+    return password;
+  }
+
+  public void setPassword(String password) {
+    this.password = password;
+  }
+
+  public String getJwt() {
+    return jwt;
+  }
+
+  public void setJwt(String jwt) {
+    this.jwt = jwt;
+  }
+
+  @Override
+  public String toString() {
+    return "LoginResponseDTO{" +
+            "username='" + name + '\'' +
+            ", password='" + password + '\'' +
+            ", jwt='" + jwt + '\'' +
+            '}';
+  }
+}
diff --git a/src/main/java/idatt2105/group11/idatt2105projectbackend/dto/QuestionAnswerDTO.java b/src/main/java/idatt2105/group11/idatt2105projectbackend/dto/QuestionAnswerDTO.java
new file mode 100644
index 0000000000000000000000000000000000000000..e8e9a930e10bc83d7cdb0dd3578dfea5f671cbcd
--- /dev/null
+++ b/src/main/java/idatt2105/group11/idatt2105projectbackend/dto/QuestionAnswerDTO.java
@@ -0,0 +1,60 @@
+package idatt2105.group11.idatt2105projectbackend.dto;
+
+public class QuestionAnswerDTO {
+  private Integer id;
+  private Integer questionId;
+  private String givenAnswer;
+  private boolean correct;
+
+  public QuestionAnswerDTO() {
+  }
+
+  public QuestionAnswerDTO(Integer id, Integer questionId, String givenAnswer, boolean correct) {
+    this.id = id;
+    this.questionId = questionId;
+    this.givenAnswer = givenAnswer;
+    this.correct = correct;
+  }
+
+  public Integer getId() {
+    return id;
+  }
+
+  public void setId(Integer id) {
+    this.id = id;
+  }
+
+  public Integer getQuestionId() {
+    return questionId;
+  }
+
+  public void setQuestionId(Integer questionId) {
+    this.questionId = questionId;
+  }
+
+  public String getGivenAnswer() {
+    return givenAnswer;
+  }
+
+  public void setGivenAnswer(String givenAnswer) {
+    this.givenAnswer = givenAnswer;
+  }
+
+  public boolean isCorrect() {
+    return correct;
+  }
+
+  public void setCorrect(boolean correct) {
+    this.correct = correct;
+  }
+
+  @Override
+  public String toString() {
+    return "QuestionAnswerDTO{" +
+            "id=" + id +
+            ", questionId=" + questionId +
+            ", givenAnswer='" + givenAnswer + '\'' +
+            ", correct=" + correct +
+            '}';
+  }
+}
diff --git a/src/main/java/idatt2105/group11/idatt2105projectbackend/dto/QuestionDTO.java b/src/main/java/idatt2105/group11/idatt2105projectbackend/dto/QuestionDTO.java
new file mode 100644
index 0000000000000000000000000000000000000000..43511a249edf0abc2b601cfaab074b53c3c30fe2
--- /dev/null
+++ b/src/main/java/idatt2105/group11/idatt2105projectbackend/dto/QuestionDTO.java
@@ -0,0 +1,64 @@
+package idatt2105.group11.idatt2105projectbackend.dto;
+
+import java.util.List;
+
+public class QuestionDTO {
+  private Integer id;
+  private String questionText;
+  private int score;
+  private List<String> answerOptions;
+  private int correctAnswerIndex;
+
+
+  public QuestionDTO() {
+  }
+
+  public QuestionDTO(Integer id, String questionText, int score) {
+    this.id = id;
+    this.questionText = questionText;
+    this.score = score;
+  }
+
+  // Getters and setters
+  public Integer getId() {
+    return id;
+  }
+
+  public void setId(Integer id) {
+    this.id = id;
+  }
+
+  public String getQuestionText() {
+    return questionText;
+  }
+
+  public void setQuestionText(String questionText) {
+    this.questionText = questionText;
+  }
+
+  public int getScore() {
+    return score;
+  }
+
+  public void setScore(int score) {
+    this.score = score;
+  }
+
+  public List<String> getAnswerOptions() {
+    return answerOptions;
+  }
+
+  public void setAnswerOptions(List<String> answerOptions) {
+    this.answerOptions = answerOptions;
+  }
+
+  public int getCorrectAnswerIndex() {
+    return correctAnswerIndex;
+  }
+
+  public void setCorrectAnswerIndex(int correctAnswerIndex) {
+    this.correctAnswerIndex = correctAnswerIndex;
+  }
+
+
+}
diff --git a/src/main/java/idatt2105/group11/idatt2105projectbackend/dto/QuizDTO.java b/src/main/java/idatt2105/group11/idatt2105projectbackend/dto/QuizDTO.java
new file mode 100644
index 0000000000000000000000000000000000000000..8ca7f073d1435bc0aa745b52cee9b1d7a8e14357
--- /dev/null
+++ b/src/main/java/idatt2105/group11/idatt2105projectbackend/dto/QuizDTO.java
@@ -0,0 +1,76 @@
+package idatt2105.group11.idatt2105projectbackend.dto;
+
+import idatt2105.group11.idatt2105projectbackend.model.Quiz;
+import idatt2105.group11.idatt2105projectbackend.model.QuizCategory;
+import idatt2105.group11.idatt2105projectbackend.model.QuizDifficulty;
+
+import java.util.List;
+
+public class QuizDTO {
+  private Integer id;
+  private String title;
+  private List<Integer> questionIds;
+  private Integer creatorId;
+  private QuizCategory category;
+  private QuizDifficulty difficulty;
+
+  public QuizDTO() {
+  }
+
+  public QuizDTO(Integer id, String title, List<Integer> questionIds, Integer creatorId, QuizCategory category, QuizDifficulty difficulty) {
+    this.title = title;
+    this.questionIds = questionIds;
+    this.creatorId = creatorId;
+    this.category = category;
+    this.difficulty = difficulty;
+  }
+
+  // Getters and setters
+  public Integer getId() {
+    return id;
+  }
+
+  public void setId(Integer id) {
+    this.id = id;
+  }
+
+  public String getTitle() {
+    return title;
+  }
+
+  public void setTitle(String title) {
+    this.title = title;
+  }
+
+  public Iterable<Integer> getQuestionIds() {
+    return questionIds;
+  }
+
+  public void setQuestionIds(List<Integer> questionIds) {
+    this.questionIds = questionIds;
+  }
+
+  public Integer getCreatorId() {
+    return creatorId;
+  }
+
+  public void setCreatorId(Integer creatorId) {
+    this.creatorId = creatorId;
+  }
+
+  public QuizCategory getCategory() {
+    return category;
+  }
+
+  public void setCategory(QuizCategory category) {
+    this.category = category;
+  }
+
+  public QuizDifficulty getDifficulty() {
+    return difficulty;
+  }
+
+  public void setDifficulty(QuizDifficulty difficulty) {
+    this.difficulty = difficulty;
+  }
+}
diff --git a/src/main/java/idatt2105/group11/idatt2105projectbackend/dto/QuizResultDTO.java b/src/main/java/idatt2105/group11/idatt2105projectbackend/dto/QuizResultDTO.java
new file mode 100644
index 0000000000000000000000000000000000000000..ca90fa8f7b96ca0c3936fcf2d418a93c0d03c495
--- /dev/null
+++ b/src/main/java/idatt2105/group11/idatt2105projectbackend/dto/QuizResultDTO.java
@@ -0,0 +1,105 @@
+package idatt2105.group11.idatt2105projectbackend.dto;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+public class QuizResultDTO {
+  private Integer id;
+  private Integer quizId;
+  private Integer userId;
+  private List<QuestionAnswerDTO> answers;
+  private int score;
+  private String status;
+  private LocalDateTime startedAt;
+  private LocalDateTime completedAt;
+
+
+  public QuizResultDTO() {
+  }
+
+  public QuizResultDTO(Integer id, Integer quizId, Integer userId, List<QuestionAnswerDTO> answers, int score, String status, LocalDateTime startedAt, LocalDateTime completedAt) {
+    this.id = id;
+    this.quizId = quizId;
+    this.userId = userId;
+    this.answers = answers;
+    this.score = score;
+    this.status = status;
+    this.startedAt = startedAt;
+    this.completedAt = completedAt;
+  }
+
+  public Integer getId() {
+    return id;
+  }
+
+  public void setId(Integer id) {
+    this.id = id;
+  }
+
+  public Integer getQuizId() {
+    return quizId;
+  }
+
+  public void setQuizId(Integer quizId) {
+    this.quizId = quizId;
+  }
+
+  public Integer getUserId() {
+    return userId;
+  }
+
+  public void setUserId(Integer userId) {
+    this.userId = userId;
+  }
+
+  public List<QuestionAnswerDTO> getAnswers() {
+    return answers;
+  }
+
+  public void setAnswers(List<QuestionAnswerDTO> answers) {
+    this.answers = answers;
+  }
+
+  public int getScore() {
+    return score;
+  }
+
+  public void setScore(int score) {
+    this.score = score;
+  }
+
+  public String getStatus() {
+    return status;
+  }
+
+  public void setStatus(String status) {
+    this.status = status;
+  }
+
+  public LocalDateTime getStartedAt() {
+    return startedAt;
+  }
+
+  public void setStartedAt(LocalDateTime startedAt) {
+    this.startedAt = startedAt;
+  }
+
+  public LocalDateTime getCompletedAt() {
+    return completedAt;
+  }
+
+  public void setCompletedAt(LocalDateTime completedAt) {
+    this.completedAt = completedAt;
+  }
+
+  @Override
+  public String toString() {
+    return "QuizResultDTO{" +
+            "id=" + id +
+            ", quizId=" + quizId +
+            ", userId=" + userId +
+            ", answers=" + answers +
+            ", score=" + score +
+            '}';
+  }
+}
diff --git a/src/main/java/idatt2105/group11/idatt2105projectbackend/dto/TokenDTO.java b/src/main/java/idatt2105/group11/idatt2105projectbackend/dto/TokenDTO.java
new file mode 100644
index 0000000000000000000000000000000000000000..3663df5be9b4c3deabd5a7cce812d4254d00beb4
--- /dev/null
+++ b/src/main/java/idatt2105/group11/idatt2105projectbackend/dto/TokenDTO.java
@@ -0,0 +1,30 @@
+package idatt2105.group11.idatt2105projectbackend.dto;
+
+
+public class TokenDTO {
+  private String token;
+
+  public TokenDTO() {
+    super();
+  }
+
+  public TokenDTO(String token) {
+    super();
+    this.token = token;
+  }
+
+  public String getToken() {
+    return token;
+  }
+
+  public void setToken(String token) {
+    this.token = token;
+  }
+
+  @Override
+  public String toString() {
+    return "TokenDTO{" +
+            "token='" + token + '\'' +
+            '}';
+  }
+}
diff --git a/src/main/java/idatt2105/group11/idatt2105projectbackend/dto/UserDTO.java b/src/main/java/idatt2105/group11/idatt2105projectbackend/dto/UserDTO.java
new file mode 100644
index 0000000000000000000000000000000000000000..e849b91953f0686bb7389f93007d430739a986c3
--- /dev/null
+++ b/src/main/java/idatt2105/group11/idatt2105projectbackend/dto/UserDTO.java
@@ -0,0 +1,27 @@
+package idatt2105.group11.idatt2105projectbackend.dto;
+
+import java.util.List;
+
+public class UserDTO extends UserRegistrationDTO {
+  private Integer id;
+
+  // Assuming you might need more fields here, such as role, etc.
+
+  public UserDTO() {
+    super();
+  }
+
+  public UserDTO(Integer id, String name, String password) {
+    super(name, password);
+    this.id = id;
+  }
+
+  // Getters and setters for the 'id' field
+  public Integer getId() {
+    return id;
+  }
+
+  public void setId(Integer id) {
+    this.id = id;
+  }
+}
diff --git a/src/main/java/idatt2105/group11/idatt2105projectbackend/dto/UserRegistrationDTO.java b/src/main/java/idatt2105/group11/idatt2105projectbackend/dto/UserRegistrationDTO.java
new file mode 100644
index 0000000000000000000000000000000000000000..586b8fa8399d034e48f4f2ad2f23f71b0a8ac719
--- /dev/null
+++ b/src/main/java/idatt2105/group11/idatt2105projectbackend/dto/UserRegistrationDTO.java
@@ -0,0 +1,43 @@
+package idatt2105.group11.idatt2105projectbackend.dto;
+
+public class UserRegistrationDTO {
+
+  private String name;
+  private String password;
+
+
+  public UserRegistrationDTO() {
+    super();
+  }
+
+  public UserRegistrationDTO(String name, String password) {
+    this.name = name;
+    this.password = password;
+  }
+
+  // Getters and setters
+
+  public String getName() {
+    return name;
+  }
+
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  public String getPassword() {
+    return password;
+  }
+
+  public void setPassword(String password) {
+    this.password = password;
+  }
+
+  @Override
+  public String toString() {
+    return "UserRegistrationDTO{" +
+            "username='" + name + '\'' +
+            ", password='" + password + '\'' +
+            '}';
+  }
+}
diff --git a/src/main/java/idatt2105/group11/idatt2105projectbackend/exception/QuestionNotFoundException.java b/src/main/java/idatt2105/group11/idatt2105projectbackend/exception/QuestionNotFoundException.java
new file mode 100644
index 0000000000000000000000000000000000000000..bde8a6a8374eead1e2a033a2b43d8de32c48b73e
--- /dev/null
+++ b/src/main/java/idatt2105/group11/idatt2105projectbackend/exception/QuestionNotFoundException.java
@@ -0,0 +1,7 @@
+package idatt2105.group11.idatt2105projectbackend.exception;
+
+public class QuestionNotFoundException extends RuntimeException {
+  public QuestionNotFoundException(String message) {
+    super(message);
+  }
+}
\ No newline at end of file
diff --git a/src/main/java/idatt2105/group11/idatt2105projectbackend/exception/QuizNotFoundException.java b/src/main/java/idatt2105/group11/idatt2105projectbackend/exception/QuizNotFoundException.java
new file mode 100644
index 0000000000000000000000000000000000000000..d49ab7e6cb8c2da6393b5c6ab6f58845b54184f6
--- /dev/null
+++ b/src/main/java/idatt2105/group11/idatt2105projectbackend/exception/QuizNotFoundException.java
@@ -0,0 +1,8 @@
+package idatt2105.group11.idatt2105projectbackend.exception;
+
+
+public class QuizNotFoundException extends RuntimeException {
+  public QuizNotFoundException(String message) {
+    super(message);
+  }
+}
\ No newline at end of file
diff --git a/src/main/java/idatt2105/group11/idatt2105projectbackend/exception/UserNotFoundException.java b/src/main/java/idatt2105/group11/idatt2105projectbackend/exception/UserNotFoundException.java
new file mode 100644
index 0000000000000000000000000000000000000000..5a0b429d45e440089073b74444c5539f7b2abc23
--- /dev/null
+++ b/src/main/java/idatt2105/group11/idatt2105projectbackend/exception/UserNotFoundException.java
@@ -0,0 +1,8 @@
+package idatt2105.group11.idatt2105projectbackend.exception;
+
+
+public class UserNotFoundException extends RuntimeException {
+  public UserNotFoundException(String message) {
+    super(message);
+  }
+}
\ No newline at end of file
diff --git a/src/main/java/idatt2105/group11/idatt2105projectbackend/model/MultipleChoiceQuestion.java b/src/main/java/idatt2105/group11/idatt2105projectbackend/model/MultipleChoiceQuestion.java
new file mode 100644
index 0000000000000000000000000000000000000000..3860211ee4d98725a7e770c95051d6382432b626
--- /dev/null
+++ b/src/main/java/idatt2105/group11/idatt2105projectbackend/model/MultipleChoiceQuestion.java
@@ -0,0 +1,51 @@
+package idatt2105.group11.idatt2105projectbackend.model;
+
+import jakarta.persistence.*;
+
+import java.util.List;
+
+@Entity
+public class MultipleChoiceQuestion extends Question {
+  @ElementCollection
+  @CollectionTable(name = "answer_options", joinColumns = @JoinColumn(name = "question_id"))
+  @Column(name = "option")
+  private List<String> answerOptions;
+
+  @Column(nullable = false)
+  private int correctAnswerIndex;
+
+  public MultipleChoiceQuestion() {
+  }
+
+  public MultipleChoiceQuestion(Quiz quiz, String questionText, int score, List<String> answerOptions, int correctAnswerIndex) {
+    super(quiz, questionText, score);
+    this.answerOptions = answerOptions;
+    this.correctAnswerIndex = correctAnswerIndex;
+  }
+
+  public List<String> getAnswerOptions() {
+    return answerOptions;
+  }
+
+  public void setAnswerOptions(List<String> answerOptions) {
+    this.answerOptions = answerOptions;
+  }
+
+  public int getCorrectAnswerIndex() {
+    return correctAnswerIndex;
+  }
+
+  public void setCorrectAnswerIndex(int correctAnswerIndex) {
+    this.correctAnswerIndex = correctAnswerIndex;
+  }
+
+  @Override
+  public boolean checkAnswer(String answer) {
+    try {
+      int answerIndex = Integer.parseInt(answer);
+      return answerIndex == correctAnswerIndex + 1;
+    } catch (NumberFormatException e) {
+      return false;
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/main/java/idatt2105/group11/idatt2105projectbackend/model/Question.java b/src/main/java/idatt2105/group11/idatt2105projectbackend/model/Question.java
new file mode 100644
index 0000000000000000000000000000000000000000..43551670e3194a45aacb9bf419191d70c5e209e2
--- /dev/null
+++ b/src/main/java/idatt2105/group11/idatt2105projectbackend/model/Question.java
@@ -0,0 +1,62 @@
+package idatt2105.group11.idatt2105projectbackend.model;
+
+import jakarta.persistence.*;
+
+@Entity
+@Inheritance(strategy = InheritanceType.JOINED)
+public abstract class Question {
+  @Id
+  @GeneratedValue(strategy = GenerationType.IDENTITY)
+  private Integer id;
+
+  @ManyToOne
+  @JoinColumn(name = "quiz_id")
+  private Quiz quiz;
+
+  @Column(nullable = false)
+  private String questionText;
+
+  @Column(nullable = false)
+  private int score;
+
+  public Question() {
+  }
+
+  public Question(Quiz quiz, String questionText, int score) {
+    this.questionText = questionText;
+    this.score = score;
+  }
+
+  public Integer getId() {
+    return id;
+  }
+
+  public void setId(Integer id) {
+    this.id = id;
+  }
+
+  public String getQuestionText() {
+    return questionText;
+  }
+
+  public void setQuestionText(String questionText) {
+    this.questionText = questionText;
+  }
+
+  public int getScore() {
+    return score;
+  }
+
+  public void setScore(int score) {
+    this.score = score;
+  }
+
+  public abstract boolean checkAnswer(String answer);
+
+  public Quiz getQuiz() {
+    return quiz;
+  }
+  public void setQuiz(Quiz quiz) {
+    this.quiz = quiz;
+  }
+}
diff --git a/src/main/java/idatt2105/group11/idatt2105projectbackend/model/QuestionAnswer.java b/src/main/java/idatt2105/group11/idatt2105projectbackend/model/QuestionAnswer.java
new file mode 100644
index 0000000000000000000000000000000000000000..615243610fea4b81b934c89181007e13ea28b28c
--- /dev/null
+++ b/src/main/java/idatt2105/group11/idatt2105projectbackend/model/QuestionAnswer.java
@@ -0,0 +1,83 @@
+package idatt2105.group11.idatt2105projectbackend.model;
+
+import jakarta.persistence.*;
+
+@Entity
+public class QuestionAnswer {
+  @Id
+  @GeneratedValue(strategy = GenerationType.IDENTITY)
+  private Integer id;
+
+  @ManyToOne(fetch = FetchType.LAZY)
+  @JoinColumn(name = "question_id")
+  private Question question;
+
+  @Column(nullable = false)
+  private String givenAnswer;
+
+  @Column(nullable = false)
+  private boolean correct;
+
+  @ManyToOne(fetch = FetchType.LAZY)
+  @JoinColumn(name = "quiz_result_id")
+  private QuizResult quizResult;
+
+  public QuestionAnswer() {
+    // JPA requires a no-arg constructor
+  }
+
+  public QuestionAnswer(Question question, String givenAnswer) {
+    this.question = question;
+    this.givenAnswer = givenAnswer;
+    this.correct = validateAnswer(givenAnswer);
+  }
+
+  // Validation method
+  private boolean validateAnswer(String givenAnswer) {
+    return question.checkAnswer(givenAnswer);
+  }
+
+  public Integer getId() {
+    return id;
+  }
+
+  public void setId(Integer id) {
+    this.id = id;
+  }
+
+  public Question getQuestion() {
+    return question;
+  }
+
+  public void setQuestion(Question question) {
+    this.question = question;
+    // Update 'correct' whenever the question changes
+    this.correct = validateAnswer(this.givenAnswer);
+  }
+
+  public String getGivenAnswer() {
+    return givenAnswer;
+  }
+
+  public void setGivenAnswer(String givenAnswer) {
+    this.givenAnswer = givenAnswer;
+    // Update 'correct' whenever the given answer changes
+    this.correct = validateAnswer(givenAnswer);
+  }
+
+  public boolean isCorrect() {
+    return correct;
+  }
+
+  public void setCorrect(boolean correct) {
+    this.correct = correct;
+  }
+
+
+  public QuizResult getQuizResult() {
+    return quizResult;
+  }
+  public void setQuizResult(QuizResult quizResult) {
+    this.quizResult = quizResult;
+  }
+}
\ No newline at end of file
diff --git a/src/main/java/idatt2105/group11/idatt2105projectbackend/model/Quiz.java b/src/main/java/idatt2105/group11/idatt2105projectbackend/model/Quiz.java
new file mode 100644
index 0000000000000000000000000000000000000000..a0bb5a153a199663d97dad16dd8219eec3f76989
--- /dev/null
+++ b/src/main/java/idatt2105/group11/idatt2105projectbackend/model/Quiz.java
@@ -0,0 +1,90 @@
+package idatt2105.group11.idatt2105projectbackend.model;
+
+import jakarta.persistence.*;
+
+import java.util.List;
+
+
+@Entity
+public class Quiz {
+  @Id
+  @GeneratedValue(strategy = GenerationType.IDENTITY)
+  private Integer id;
+
+  @Column(nullable = false)
+  private String title;
+
+  @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
+  @JoinColumn(name = "quiz_id")
+  private List<Question> questions;
+
+
+  @ManyToOne(fetch = FetchType.LAZY)
+  @JoinColumn(name = "creator_id")
+  private User creator;
+
+  @Enumerated(EnumType.STRING)
+  private QuizCategory category;
+
+  @Enumerated(EnumType.STRING)
+  private QuizDifficulty difficulty;
+
+  public Quiz() {
+  }
+
+  public Quiz(String title, List<Question> questions, User creator, QuizCategory category, QuizDifficulty difficulty) {
+    this.title = title;
+    this.questions = questions;
+    this.creator = creator;
+    this.category = category;
+    this.difficulty = difficulty;
+
+  }
+
+  public Integer getId() {
+    return id;
+  }
+
+  public void setId(Integer id) {
+    this.id = id;
+  }
+
+  public String getTitle() {
+    return title;
+  }
+
+  public void setTitle(String title) {
+    this.title = title;
+  }
+
+  public List<Question> getQuestions() {
+    return questions;
+  }
+
+  public void setQuestions(List<Question> questions) {
+    this.questions = questions;
+  }
+
+  public User getCreator() {
+    return creator;
+  }
+
+  public QuizCategory getCategory() {
+    return category;
+  }
+  public void setCategory(QuizCategory category) {
+    this.category = category;
+  }
+
+  public void setCreator(User creator) {
+    this.creator = creator;
+  }
+
+  public QuizDifficulty getDifficulty() {
+    return difficulty;
+  }
+
+  public void setDifficulty(QuizDifficulty difficulty) {
+    this.difficulty = difficulty;
+  }
+}
diff --git a/src/main/java/idatt2105/group11/idatt2105projectbackend/model/QuizCategory.java b/src/main/java/idatt2105/group11/idatt2105projectbackend/model/QuizCategory.java
new file mode 100644
index 0000000000000000000000000000000000000000..d3b61a168d77f5c535ec36cb7f4cfac60316d3ca
--- /dev/null
+++ b/src/main/java/idatt2105/group11/idatt2105projectbackend/model/QuizCategory.java
@@ -0,0 +1,21 @@
+package idatt2105.group11.idatt2105projectbackend.model;
+
+public enum QuizCategory {
+  BUSINESS,
+  ART,
+  COMPUTER_SCIENCE,
+  CULTURE_AND_TRADITIONS,
+  FINANCE,
+  GENERAL_KNOWLEDGE,
+  GEOGRAPHY,
+  HISTORY,
+  LANGUAGES,
+  LAW,
+  MATH,
+  MUSIC,
+  SCIENCE,
+  SEASONAL,
+  SOCIAL_EMOTIONAL_LEARNING,
+  SOCIAL_STUDIES,
+  TRIVIA
+}
diff --git a/src/main/java/idatt2105/group11/idatt2105projectbackend/model/QuizDifficulty.java b/src/main/java/idatt2105/group11/idatt2105projectbackend/model/QuizDifficulty.java
new file mode 100644
index 0000000000000000000000000000000000000000..6d3d97cf3a95b16ebca1f9096ffd66bac652217a
--- /dev/null
+++ b/src/main/java/idatt2105/group11/idatt2105projectbackend/model/QuizDifficulty.java
@@ -0,0 +1,7 @@
+package idatt2105.group11.idatt2105projectbackend.model;
+
+public enum QuizDifficulty {
+    EASY,
+    MEDIUM,
+    HARD
+}
diff --git a/src/main/java/idatt2105/group11/idatt2105projectbackend/model/QuizResult.java b/src/main/java/idatt2105/group11/idatt2105projectbackend/model/QuizResult.java
new file mode 100644
index 0000000000000000000000000000000000000000..c4acb5445e1ddf478ca20023e04169d5886bdb53
--- /dev/null
+++ b/src/main/java/idatt2105/group11/idatt2105projectbackend/model/QuizResult.java
@@ -0,0 +1,138 @@
+package idatt2105.group11.idatt2105projectbackend.model;
+
+import jakarta.persistence.*;
+
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.List;
+
+@Entity
+@Table(name = "quiz_results")
+public class QuizResult {
+
+  @Id
+  @GeneratedValue(strategy = GenerationType.IDENTITY)
+  private Integer id;
+
+  @ManyToOne
+  @JoinColumn(name = "quiz_id", nullable = false)
+  private Quiz quiz;
+
+  @OneToMany(mappedBy = "quizResult", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
+  private List<QuestionAnswer> answers = new ArrayList<>();
+
+  @Column(nullable = false)
+  private int score;
+
+  @ManyToOne(fetch = FetchType.LAZY)
+  @JoinColumn(name = "user_id")
+  private User user;
+
+
+  @Column(nullable = false)
+  private String status;
+
+  @Column(nullable = false)
+  private LocalDateTime startedAt;
+
+  @Column
+  private LocalDateTime completedAt;
+
+
+
+
+  public QuizResult() {
+    // JPA requires a no-arg constructor
+  }
+
+  // Constructor for initializing with a quiz and optionally with answers.
+  public QuizResult(Quiz quiz, List<QuestionAnswer> answers, User user, String status, LocalDateTime startedAt, LocalDateTime completedAt) {
+    this.quiz = quiz;
+    this.setAnswers(answers);
+    this.user = user;
+    this.status = status;
+    this.startedAt = startedAt;
+    this.completedAt = completedAt;
+  }
+
+  // Getter and Setter methods
+  public Integer getId() {
+    return id;
+  }
+
+  public void setId(Integer id) {
+    this.id = id;
+  }
+
+  public Quiz getQuiz() {
+    return quiz;
+  }
+
+  public void setQuiz(Quiz quiz) {
+    this.quiz = quiz;
+  }
+
+  public User getUser() {
+    return user;
+  }
+
+  public void setUser(User user) {
+    this.user = user;
+  }
+
+  public List<QuestionAnswer> getAnswers() {
+    return answers;
+  }
+
+  // When setting answers, also recalculate the score based on the correctness and question score.
+  public void setAnswers(List<QuestionAnswer> answers) {
+    this.answers = answers;
+    this.answers.forEach(answer -> answer.setQuizResult(this));
+    calculateScore(); // Recalculate the score based on the new set of answers
+  }
+
+  public int getScore() {
+    return score;
+  }
+
+  public void setScore(int score) {
+    this.score = score;
+  }
+
+  public String getStatus() {
+    return status;
+  }
+
+  public void setStatus(String status) {
+    this.status = status;
+  }
+
+  public LocalDateTime getStartedAt() {
+    return startedAt;
+  }
+
+  public void setStartedAt(LocalDateTime startedAt) {
+    this.startedAt = startedAt;
+  }
+
+  public LocalDateTime getCompletedAt() {
+    return completedAt;
+  }
+
+  public void setCompletedAt(LocalDateTime completedAt) {
+    this.completedAt = completedAt;
+  }
+
+  public void addQuestionAnswer(QuestionAnswer questionAnswer) {
+    this.answers.add(questionAnswer);
+    questionAnswer.setQuizResult(this);
+    calculateScore();
+  }
+
+  private void calculateScore() {
+    this.score = this.answers.stream()
+            .filter(QuestionAnswer::isCorrect)
+            .mapToInt(answer -> answer.getQuestion().getScore())
+            .sum();
+  }
+}
diff --git a/src/main/java/idatt2105/group11/idatt2105projectbackend/model/Role.java b/src/main/java/idatt2105/group11/idatt2105projectbackend/model/Role.java
new file mode 100644
index 0000000000000000000000000000000000000000..02cfab748a4a8fc3f0455b25be2e210c815396c7
--- /dev/null
+++ b/src/main/java/idatt2105/group11/idatt2105projectbackend/model/Role.java
@@ -0,0 +1,62 @@
+package idatt2105.group11.idatt2105projectbackend.model;
+
+
+import jakarta.persistence.Id;
+import jakarta.persistence.Column;
+import jakarta.persistence.Table;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+
+import org.springframework.security.core.GrantedAuthority;
+
+@Entity
+@Table(name = "role")
+public class Role implements GrantedAuthority {
+
+  @Id
+  @GeneratedValue(strategy = GenerationType.AUTO)
+  @Column(name = "role_id")
+  private Integer roleId;
+
+  @Column(nullable = false)
+  private String authority;
+
+  public Role() {
+    super();
+  }
+
+  public Role(String authority) {
+    this.authority = authority;
+  }
+
+  public Role(Integer roleId, String authority) {
+    this.roleId = roleId;
+    this.authority = authority;
+  }
+
+  public Integer getRoleId() {
+    return roleId;
+  }
+
+  public void setRoleId(Integer roleId) {
+    this.roleId = roleId;
+  }
+
+  @Override
+  public String getAuthority() {
+    return this.authority;
+  }
+
+  public void setAuthority(String authority) {
+    this.authority = authority;
+  }
+
+  @Override
+  public String toString() {
+    return "Role{" +
+            "roleId=" + roleId +
+            ", authority='" + authority + '\'' +
+            '}';
+  }
+}
diff --git a/src/main/java/idatt2105/group11/idatt2105projectbackend/model/User.java b/src/main/java/idatt2105/group11/idatt2105projectbackend/model/User.java
new file mode 100644
index 0000000000000000000000000000000000000000..38ac0b49dd27d1cdf18aa72a79988d21268a4ab6
--- /dev/null
+++ b/src/main/java/idatt2105/group11/idatt2105projectbackend/model/User.java
@@ -0,0 +1,132 @@
+package idatt2105.group11.idatt2105projectbackend.model;
+
+import idatt2105.group11.idatt2105projectbackend.model.Quiz;
+import idatt2105.group11.idatt2105projectbackend.model.QuizResult;
+import jakarta.persistence.*;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
+
+import java.util.*;
+
+
+@Entity
+@Table(name = "users")
+public class User implements UserDetails {
+  @Id
+  @GeneratedValue(strategy = GenerationType.IDENTITY)
+  @Column(name = "app_user_id", unique = true)
+  private Integer id;
+
+  @Column(nullable = false, unique = true)
+  private String name;
+
+  @Column(nullable = false)
+  private String password;
+
+  @ManyToMany(fetch = FetchType.EAGER)
+  @JoinTable(name = "app_user_role",
+          joinColumns = {@JoinColumn(name = "app_user_id")},
+          inverseJoinColumns = {@JoinColumn(name = "role_id")}
+  )
+  private Set<Role> authorities;
+
+  // Quizzes created by the user
+  @OneToMany(mappedBy = "creator", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
+  private List<Quiz> createdQuizzes = new ArrayList<>();
+
+  // Quiz attempts by the user
+  @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
+  private List<QuizResult> quizResults = new ArrayList<>();
+
+
+  public User() {
+    this.authorities = new HashSet<>();
+  }
+
+  public User(String name, String password, Set<Role> authorities) {
+    this.name = name;
+    this.password = password;
+    this.authorities = authorities;
+  }
+
+  public User(Integer id, String name, String password, Set<Role> authorities) {
+    this.id = id;
+    this.name = name;
+    this.password = password;
+    this.authorities = authorities;
+  }
+
+  public Integer getId() {
+    return id;
+  }
+
+  public void setId(Integer id) {
+    this.id = id;
+  }
+
+  public List<Quiz> getCreatedQuizzes() {
+    return createdQuizzes;
+  }
+
+  public void setCreatedQuizzes(List<Quiz> createdQuizzes) {
+    this.createdQuizzes = createdQuizzes;
+  }
+
+  public List<QuizResult> getQuizResults() {
+    return quizResults;
+  }
+
+  public void setQuizResults(List<QuizResult> quizResults) {
+    this.quizResults = quizResults;
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  @Override
+  public Collection<? extends GrantedAuthority> getAuthorities() {
+    return null;
+  }
+
+  public String getPassword() {
+    return password;
+  }
+
+  @Override
+  public String getUsername() {
+    return null;
+  }
+
+  @Override
+  public boolean isAccountNonExpired() {
+    return false;
+  }
+
+  @Override
+  public boolean isAccountNonLocked() {
+    return false;
+  }
+
+  @Override
+  public boolean isCredentialsNonExpired() {
+    return false;
+  }
+
+  @Override
+  public boolean isEnabled() {
+    return false;
+  }
+
+  public void setPassword(String password) {
+    this.password = password;
+  }
+
+  public void setAuthorities(Set<Role> authorities) {
+    this.authorities = authorities;
+  }
+}
diff --git a/src/main/java/idatt2105/group11/idatt2105projectbackend/repository/QuestionAnswerRepository.java b/src/main/java/idatt2105/group11/idatt2105projectbackend/repository/QuestionAnswerRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..8379417a02f96aa55e05fb23b12773656dd65455
--- /dev/null
+++ b/src/main/java/idatt2105/group11/idatt2105projectbackend/repository/QuestionAnswerRepository.java
@@ -0,0 +1,15 @@
+package idatt2105.group11.idatt2105projectbackend.repository;
+
+import idatt2105.group11.idatt2105projectbackend.model.QuestionAnswer;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+import java.util.Optional;
+
+@Repository
+public interface QuestionAnswerRepository extends JpaRepository<QuestionAnswer, Integer> {
+
+  List<QuestionAnswer> findByQuestionId(Integer questionId);
+
+}
diff --git a/src/main/java/idatt2105/group11/idatt2105projectbackend/repository/QuestionRepository.java b/src/main/java/idatt2105/group11/idatt2105projectbackend/repository/QuestionRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..5ee965157540a1c033c6ca56ba5cddd4dd9ec5f7
--- /dev/null
+++ b/src/main/java/idatt2105/group11/idatt2105projectbackend/repository/QuestionRepository.java
@@ -0,0 +1,16 @@
+package idatt2105.group11.idatt2105projectbackend.repository;
+
+import idatt2105.group11.idatt2105projectbackend.model.Question;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+import java.util.Optional;
+
+@Repository
+public interface QuestionRepository extends JpaRepository<Question, Integer> {
+
+  Optional<Question> findById(Integer id);
+
+  List<Question> findAllByQuizId(Integer quizId);
+}
diff --git a/src/main/java/idatt2105/group11/idatt2105projectbackend/repository/QuizRepository.java b/src/main/java/idatt2105/group11/idatt2105projectbackend/repository/QuizRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..b507f9251a6f1824efd10a72a8a8275bcf87492b
--- /dev/null
+++ b/src/main/java/idatt2105/group11/idatt2105projectbackend/repository/QuizRepository.java
@@ -0,0 +1,21 @@
+package idatt2105.group11.idatt2105projectbackend.repository;
+
+import idatt2105.group11.idatt2105projectbackend.model.QuizCategory;
+import idatt2105.group11.idatt2105projectbackend.model.Quiz;
+import idatt2105.group11.idatt2105projectbackend.model.QuizDifficulty;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+import java.util.Optional;
+
+@Repository
+public interface QuizRepository extends JpaRepository<Quiz, Integer> {
+
+  Optional<Quiz> findById(Integer id);
+
+  List<Quiz> findAllByCategory(QuizCategory category);
+  List<Quiz> findAllByDifficulty(QuizDifficulty difficulty);
+  List<Quiz> findAllByCreatorId(Integer creatorId);
+
+}
diff --git a/src/main/java/idatt2105/group11/idatt2105projectbackend/repository/QuizResultRepository.java b/src/main/java/idatt2105/group11/idatt2105projectbackend/repository/QuizResultRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..a20076e27484240c3366eea68f9cfaa1c81d9e15
--- /dev/null
+++ b/src/main/java/idatt2105/group11/idatt2105projectbackend/repository/QuizResultRepository.java
@@ -0,0 +1,17 @@
+package idatt2105.group11.idatt2105projectbackend.repository;
+
+import idatt2105.group11.idatt2105projectbackend.model.QuizResult;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+import java.util.Optional;
+
+@Repository
+public interface QuizResultRepository extends JpaRepository<QuizResult, Integer> {
+  List<QuizResult> findByUserId(Integer userId);
+
+  Optional<QuizResult> findFirstByUserIdOrderByCompletedAtDesc(Integer userId);
+
+
+}
diff --git a/src/main/java/idatt2105/group11/idatt2105projectbackend/repository/RoleRepository.java b/src/main/java/idatt2105/group11/idatt2105projectbackend/repository/RoleRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..3a758ba07c72563e7816e3702cae124744cd9a74
--- /dev/null
+++ b/src/main/java/idatt2105/group11/idatt2105projectbackend/repository/RoleRepository.java
@@ -0,0 +1,12 @@
+package idatt2105.group11.idatt2105projectbackend.repository;
+
+import idatt2105.group11.idatt2105projectbackend.model.Role;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.Optional;
+
+@Repository
+public interface RoleRepository extends JpaRepository<Role, Integer> {
+  Optional<Role> findByAuthority(String authority);
+}
diff --git a/src/main/java/idatt2105/group11/idatt2105projectbackend/repository/UserRepository.java b/src/main/java/idatt2105/group11/idatt2105projectbackend/repository/UserRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..a8a93475d75592888618834657756ec06e80d998
--- /dev/null
+++ b/src/main/java/idatt2105/group11/idatt2105projectbackend/repository/UserRepository.java
@@ -0,0 +1,20 @@
+package idatt2105.group11.idatt2105projectbackend.repository;
+
+
+import idatt2105.group11.idatt2105projectbackend.model.User;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.Optional;
+
+@Repository
+public interface UserRepository extends JpaRepository<User, Integer> {
+
+  Optional<User> findByName(String Name);
+
+  Optional<User> findById(Integer id);
+
+  Optional<User> findByPassword(String password);
+}
+
+
diff --git a/src/main/java/idatt2105/group11/idatt2105projectbackend/service/AuthenticationService.java b/src/main/java/idatt2105/group11/idatt2105projectbackend/service/AuthenticationService.java
new file mode 100644
index 0000000000000000000000000000000000000000..cf05fd22658da70d7828fd5b29ec74c5dd00e5c7
--- /dev/null
+++ b/src/main/java/idatt2105/group11/idatt2105projectbackend/service/AuthenticationService.java
@@ -0,0 +1,86 @@
+package idatt2105.group11.idatt2105projectbackend.service;
+
+import idatt2105.group11.idatt2105projectbackend.dto.LoginResponseDTO;
+import idatt2105.group11.idatt2105projectbackend.exception.UserNotFoundException;
+import idatt2105.group11.idatt2105projectbackend.model.Role;
+import idatt2105.group11.idatt2105projectbackend.model.User;
+import idatt2105.group11.idatt2105projectbackend.repository.RoleRepository;
+import idatt2105.group11.idatt2105projectbackend.repository.UserRepository;
+import jakarta.transaction.Transactional;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.stereotype.Service;
+
+import java.util.HashSet;
+import java.util.Optional;
+import java.util.Set;
+
+@Service
+@Transactional
+public class AuthenticationService {
+
+  private final UserRepository userRepository;
+  private final RoleRepository roleRepository;
+  private final PasswordEncoder encoder;
+  private final AuthenticationManager authManager;
+  private final TokenService tokenService;
+  private final UserService userService;
+
+  public AuthenticationService(UserRepository userRepository, RoleRepository roleRepository,
+                               PasswordEncoder encoder, AuthenticationManager authManager,
+                               TokenService tokenService, UserService userService) {
+    this.userRepository = userRepository;
+    this.roleRepository = roleRepository;
+    this.encoder = encoder;
+    this.authManager = authManager;
+    this.tokenService = tokenService;
+    this.userService = userService;
+  }
+
+  public User registerUser(String username, String password) {
+    String encodedPassword = encoder.encode(password);
+    Role userRole = null;
+    if (roleRepository.findByAuthority("USER").isPresent()) userRole = roleRepository.findByAuthority("USER").get();
+
+    Set<Role> authorities = new HashSet<>();
+    authorities.add(userRole);
+
+    return userRepository.save(new User(username, encodedPassword, authorities));
+  }
+
+  public LoginResponseDTO loginUser(String username, String password) {
+    try {
+      Authentication auth = authManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
+      String token = tokenService.generateJwt(auth);
+      System.out.println("first token: " + token);
+
+      Optional<User> optionalUser = userRepository.findByName(username);
+
+      if (optionalUser.isPresent()) {
+        return new LoginResponseDTO(optionalUser.get(), token);
+      } else {
+        throw new UsernameNotFoundException("User not found.");
+      }
+
+    } catch (AuthenticationException e) {
+      throw new UserNotFoundException("Invalid username or password.");
+    }
+  }
+
+  public String refreshJWT(String existingToken) {
+    tokenService.verifyToken(existingToken);
+
+    String username = tokenService.getNameFromToken(existingToken);
+
+    UserDetails userDetails = userService.loadUserByUsername(username);
+
+    Authentication auth = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
+
+    return tokenService.generateJwt(auth);
+  }
+}
diff --git a/src/main/java/idatt2105/group11/idatt2105projectbackend/service/QuestionAnswerService.java b/src/main/java/idatt2105/group11/idatt2105projectbackend/service/QuestionAnswerService.java
new file mode 100644
index 0000000000000000000000000000000000000000..a9f20e6fa52ef6068b582195ad2ece7cb850e2f3
--- /dev/null
+++ b/src/main/java/idatt2105/group11/idatt2105projectbackend/service/QuestionAnswerService.java
@@ -0,0 +1,48 @@
+package idatt2105.group11.idatt2105projectbackend.service;
+
+import idatt2105.group11.idatt2105projectbackend.dto.QuestionAnswerDTO;
+import idatt2105.group11.idatt2105projectbackend.exception.QuizNotFoundException;
+import idatt2105.group11.idatt2105projectbackend.model.Question;
+import idatt2105.group11.idatt2105projectbackend.model.QuestionAnswer;
+import idatt2105.group11.idatt2105projectbackend.model.QuizResult;
+import idatt2105.group11.idatt2105projectbackend.repository.QuestionAnswerRepository;
+import idatt2105.group11.idatt2105projectbackend.repository.QuestionRepository;
+import idatt2105.group11.idatt2105projectbackend.repository.QuizResultRepository;
+import jakarta.persistence.EntityNotFoundException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class QuestionAnswerService {
+
+  private final QuestionAnswerRepository questionAnswerRepository;
+  private final QuizResultRepository quizResultRepository;
+  private final QuestionRepository questionRepository;
+
+  @Autowired
+  public QuestionAnswerService(QuestionAnswerRepository questionAnswerRepository,
+                               QuizResultRepository quizResultRepository,
+                               QuestionRepository questionRepository) {
+    this.questionAnswerRepository = questionAnswerRepository;
+    this.quizResultRepository = quizResultRepository;
+    this.questionRepository = questionRepository;
+  }
+
+  public QuestionAnswer saveAnswer(Integer quizResultId, QuestionAnswerDTO answerDTO) {
+    QuizResult quizResult = quizResultRepository.findById(quizResultId)
+            .orElseThrow(() -> new EntityNotFoundException("QuizResult not found with id: " + quizResultId));
+
+    Question question = questionRepository.findById(answerDTO.getQuestionId())
+            .orElseThrow(() -> new QuizNotFoundException("Question not found with id: " + answerDTO.getQuestionId()));
+
+    QuestionAnswer answer = new QuestionAnswer();
+    answer.setQuestion(question);
+    answer.setGivenAnswer(answerDTO.getGivenAnswer());
+    answer.setCorrect(question.checkAnswer(answerDTO.getGivenAnswer()));
+    answer.setQuizResult(quizResult);
+
+    quizResult.addQuestionAnswer(answer);
+
+    return questionAnswerRepository.save(answer);
+  }
+}
diff --git a/src/main/java/idatt2105/group11/idatt2105projectbackend/service/QuestionService.java b/src/main/java/idatt2105/group11/idatt2105projectbackend/service/QuestionService.java
new file mode 100644
index 0000000000000000000000000000000000000000..fa81452fa0ff11c89ab45cccbc71d377c155e454
--- /dev/null
+++ b/src/main/java/idatt2105/group11/idatt2105projectbackend/service/QuestionService.java
@@ -0,0 +1,68 @@
+package idatt2105.group11.idatt2105projectbackend.service;
+
+import idatt2105.group11.idatt2105projectbackend.dto.QuestionDTO;
+import idatt2105.group11.idatt2105projectbackend.exception.QuestionNotFoundException;
+import idatt2105.group11.idatt2105projectbackend.model.MultipleChoiceQuestion;
+import idatt2105.group11.idatt2105projectbackend.model.Question;
+import idatt2105.group11.idatt2105projectbackend.repository.QuestionRepository;
+import jakarta.transaction.Transactional;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class QuestionService {
+
+  private final QuestionRepository questionRepository;
+
+  @Autowired
+  public QuestionService(QuestionRepository questionRepository) {
+    this.questionRepository = questionRepository;
+  }
+
+  public QuestionDTO updateQuestion(QuestionDTO questionDTO) {
+    MultipleChoiceQuestion question = (MultipleChoiceQuestion) questionRepository.findById(questionDTO.getId())
+            .orElseThrow(() -> new QuestionNotFoundException("Question not found with id " + questionDTO.getId()));
+
+    question.setQuestionText(questionDTO.getQuestionText());
+    question.setScore(questionDTO.getScore());
+    question.setAnswerOptions(questionDTO.getAnswerOptions());
+    question.setCorrectAnswerIndex(questionDTO.getCorrectAnswerIndex());
+
+    MultipleChoiceQuestion updatedQuestion = questionRepository.save(question);
+    return convertToQuestionDTO(updatedQuestion);
+  }
+
+
+  public void deleteQuestion(Integer id) {
+    questionRepository.deleteById(id);
+  }
+
+  public List<Question> findAllQuestionsByQuizId(Integer quizId) {
+    return questionRepository.findAllByQuizId(quizId);
+  }
+
+  @Transactional
+  public MultipleChoiceQuestion createMCQuestion(QuestionDTO questionDTO) {
+    MultipleChoiceQuestion question = new MultipleChoiceQuestion();
+    question.setQuestionText(questionDTO.getQuestionText());
+    question.setScore(questionDTO.getScore());
+    question.setAnswerOptions(questionDTO.getAnswerOptions());
+    question.setCorrectAnswerIndex(questionDTO.getCorrectAnswerIndex());
+    return questionRepository.save(question);
+  }
+
+  private QuestionDTO convertToQuestionDTO(MultipleChoiceQuestion question) {
+    QuestionDTO questionDTO = new QuestionDTO();
+    questionDTO.setId(question.getId());
+    questionDTO.setQuestionText(question.getQuestionText());
+    questionDTO.setScore(question.getScore());
+    questionDTO.setAnswerOptions(question.getAnswerOptions());
+    questionDTO.setCorrectAnswerIndex(question.getCorrectAnswerIndex());
+
+    return questionDTO;
+  }
+
+
+}
diff --git a/src/main/java/idatt2105/group11/idatt2105projectbackend/service/QuizResultService.java b/src/main/java/idatt2105/group11/idatt2105projectbackend/service/QuizResultService.java
new file mode 100644
index 0000000000000000000000000000000000000000..e325ce932252a0befe528a6e75067fa0f68f2d7f
--- /dev/null
+++ b/src/main/java/idatt2105/group11/idatt2105projectbackend/service/QuizResultService.java
@@ -0,0 +1,129 @@
+package idatt2105.group11.idatt2105projectbackend.service;
+
+import idatt2105.group11.idatt2105projectbackend.dto.QuestionAnswerDTO;
+import idatt2105.group11.idatt2105projectbackend.dto.QuizResultDTO;
+import idatt2105.group11.idatt2105projectbackend.exception.QuestionNotFoundException;
+import idatt2105.group11.idatt2105projectbackend.exception.QuizNotFoundException;
+import idatt2105.group11.idatt2105projectbackend.exception.UserNotFoundException;
+import idatt2105.group11.idatt2105projectbackend.model.*;
+import idatt2105.group11.idatt2105projectbackend.repository.QuestionRepository;
+import idatt2105.group11.idatt2105projectbackend.repository.QuizRepository;
+import idatt2105.group11.idatt2105projectbackend.repository.QuizResultRepository;
+import idatt2105.group11.idatt2105projectbackend.repository.UserRepository;
+import jakarta.persistence.EntityNotFoundException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.time.LocalDateTime;
+import java.util.stream.Collectors;
+
+@Service
+public class QuizResultService {
+
+  private final QuizResultRepository quizResultRepository;
+
+  private final QuizRepository quizRepository;
+
+  private final UserRepository userRepository;
+
+  private final QuestionRepository questionRepository;
+
+  @Autowired
+  public QuizResultService(QuizResultRepository quizResultRepository, QuizRepository quizRepository, UserRepository userRepository, QuestionRepository questionRepository) {
+    this.quizResultRepository = quizResultRepository;
+    this.quizRepository = quizRepository;
+    this.userRepository = userRepository;
+    this.questionRepository = questionRepository;
+  }
+
+
+  public List<QuizResult> findAllResultsForUserId(Integer userId) {
+    return quizResultRepository.findByUserId(userId);
+  }
+
+  public QuizResult startQuizResult(QuizResultDTO creationDTO) {
+    Quiz quiz = quizRepository.findById(creationDTO.getQuizId())
+            .orElseThrow(() -> new QuizNotFoundException("Quiz not found with id: " + creationDTO.getQuizId()));
+    User user = userRepository.findById(creationDTO.getUserId())
+            .orElseThrow(() -> new UserNotFoundException("User not found with id: " + creationDTO.getUserId()));
+
+    QuizResult quizResult = new QuizResult();
+    quizResult.setQuiz(quiz);
+    quizResult.setUser(user);
+    quizResult.setStatus("Påbegynt");
+    quizResult.setStartedAt(LocalDateTime.now());
+    quizResult.setCompletedAt(creationDTO.getCompletedAt());
+    return quizResultRepository.save(quizResult);
+  }
+
+  public QuizResultDTO completeQuiz(Integer quizResultId) {
+    QuizResult quizResult = quizResultRepository.findById(quizResultId)
+            .orElseThrow(() -> new EntityNotFoundException("QuizResult not found with id: " + quizResultId));
+
+    quizResult.setCompletedAt(LocalDateTime.now());
+    quizResult.setStatus("Fullført");
+    QuizResult updatedQuizResult = quizResultRepository.save(quizResult);
+
+    return convertToQuizResultDTO(updatedQuizResult);
+  }
+
+
+  public QuizResultDTO findLatestQuizResultForUser(Integer userId) {
+    QuizResult latestQuizResult = quizResultRepository.findFirstByUserIdOrderByCompletedAtDesc(userId)
+            .orElseThrow(() -> new QuizNotFoundException("No quiz results found for user with id: " + userId));
+    return convertToQuizResultDTO(latestQuizResult);
+  }
+
+  private QuizResultDTO convertToQuizResultDTO(QuizResult quizResult) {
+    QuizResultDTO quizResultDTO = new QuizResultDTO();
+    quizResultDTO.setId(quizResult.getId());
+    quizResultDTO.setQuizId(quizResult.getQuiz().getId());
+    quizResultDTO.setUserId(quizResult.getUser().getId());
+    quizResultDTO.setScore(quizResult.getScore());
+    quizResultDTO.setStatus(quizResult.getStatus());
+    quizResultDTO.setStartedAt(quizResult.getStartedAt());
+    quizResultDTO.setCompletedAt(quizResult.getCompletedAt());
+
+    // Anta at vi også trenger å konvertere listen av QuestionAnswer til QuestionAnswerDTO
+    // Dette krever at vi har en metode for å gjøre denne konverteringen:
+    List<QuestionAnswerDTO> answerDTOs = quizResult.getAnswers().stream()
+            .map(this::convertToQuestionAnswerDTO)
+            .collect(Collectors.toList());
+    quizResultDTO.setAnswers(answerDTOs);
+
+    return quizResultDTO;
+  }
+
+  private QuestionAnswerDTO convertToQuestionAnswerDTO(QuestionAnswer questionAnswer) {
+    QuestionAnswerDTO questionAnswerDTO = new QuestionAnswerDTO();
+    questionAnswerDTO.setId(questionAnswer.getId());
+    questionAnswerDTO.setQuestionId(questionAnswer.getQuestion().getId());
+    questionAnswerDTO.setGivenAnswer(questionAnswer.getGivenAnswer());
+    questionAnswerDTO.setCorrect(questionAnswer.isCorrect());
+
+    return questionAnswerDTO;
+  }
+
+
+
+
+
+  private List<QuestionAnswer> convertToQuestionAnswers(List<QuestionAnswerDTO> answerDTOs, QuizResult quizResult) {
+    List<QuestionAnswer> answers = new ArrayList<>();
+    for (QuestionAnswerDTO answerDTO : answerDTOs) {
+      QuestionAnswer answer = new QuestionAnswer();
+
+      MultipleChoiceQuestion question = (MultipleChoiceQuestion) questionRepository.findById(answerDTO.getQuestionId())
+              .orElseThrow(() -> new QuestionNotFoundException("Question not found with id: " + answerDTO.getQuestionId()));
+      answer.setQuestion(question);
+      answer.setGivenAnswer(answerDTO.getGivenAnswer());
+      answer.setCorrect(question.checkAnswer(answerDTO.getGivenAnswer()));
+      answer.setQuizResult(quizResult);
+
+      answers.add(answer);
+    }
+    return answers;
+  }
+}
diff --git a/src/main/java/idatt2105/group11/idatt2105projectbackend/service/QuizService.java b/src/main/java/idatt2105/group11/idatt2105projectbackend/service/QuizService.java
new file mode 100644
index 0000000000000000000000000000000000000000..703a19ea61eb67d51b715d95d39538c020463f71
--- /dev/null
+++ b/src/main/java/idatt2105/group11/idatt2105projectbackend/service/QuizService.java
@@ -0,0 +1,96 @@
+package idatt2105.group11.idatt2105projectbackend.service;
+
+import idatt2105.group11.idatt2105projectbackend.dto.QuizDTO;
+import idatt2105.group11.idatt2105projectbackend.exception.QuizNotFoundException;
+import idatt2105.group11.idatt2105projectbackend.model.*;
+import idatt2105.group11.idatt2105projectbackend.repository.QuestionRepository;
+import idatt2105.group11.idatt2105projectbackend.repository.QuizRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Service
+public class QuizService {
+  @Autowired
+  private QuizRepository quizRepository;
+
+  @Autowired
+  private QuestionRepository questionRepository;
+
+  @Autowired
+  public QuizService(QuizRepository quizRepository, QuestionRepository questionRepository) {
+    this.quizRepository = quizRepository;
+    this.questionRepository = questionRepository;
+  }
+
+  @Transactional
+  public Quiz createQuiz(QuizDTO quizDTO) {
+    Quiz quiz = new Quiz();
+    quiz.setTitle(quizDTO.getTitle());
+    quiz.setCategory(quizDTO.getCategory());
+
+    List<Question> questions = questionRepository.findAllById(quizDTO.getQuestionIds());
+    quiz.setQuestions(questions);
+
+    return quizRepository.save(quiz);
+  }
+
+  public QuizDTO updateQuiz(QuizDTO quizDTO) {
+    Quiz quiz = quizRepository.findById(quizDTO.getId())
+            .orElseThrow(() -> new QuizNotFoundException("Quiz not found with id " + quizDTO.getId()));
+
+    quiz.setTitle(quizDTO.getTitle());
+    quiz.setCategory(quizDTO.getCategory());
+
+    Quiz updatedQuiz = quizRepository.save(quiz);
+    return convertToQuizDTO(updatedQuiz);
+  }
+
+  public void deleteQuiz(Integer id) {
+    Quiz quiz = quizRepository.findById(id)
+            .orElseThrow(() -> new QuizNotFoundException("Quiz not found with id " + id));
+
+    questionRepository.deleteAll(quiz.getQuestions());
+
+    quizRepository.delete(quiz);
+  }
+
+  public List<Quiz> findAllQuizzes() {
+    return quizRepository.findAll();
+  }
+
+  public List<Quiz> findAllQuizzesByCategory(QuizCategory category) {
+    return quizRepository.findAllByCategory(category);
+  }
+  public List<Quiz> findAllQuizzesByDifficulty(QuizDifficulty difficulty) {
+    return quizRepository.findAllByDifficulty(difficulty);
+  }
+  public List<Quiz> findAllQuizzesByCreatorId(Integer creatorId) {
+    return quizRepository.findAllByCreatorId(creatorId);
+  }
+
+  public Quiz findQuizById(Integer id) {
+    return quizRepository.findById(id)
+            .orElseThrow(() -> new QuizNotFoundException("Quiz not found with id " + id));
+  }
+
+  public QuizDTO convertToQuizDTO(Quiz quiz) {
+    QuizDTO quizDTO = new QuizDTO();
+    quizDTO.setId(quiz.getId());
+    quizDTO.setTitle(quiz.getTitle());
+    quizDTO.setCategory(quiz.getCategory());
+
+    List<Integer> questionIds = quiz.getQuestions().stream()
+            .map(Question::getId)
+            .collect(Collectors.toList());
+    quizDTO.setQuestionIds(questionIds);
+
+    return quizDTO;
+  }
+
+
+}
+
diff --git a/src/main/java/idatt2105/group11/idatt2105projectbackend/service/TokenService.java b/src/main/java/idatt2105/group11/idatt2105projectbackend/service/TokenService.java
new file mode 100644
index 0000000000000000000000000000000000000000..c6fd4f8d0286a48cfa26a5350f414655dc71b6db
--- /dev/null
+++ b/src/main/java/idatt2105/group11/idatt2105projectbackend/service/TokenService.java
@@ -0,0 +1,54 @@
+package idatt2105.group11.idatt2105projectbackend.service;
+
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.oauth2.jwt.*;
+import org.springframework.stereotype.Service;
+
+import java.time.Instant;
+import java.util.stream.Collectors;
+
+@Service
+public class TokenService {
+
+  private final JwtEncoder jwtEncoder;
+  private final JwtDecoder jwtDecoder;
+
+  public TokenService(JwtEncoder jwtEncoder, JwtDecoder jwtDecoder) {
+    this.jwtEncoder = jwtEncoder;
+    this.jwtDecoder = jwtDecoder;
+  }
+
+  public String generateJwt(Authentication auth) {
+    Instant now = Instant.now();
+    Instant expiresAt = now.plusSeconds(300);
+
+    String scope = auth.getAuthorities().stream()
+            .map(GrantedAuthority::getAuthority)
+            .collect(Collectors.joining(" "));
+
+    JwtClaimsSet claims = JwtClaimsSet.builder()
+            .issuer("self")
+            .issuedAt(now)
+            .subject(auth.getName())
+            .claim("roles", scope)
+            .expiresAt(expiresAt)
+            .build();
+
+    return jwtEncoder.encode(JwtEncoderParameters.from(claims)).getTokenValue();
+  }
+
+  public void verifyToken(String token) {
+    try {
+      jwtDecoder.decode(token);
+    } catch (JwtException e) {
+      throw new IllegalArgumentException("Invalid token, could not decode. Message:", e);
+    }
+  }
+
+  public String getNameFromToken(String token) {
+    Jwt jwt = jwtDecoder.decode(token);
+    return jwt.getSubject();
+  }
+}
+
diff --git a/src/main/java/idatt2105/group11/idatt2105projectbackend/service/UserService.java b/src/main/java/idatt2105/group11/idatt2105projectbackend/service/UserService.java
new file mode 100644
index 0000000000000000000000000000000000000000..185bfc55bb4ceb68002462e48d07460a10634cbb
--- /dev/null
+++ b/src/main/java/idatt2105/group11/idatt2105projectbackend/service/UserService.java
@@ -0,0 +1,48 @@
+package idatt2105.group11.idatt2105projectbackend.service;
+
+import idatt2105.group11.idatt2105projectbackend.exception.UserNotFoundException;
+import idatt2105.group11.idatt2105projectbackend.model.User;
+import idatt2105.group11.idatt2105projectbackend.repository.UserRepository;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.stereotype.Service;
+import org.springframework.web.bind.annotation.RequestBody;
+
+import java.util.List;
+import java.util.Optional;
+
+@Service
+public class UserService implements UserDetailsService {
+
+  private final UserRepository userRepository;
+
+  public UserService(UserRepository userRepository) {
+    this.userRepository = userRepository;
+  }
+
+  public List<User> findAllAppUsers() {
+    return userRepository.findAll();
+  }
+
+  public void addAppUser(@RequestBody User user) {
+    userRepository.save(user);
+  }
+
+  public Boolean verifyAppUser(User user) {
+    return userRepository.findByName(user.getName()).isPresent() &&
+            userRepository.findByPassword(user.getPassword()).isPresent();
+  }
+
+  public User findAppUserByName(String name) {
+    Optional<User> userOptional = userRepository.findByName(name);
+
+    return userOptional.orElse(null);
+  }
+
+  @Override
+  public UserDetails loadUserByUsername(String name) throws UsernameNotFoundException {
+    return userRepository.findByName(name)
+            .orElseThrow(() -> new UsernameNotFoundException("User '" + name + "' not found."));
+  }
+}
diff --git a/src/main/java/idatt2105/group11/idatt2105projectbackend/utils/KeyGeneratorUtility.java b/src/main/java/idatt2105/group11/idatt2105projectbackend/utils/KeyGeneratorUtility.java
new file mode 100644
index 0000000000000000000000000000000000000000..56a6d94fe8f7d75295dab8b03be1425829dbd30c
--- /dev/null
+++ b/src/main/java/idatt2105/group11/idatt2105projectbackend/utils/KeyGeneratorUtility.java
@@ -0,0 +1,22 @@
+package idatt2105.group11.idatt2105projectbackend.utils;
+
+
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+
+public class KeyGeneratorUtility {
+
+  public static KeyPair generateRSAKey() {
+    KeyPair keyPair;
+
+    try {
+      KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
+      keyPairGenerator.initialize(2048);
+      keyPair = keyPairGenerator.generateKeyPair();
+    } catch (Exception e) {
+      throw new IllegalStateException();
+    }
+
+    return keyPair;
+  }
+}
diff --git a/src/main/java/idatt2105/group11/idatt2105projectbackend/utils/RSAKeyProperties.java b/src/main/java/idatt2105/group11/idatt2105projectbackend/utils/RSAKeyProperties.java
new file mode 100644
index 0000000000000000000000000000000000000000..763b6fc58d1237d834eabafe8212e025c917a942
--- /dev/null
+++ b/src/main/java/idatt2105/group11/idatt2105projectbackend/utils/RSAKeyProperties.java
@@ -0,0 +1,36 @@
+package idatt2105.group11.idatt2105projectbackend.utils;
+
+import org.springframework.stereotype.Component;
+
+import java.security.KeyPair;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+
+@Component
+public class RSAKeyProperties {
+
+  private RSAPublicKey publicKey;
+  private RSAPrivateKey privateKey;
+
+  public RSAKeyProperties() {
+    KeyPair keyPair = KeyGeneratorUtility.generateRSAKey();
+    publicKey = (RSAPublicKey) keyPair.getPublic();
+    privateKey = (RSAPrivateKey) keyPair.getPrivate();
+  }
+
+  public RSAPublicKey getPublicKey() {
+    return publicKey;
+  }
+
+  public void setPublicKey(RSAPublicKey publicKey) {
+    this.publicKey = publicKey;
+  }
+
+  public RSAPrivateKey getPrivateKey() {
+    return privateKey;
+  }
+
+  public void setPrivateKey(RSAPrivateKey privateKey) {
+    this.privateKey = privateKey;
+  }
+}
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
new file mode 100644
index 0000000000000000000000000000000000000000..76e1cf573705f3c659270f849edc2a27cb1b9176
--- /dev/null
+++ b/src/main/resources/application.properties
@@ -0,0 +1 @@
+spring.application.name=idatt2105-project-backend
diff --git a/src/test/java/idatt2105/group11/idatt2105projectbackend/Idatt2105ProjectBackendApplicationTests.java b/src/test/java/idatt2105/group11/idatt2105projectbackend/Idatt2105ProjectBackendApplicationTests.java
new file mode 100644
index 0000000000000000000000000000000000000000..c3296332859b522ae82ced6f7faa27092f3e45d5
--- /dev/null
+++ b/src/test/java/idatt2105/group11/idatt2105projectbackend/Idatt2105ProjectBackendApplicationTests.java
@@ -0,0 +1,13 @@
+package idatt2105.group11.idatt2105projectbackend;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class Idatt2105ProjectBackendApplicationTests {
+
+	@Test
+	void contextLoads() {
+	}
+
+}