Skip to content
Snippets Groups Projects
Commit c6de6706 authored by Torbjørn Antonsen's avatar Torbjørn Antonsen
Browse files

Merge branch 'file-migration' into 'main'

File migration from one repo to another containing backend

See merge request !6
parents d8cdc363 6244952d
Branches
No related tags found
1 merge request!6File migration from one repo to another containing backend
Pipeline #267379 passed
Showing
with 1403 additions and 0 deletions
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/
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."
File added
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
mvnw 0 → 100644
#!/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 "$@"
mvnw.cmd 0 → 100644
@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%
pom.xml 0 → 100644
<?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>
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);
}
}
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);
}
}
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;
}
}
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);
}
}
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;
}
}
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;
}
}
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;
}
}
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;
}
}
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();
}
}
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 + '\'' +
'}';
}
}
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 +
'}';
}
}
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;
}
}
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;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment