diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..3b41682 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +/mvnw text eol=lf +*.cmd text eol=crlf diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..d58dfb7 --- /dev/null +++ b/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,19 @@ +# 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 +# +# http://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. +wrapperVersion=3.3.2 +distributionType=only-script +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip diff --git a/mvnw b/mvnw new file mode 100755 index 0000000..19529dd --- /dev/null +++ b/mvnw @@ -0,0 +1,259 @@ +#!/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 +# +# http://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.3.2 +# +# Optional ENV vars +# ----------------- +# JAVA_HOME - location of a JDK home dir, required when download maven via java source +# MVNW_REPOURL - repo url base for downloading maven distribution +# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output +# ---------------------------------------------------------------------------- + +set -euf +[ "${MVNW_VERBOSE-}" != debug ] || set -x + +# OS specific support. +native_path() { printf %s\\n "$1"; } +case "$(uname)" in +CYGWIN* | MINGW*) + [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")" + native_path() { cygpath --path --windows "$1"; } + ;; +esac + +# set JAVACMD and JAVACCMD +set_java_home() { + # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched + 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" + JAVACCMD="$JAVA_HOME/jre/sh/javac" + else + JAVACMD="$JAVA_HOME/bin/java" + JAVACCMD="$JAVA_HOME/bin/javac" + + if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then + echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2 + echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2 + return 1 + fi + fi + else + JAVACMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v java + )" || : + JAVACCMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v javac + )" || : + + if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then + echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2 + return 1 + fi + fi +} + +# hash string like Java String::hashCode +hash_string() { + str="${1:-}" h=0 + while [ -n "$str" ]; do + char="${str%"${str#?}"}" + h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296)) + str="${str#?}" + done + printf %x\\n $h +} + +verbose() { :; } +[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; } + +die() { + printf %s\\n "$1" >&2 + exit 1 +} + +trim() { + # MWRAPPER-139: + # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds. + # Needed for removing poorly interpreted newline sequences when running in more + # exotic environments such as mingw bash on Windows. + printf "%s" "${1}" | tr -d '[:space:]' +} + +# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties +while IFS="=" read -r key value; do + case "${key-}" in + distributionUrl) distributionUrl=$(trim "${value-}") ;; + distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;; + esac +done <"${0%/*}/.mvn/wrapper/maven-wrapper.properties" +[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties" + +case "${distributionUrl##*/}" in +maven-mvnd-*bin.*) + MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ + case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in + *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;; + :Darwin*x86_64) distributionPlatform=darwin-amd64 ;; + :Darwin*arm64) distributionPlatform=darwin-aarch64 ;; + :Linux*x86_64*) distributionPlatform=linux-amd64 ;; + *) + echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2 + distributionPlatform=linux-amd64 + ;; + esac + distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip" + ;; +maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;; +*) MVN_CMD="mvn${0##*/mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;; +esac + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}" +distributionUrlName="${distributionUrl##*/}" +distributionUrlNameMain="${distributionUrlName%.*}" +distributionUrlNameMain="${distributionUrlNameMain%-bin}" +MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}" +MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")" + +exec_maven() { + unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || : + exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD" +} + +if [ -d "$MAVEN_HOME" ]; then + verbose "found existing MAVEN_HOME at $MAVEN_HOME" + exec_maven "$@" +fi + +case "${distributionUrl-}" in +*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;; +*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;; +esac + +# prepare tmp dir +if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then + clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; } + trap clean HUP INT TERM EXIT +else + die "cannot create temp dir" +fi + +mkdir -p -- "${MAVEN_HOME%/*}" + +# Download and Install Apache Maven +verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +verbose "Downloading from: $distributionUrl" +verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +# select .zip or .tar.gz +if ! command -v unzip >/dev/null; then + distributionUrl="${distributionUrl%.zip}.tar.gz" + distributionUrlName="${distributionUrl##*/}" +fi + +# verbose opt +__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR='' +[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v + +# normalize http auth +case "${MVNW_PASSWORD:+has-password}" in +'') MVNW_USERNAME='' MVNW_PASSWORD='' ;; +has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;; +esac + +if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then + verbose "Found wget ... using wget" + wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl" +elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then + verbose "Found curl ... using curl" + curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl" +elif set_java_home; then + verbose "Falling back to use Java to download" + javaSource="$TMP_DOWNLOAD_DIR/Downloader.java" + targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName" + cat >"$javaSource" <<-END + public class Downloader extends java.net.Authenticator + { + protected java.net.PasswordAuthentication getPasswordAuthentication() + { + return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() ); + } + public static void main( String[] args ) throws Exception + { + setDefault( new Downloader() ); + java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() ); + } + } + END + # For Cygwin/MinGW, switch paths to Windows format before running javac and java + verbose " - Compiling Downloader.java ..." + "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java" + verbose " - Running Downloader.java ..." + "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")" +fi + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +if [ -n "${distributionSha256Sum-}" ]; then + distributionSha256Result=false + if [ "$MVN_CMD" = mvnd.sh ]; then + echo "Checksum validation is not supported for maven-mvnd." >&2 + echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + elif command -v sha256sum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + elif command -v shasum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + else + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 + echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + fi + if [ $distributionSha256Result = false ]; then + echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2 + echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2 + exit 1 + fi +fi + +# unzip and move +if command -v unzip >/dev/null; then + unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip" +else + tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar" +fi +printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/mvnw.url" +mv -- "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME" + +clean || : +exec_maven "$@" diff --git a/mvnw.cmd b/mvnw.cmd new file mode 100644 index 0000000..249bdf3 --- /dev/null +++ b/mvnw.cmd @@ -0,0 +1,149 @@ +<# : batch portion +@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 http://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.3.2 +@REM +@REM Optional ENV vars +@REM MVNW_REPOURL - repo url base for downloading maven distribution +@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output +@REM ---------------------------------------------------------------------------- + +@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) +@SET __MVNW_CMD__= +@SET __MVNW_ERROR__= +@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% +@SET PSModulePath= +@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( + IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) +) +@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% +@SET __MVNW_PSMODULEP_SAVE= +@SET __MVNW_ARG0_NAME__= +@SET MVNW_USERNAME= +@SET MVNW_PASSWORD= +@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*) +@echo Cannot start maven from wrapper >&2 && exit /b 1 +@GOTO :EOF +: end batch / begin powershell #> + +$ErrorActionPreference = "Stop" +if ($env:MVNW_VERBOSE -eq "true") { + $VerbosePreference = "Continue" +} + +# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties +$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl +if (!$distributionUrl) { + Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" +} + +switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { + "maven-mvnd-*" { + $USE_MVND = $true + $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" + $MVN_CMD = "mvnd.cmd" + break + } + default { + $USE_MVND = $false + $MVN_CMD = $script -replace '^mvnw','mvn' + break + } +} + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +if ($env:MVNW_REPOURL) { + $MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" } + $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')" +} +$distributionUrlName = $distributionUrl -replace '^.*/','' +$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' +$MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain" +if ($env:MAVEN_USER_HOME) { + $MAVEN_HOME_PARENT = "$env:MAVEN_USER_HOME/wrapper/dists/$distributionUrlNameMain" +} +$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' +$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" + +if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { + Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" + Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" + exit $? +} + +if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { + Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" +} + +# prepare tmp dir +$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile +$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" +$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null +trap { + if ($TMP_DOWNLOAD_DIR.Exists) { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } + } +} + +New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null + +# Download and Install Apache Maven +Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +Write-Verbose "Downloading from: $distributionUrl" +Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +$webclient = New-Object System.Net.WebClient +if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { + $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) +} +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum +if ($distributionSha256Sum) { + if ($USE_MVND) { + Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." + } + Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash + if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { + Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." + } +} + +# unzip and move +Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null +Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null +try { + Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null +} catch { + if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { + Write-Error "fail to move MAVEN_HOME" + } +} finally { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } +} + +Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..33d91c9 --- /dev/null +++ b/pom.xml @@ -0,0 +1,92 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.4.4 + + + com.CTF + server + 0.0.1-SNAPSHOT + server + Demo project for Spring Boot + + + + + + + + + + + + + + + 17 + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springdoc + springdoc-openapi-ui + 1.6.14 + + + org.springframework.boot + spring-boot-starter-oauth2-resource-server + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-web + + + io.jsonwebtoken + jjwt + 0.9.1 + + + + org.mariadb.jdbc + mariadb-java-client + runtime + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.security + spring-security-test + test + + + org.projectlombok + lombok + 1.18.36 + provided + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/private_key.pem b/private_key.pem new file mode 100644 index 0000000..68414c4 --- /dev/null +++ b/private_key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDZyw8oicHJeAUe +zT+n8NYuC047ocEB3LMNhDzZvfTQaMNZkWEyemU3UgJ6CqF2nqFm/WV7a+qSVB7t +iirXy+REcfBTDDnP2tFaq7YP2ODWzyF8rwgztpkxEoLlP5tDCUt/pet4C/+Q+Hzc +xVOKXFMneRoE9LxqZ2UmMO3pn0zcXsFoyBWWlwR3ft5t+RXmGF2noEvF9ijDCiQP +3EsV2ySwkQlBZeegdlHD+C6+NXgyU4xM38zS17UAr6JhwEflkBmNRleiMGGsKMOL +i+f8FQBCTCEfRxiF6Aa8uo9dKYuGwTqtizuSpQqzGRKCltFUBe+qyxgxfuNc+pNh +EtwfBWUTAgMBAAECggEAH8h+YdAYs6oMNT6Gt59x4i5MMG+elwL6LlLJ/oy2GWPw +fjW1FYS/GJ+jNOQwQ/tKWplIIgbRqKEWElxDfFKI8WQfSj9SgH7SZoUAgLeJuE9p +96QjckiHep3U9Fef9Nx6ZBp2joJRvXpF3oH9eweWKwCFR4vfozeLj1M8pQdWVCJK +8ytgx+54YhtzMGBCor0AruCgnBYj5E7KaqV1RGa4ER8Ktao1NvIb8X6QVy4eMraH +mpr1cMJLzuVKJkY5uc4ebJIcWEglJqufSuFNu7/0SePLx/Kijanmrh2FDgl4H6Ji +npzNjIbDfYa4xDlwHoGJCvX0FxOEZAdw7siUD0Gb4QKBgQDu6h7gKiD7CgReFJR+ +YHgfa1fEvNPY2+aXGaMmuricxRW+weesOw97t2z0+WkmrZqDY7yik/bOPC/i3D/2 +wrc9X6GSkRx1ltuGj94cB/MXH/jf0bQNAGRJZ/emSP7ulE4xlu6t3Z+p77etBiaA +SuJ6O0uC3IwFo0vBOGUULhfFzwKBgQDpXkOaMXyPP1YrqbV0bjANGCqP5zoU8ypv +6GouekrGqoPcabvTglQFmQ6oAJVbBnhNuaM3ov6LTKkMaHnJKKII98YmirGzzAvf +xE8GYnl9zWr6wIA9uoBN32jIAa7kOZUhQk+RNGx782UVGyltn9ihUflzyrv0VC/P +9T7jrRwBfQKBgFzJ5tXu5sI5ALs9SPLQKrchLIRHRgvKVANJPLk0+bBBRxHAI2cb +xQaqlZGLMFCKSiFPYhrOVqOAcqSsH9eJhjs64fiXjTMKNRZM19mRKNNJYpIi0sfd +6BUuYNtfLEuio7/Uu7wg//qzFGYJpnhbHRyV3NzlJSinZCuV6IPu5uK3AoGAXyHK +NSVPPaX4HryD9/6jH/NmBlugVcH63rvD7UZ1DR+duVBw/Pv3/IA0dVAnkn/Eswql ++pw7X9XUY/aDDvm9dCJtaHDJmB3qCUIhZNzn4dzHa4jlvkQ04YndUQs+nFLM9E3v +2aWhQ7Yo0r3L2aB70udz5TwT+roG86NqC64Z6JECgYBQeCNZB2ZHmCAjMX2xq7eS ++6fH9iHl1DhBRHdvYn2WelbjPMZ2yutaoTybvdltgUWEU2eMRhZMb7K1MbtwxIzC +ucXWvDlx5QZDtCRoXwF3DtTTXfOvfVfi1nilqCJSG6sIOP8MIuKKnnpv3/1sMr96 +ppnk7TIuJhvoo3VQR0mvYw== +-----END PRIVATE KEY----- diff --git a/src/main/java/com/CTF/server/ServerApplication.java b/src/main/java/com/CTF/server/ServerApplication.java new file mode 100644 index 0000000..2b27d9e --- /dev/null +++ b/src/main/java/com/CTF/server/ServerApplication.java @@ -0,0 +1,12 @@ +package com.CTF.server; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class ServerApplication { + + public static void main(String[] args) { + SpringApplication.run(ServerApplication.class, args); + } +} \ No newline at end of file diff --git a/src/main/java/com/CTF/server/config/SecurityConfig.java b/src/main/java/com/CTF/server/config/SecurityConfig.java new file mode 100644 index 0000000..503943b --- /dev/null +++ b/src/main/java/com/CTF/server/config/SecurityConfig.java @@ -0,0 +1,58 @@ +package com.CTF.server.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter; +import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.oauth2.jwt.NimbusJwtDecoder; +import javax.crypto.spec.SecretKeySpec; +import java.nio.charset.StandardCharsets; + + +@Configuration +@EnableWebSecurity +public class SecurityConfig { + + @Value("${jwt.secret}") + private String secret; + + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + http + .csrf(csrf -> csrf.disable()) + .authorizeHttpRequests(auth -> auth + .anyRequest().permitAll() + ) + .sessionManagement(sess -> sess.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) + .oauth2ResourceServer(oauth2 -> oauth2.jwt(jwt -> jwt.jwtAuthenticationConverter(jwtAuthenticationConverter()) + .decoder(jwtDecoder()))); + + return http.build(); + } + + @Bean + public JwtAuthenticationConverter jwtAuthenticationConverter() { + JwtAuthenticationConverter converter = new JwtAuthenticationConverter(); + converter.setJwtGrantedAuthoritiesConverter(new JwtGrantedAuthoritiesConverter()); + return converter; + } + + @Bean + public NimbusJwtDecoder jwtDecoder() { + byte[] keyBytes = secret.getBytes(StandardCharsets.UTF_8); + SecretKeySpec secretKey = new SecretKeySpec(keyBytes, "HmacSHA512"); + return NimbusJwtDecoder.withSecretKey(secretKey).build(); + } + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } +} \ No newline at end of file diff --git a/src/main/java/com/CTF/server/config/WebConfig.java b/src/main/java/com/CTF/server/config/WebConfig.java new file mode 100644 index 0000000..5085bb8 --- /dev/null +++ b/src/main/java/com/CTF/server/config/WebConfig.java @@ -0,0 +1,18 @@ +package com.CTF.server.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class WebConfig implements WebMvcConfigurer { + + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/api/**") + .allowedOrigins("https://dev.d.ctf.arrobe.fr", "http://localhost:5173") + .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") + .allowedHeaders("*") + .allowCredentials(true); + } +} \ No newline at end of file diff --git a/src/main/java/com/CTF/server/controller/ArticleController.java b/src/main/java/com/CTF/server/controller/ArticleController.java new file mode 100644 index 0000000..2b7280f --- /dev/null +++ b/src/main/java/com/CTF/server/controller/ArticleController.java @@ -0,0 +1,72 @@ +package com.CTF.server.controller; + +import com.CTF.server.entity.*; +import com.CTF.server.repository.ArticleRepository; +import com.CTF.server.repository.MessageRepository; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.Date; +import java.util.List; +import java.util.Optional; + +@RestController +@RequestMapping("/api/articles") +public class ArticleController { + + private final ArticleRepository articleRepository; + private final MessageRepository messageRepository; + + public ArticleController(ArticleRepository articleRepository, MessageRepository messageRepository) { + this.articleRepository = articleRepository; + this.messageRepository = messageRepository; + } + + @GetMapping + public List getAllArticles() { + List
articles = articleRepository.findAll(); + return articles.stream().map(article -> { + List messages = messageRepository.findByArticleId(article.getId()); + ArticleWithMessage articleWithMessage = new ArticleWithMessage(); + articleWithMessage.setArticle(article); + // set LowMessage list + articleWithMessage.setMessages(messages.stream().map(message -> { + LowMessage lowMessage = new LowMessage(); + lowMessage.setText(message.getText()); + lowMessage.setIp(message.getIp()); + lowMessage.setTime(message.getTime().toString()); + return lowMessage; + }).toList()); + return articleWithMessage; + }).toList(); + } + + @GetMapping("/{id}") + public ResponseEntity getArticleById(@PathVariable Long id) { + Optional
article = articleRepository.findById(id); + + if (article.isPresent()) { + List messages = messageRepository.findByArticleId(id); + ArticleWithMessage articleWithMessage = new ArticleWithMessage(); + articleWithMessage.setArticle(article.get()); + // set LowMessage list + articleWithMessage.setMessages(messages.stream().map(message -> { + LowMessage lowMessage = new LowMessage(); + lowMessage.setText(message.getText()); + lowMessage.setIp(message.getIp()); + lowMessage.setTime(message.getTime().toString()); + return lowMessage; + }).toList()); + + return ResponseEntity.ok(articleWithMessage); + } + + return ResponseEntity.notFound().build(); + } + + @PostMapping + public Article createArticle(@RequestBody Article article) { + article.setDate(new Date()); + return articleRepository.save(article); + } +} \ No newline at end of file diff --git a/src/main/java/com/CTF/server/controller/AuthController.java b/src/main/java/com/CTF/server/controller/AuthController.java new file mode 100644 index 0000000..ed936f4 --- /dev/null +++ b/src/main/java/com/CTF/server/controller/AuthController.java @@ -0,0 +1,49 @@ +package com.CTF.server.controller; + +import com.CTF.server.entity.Maria; +import com.CTF.server.entity.Role; +import com.CTF.server.entity.User; +import com.CTF.server.repository.MariaRepository; +import com.CTF.server.repository.UserRepository; +import org.springframework.http.ResponseEntity; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.web.bind.annotation.*; + +import java.util.Optional; + +@RestController +@RequestMapping("/api/public") +public class AuthController { + + private final UserRepository userRepository; + private final PasswordEncoder passwordEncoder; + private final MariaRepository mariaRepository; + + public AuthController(UserRepository userRepository, PasswordEncoder passwordEncoder, MariaRepository mariaRepository) { + this.userRepository = userRepository; + this.passwordEncoder = passwordEncoder; + this.mariaRepository = mariaRepository; + } + + @PostMapping("/register") + public ResponseEntity register(@RequestBody User user) { + user.setPassword(passwordEncoder.encode(user.getPassword())); + user.setRole(Role.USER); + userRepository.save(user); + return ResponseEntity.ok("User registered successfully!"); + } + + @PostMapping("/login") + public ResponseEntity login(@RequestBody User user) { + Optional optionalUser = userRepository.findByUsername(user.getUsername()); + if (optionalUser.isPresent() && passwordEncoder.matches(user.getPassword(), optionalUser.get().getPassword())) { + if (optionalUser.get().getRole() == Role.ADMIN) { + Optional maria = mariaRepository.findById(1L); + return ResponseEntity.ok(maria.get().getMaria()); + } + return ResponseEntity.ok("AUthentifié"); + } else { + return ResponseEntity.status(401).body("user"); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/CTF/server/controller/JwtKeyController.java b/src/main/java/com/CTF/server/controller/JwtKeyController.java new file mode 100644 index 0000000..58e4472 --- /dev/null +++ b/src/main/java/com/CTF/server/controller/JwtKeyController.java @@ -0,0 +1,23 @@ +package com.CTF.server.controller; + +import org.springframework.core.io.ClassPathResource; +import org.springframework.util.StreamUtils; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import java.nio.charset.StandardCharsets; +import java.util.Map; + +@RestController +@RequestMapping("/keys") +public class JwtKeyController { + + @GetMapping + public Map getKey() throws Exception { + ClassPathResource resource = new ClassPathResource("public_key.pem"); + String publicKey = StreamUtils.copyToString(resource.getInputStream(), StandardCharsets.UTF_8); + return Map.of("keys", publicKey); + } +} + + diff --git a/src/main/java/com/CTF/server/controller/MessageController.java b/src/main/java/com/CTF/server/controller/MessageController.java new file mode 100644 index 0000000..b9d358e --- /dev/null +++ b/src/main/java/com/CTF/server/controller/MessageController.java @@ -0,0 +1,61 @@ +package com.CTF.server.controller; + +import com.CTF.server.entity.Article; +import com.CTF.server.entity.Message; +import com.CTF.server.repository.ArticleRepository; +import com.CTF.server.repository.MessageRepository; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.Date; +import java.util.List; +import java.util.Optional; + +@RestController +@RequestMapping("/api/messages") +public class MessageController { + + private final MessageRepository messageRepository; + private final ArticleRepository articleRepository; + + public MessageController(MessageRepository messageRepository, ArticleRepository articleRepository) { + this.messageRepository = messageRepository; + this.articleRepository = articleRepository; + } + + @GetMapping("/{articleId}") + public ResponseEntity> getMessagesByArticleId(@PathVariable Long articleId) { + Optional
articleOptional = articleRepository.findById(articleId); + if (articleOptional.isPresent()) { + List messages = messageRepository.findByArticleId(articleId); + return ResponseEntity.ok(messages); + } + return ResponseEntity.notFound().build(); + } + + @PostMapping("") + public ResponseEntity addMessage(@RequestBody Message message, @RequestHeader(value = "X-Forwarded-For", required = false) String clientIp) { + Optional
articleOptional = articleRepository.findById(message.getArticle().getId()); + if (articleOptional.isPresent()) { + message.setArticle(articleOptional.get()); + message.setTime(new Date()); + + // Si l'IP est fournie dans les en-têtes, sinon null + message.setIp(clientIp); + + Message savedMessage = messageRepository.save(message); + return new ResponseEntity<>(savedMessage, HttpStatus.CREATED); + } + return ResponseEntity.notFound().build(); + } + + @DeleteMapping("/{id}") + public ResponseEntity deleteMessage(@PathVariable Long id) { + if (messageRepository.existsById(id)) { + messageRepository.deleteById(id); + return ResponseEntity.noContent().build(); + } + return ResponseEntity.notFound().build(); + } +} \ No newline at end of file diff --git a/src/main/java/com/CTF/server/entity/Article.java b/src/main/java/com/CTF/server/entity/Article.java new file mode 100644 index 0000000..2d0a5f4 --- /dev/null +++ b/src/main/java/com/CTF/server/entity/Article.java @@ -0,0 +1,28 @@ +package com.CTF.server.entity; + +import jakarta.persistence.*; +import lombok.*; + +import java.util.Date; + +@Entity +@Table(name = "articles") +@Getter @Setter +@NoArgsConstructor @AllArgsConstructor +public class Article { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String title; + + @Column(columnDefinition = "TEXT") + private String description; + + @Temporal(TemporalType.TIMESTAMP) + private Date date; + + private String ipAdress; + private String image; + private String content; +} diff --git a/src/main/java/com/CTF/server/entity/ArticleWithMessage.java b/src/main/java/com/CTF/server/entity/ArticleWithMessage.java new file mode 100644 index 0000000..bb4dce1 --- /dev/null +++ b/src/main/java/com/CTF/server/entity/ArticleWithMessage.java @@ -0,0 +1,14 @@ +package com.CTF.server.entity; + +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +@Getter +@Setter +public class ArticleWithMessage { + Article article; + List messages; +} + diff --git a/src/main/java/com/CTF/server/entity/LowMessage.java b/src/main/java/com/CTF/server/entity/LowMessage.java new file mode 100644 index 0000000..03fb944 --- /dev/null +++ b/src/main/java/com/CTF/server/entity/LowMessage.java @@ -0,0 +1,12 @@ +package com.CTF.server.entity; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class LowMessage{ + private String text; + private String ip; + private String time; +} diff --git a/src/main/java/com/CTF/server/entity/Maria.java b/src/main/java/com/CTF/server/entity/Maria.java new file mode 100644 index 0000000..2fefbb2 --- /dev/null +++ b/src/main/java/com/CTF/server/entity/Maria.java @@ -0,0 +1,21 @@ +package com.CTF.server.entity; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Entity +@Table(name = "maria") +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class Maria { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String maria; +} diff --git a/src/main/java/com/CTF/server/entity/Message.java b/src/main/java/com/CTF/server/entity/Message.java new file mode 100644 index 0000000..235f437 --- /dev/null +++ b/src/main/java/com/CTF/server/entity/Message.java @@ -0,0 +1,28 @@ +package com.CTF.server.entity; + +import jakarta.persistence.*; +import lombok.*; + +import java.util.Date; + +@Entity +@Table(name = "messages") +@Getter @Setter +@NoArgsConstructor @AllArgsConstructor +public class Message { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(columnDefinition = "TEXT") + private String text; + + private String ip; + + @Temporal(TemporalType.TIMESTAMP) + private Date time; + + @ManyToOne + @JoinColumn(name = "article_id") + private Article article; +} diff --git a/src/main/java/com/CTF/server/entity/Role.java b/src/main/java/com/CTF/server/entity/Role.java new file mode 100644 index 0000000..ebbb32d --- /dev/null +++ b/src/main/java/com/CTF/server/entity/Role.java @@ -0,0 +1,6 @@ +package com.CTF.server.entity; + +public enum Role { + USER, + ADMIN +} diff --git a/src/main/java/com/CTF/server/entity/User.java b/src/main/java/com/CTF/server/entity/User.java new file mode 100644 index 0000000..52b2a62 --- /dev/null +++ b/src/main/java/com/CTF/server/entity/User.java @@ -0,0 +1,27 @@ +package com.CTF.server.entity; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + + +@Entity +@Table(name = "users") +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class User { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String username; + + private String password; + + @Enumerated(EnumType.STRING) + private Role role; +} \ No newline at end of file diff --git a/src/main/java/com/CTF/server/repository/ArticleRepository.java b/src/main/java/com/CTF/server/repository/ArticleRepository.java new file mode 100644 index 0000000..daa883a --- /dev/null +++ b/src/main/java/com/CTF/server/repository/ArticleRepository.java @@ -0,0 +1,12 @@ +package com.CTF.server.repository; + +import com.CTF.server.entity.Article; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface ArticleRepository extends JpaRepository { + + Optional
findById(Long id); + +} diff --git a/src/main/java/com/CTF/server/repository/MariaRepository.java b/src/main/java/com/CTF/server/repository/MariaRepository.java new file mode 100644 index 0000000..b8042c9 --- /dev/null +++ b/src/main/java/com/CTF/server/repository/MariaRepository.java @@ -0,0 +1,10 @@ +package com.CTF.server.repository; + +import com.CTF.server.entity.Maria; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface MariaRepository extends JpaRepository { + Optional findById(Long id); +} diff --git a/src/main/java/com/CTF/server/repository/MessageRepository.java b/src/main/java/com/CTF/server/repository/MessageRepository.java new file mode 100644 index 0000000..2a3e8fc --- /dev/null +++ b/src/main/java/com/CTF/server/repository/MessageRepository.java @@ -0,0 +1,12 @@ +package com.CTF.server.repository; + +import com.CTF.server.entity.Message; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface MessageRepository extends JpaRepository { + List findByArticleId(Long articleId); +} \ No newline at end of file diff --git a/src/main/java/com/CTF/server/repository/UserRepository.java b/src/main/java/com/CTF/server/repository/UserRepository.java new file mode 100644 index 0000000..39a1295 --- /dev/null +++ b/src/main/java/com/CTF/server/repository/UserRepository.java @@ -0,0 +1,9 @@ +package com.CTF.server.repository; + +import com.CTF.server.entity.User; +import org.springframework.data.jpa.repository.JpaRepository; +import java.util.Optional; + +public interface UserRepository extends JpaRepository { + Optional findByUsername(String username); +} diff --git a/src/main/java/com/CTF/server/service/UserService.java b/src/main/java/com/CTF/server/service/UserService.java new file mode 100644 index 0000000..70c81fb --- /dev/null +++ b/src/main/java/com/CTF/server/service/UserService.java @@ -0,0 +1,11 @@ +package com.CTF.server.service; + +import com.CTF.server.entity.User; +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; + +@Service +public class UserService { +} diff --git a/src/main/java/com/CTF/server/util/JwtUtil.java b/src/main/java/com/CTF/server/util/JwtUtil.java new file mode 100644 index 0000000..9bbfeb4 --- /dev/null +++ b/src/main/java/com/CTF/server/util/JwtUtil.java @@ -0,0 +1,60 @@ +package com.CTF.server.util; + +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.nio.charset.StandardCharsets; +import java.util.Date; +import java.util.function.Function; + +@Component +public class JwtUtil { + + @Value("${jwt.secret}") + private String secret; + + @Value("${jwt.expiration}") + private long expiration; + + public String generateToken(String username) { + return Jwts.builder() + .setSubject(username) + .setIssuedAt(new Date()) + .setExpiration(new Date(System.currentTimeMillis() + expiration)) + .signWith(SignatureAlgorithm.HS512, secret.getBytes(StandardCharsets.UTF_8)) + .compact(); + } + + public Boolean validateToken(String token, String username) { + final String extractedUsername = getUsernameFromToken(token); + return (extractedUsername.equals(username) && !isTokenExpired(token)); + } + + public String getUsernameFromToken(String token) { + return getClaimFromToken(token, Claims::getSubject); + } + + public Date getExpirationDateFromToken(String token) { + return getClaimFromToken(token, Claims::getExpiration); + } + + public T getClaimFromToken(String token, Function claimsResolver) { + final Claims claims = getAllClaimsFromToken(token); + return claimsResolver.apply(claims); + } + + private Claims getAllClaimsFromToken(String token) { + return Jwts.parser() + .setSigningKey(secret.getBytes(StandardCharsets.UTF_8)) + .parseClaimsJws(token) + .getBody(); + } + + private Boolean isTokenExpired(String token) { + final Date expiration = getExpirationDateFromToken(token); + return expiration.before(new Date()); + } +} \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties new file mode 100644 index 0000000..25ed2ae --- /dev/null +++ b/src/main/resources/application.properties @@ -0,0 +1,23 @@ +spring.application.name=server +spring.datasource.url=jdbc:{{user}}://127.0.0.1:3306/dev_web +spring.datasource.username={{username}} +spring.datasource.password={{password}} + +spring.jpa.hibernate.ddl-auto=update +spring.jpa.show-sql=true +spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect +spring.jpa.properties.hibernate.jdbc.batch_size=50 +spring.jpa.properties.hibernate.order_inserts=true +spring.jpa.properties.hibernate.order_updates=true +spring.jpa.properties.hibernate.jdbc.batch_versioned_data=true + +server.port=8080 + +jwt.secret={{zrwJ84UHk3pS46XcMu1aVu3zaBH2929}} +jwt.expiration=3600000 + +spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8080 +spring.security.oauth2.resourceserver.jwt.jwk-set-uri=http://localhost:8080/keys + +logging.level.org.springframework.security=DEBUG + diff --git a/src/main/resources/public_key.pem b/src/main/resources/public_key.pem new file mode 100644 index 0000000..5f132de --- /dev/null +++ b/src/main/resources/public_key.pem @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2csPKInByXgFHs0/p/DW +LgtOO6HBAdyzDYQ82b300GjDWZFhMnplN1ICegqhdp6hZv1le2vqklQe7Yoq18vk +RHHwUww5z9rRWqu2D9jg1s8hfK8IM7aZMRKC5T+bQwlLf6XreAv/kPh83MVTilxT +J3kaBPS8amdlJjDt6Z9M3F7BaMgVlpcEd37ebfkV5hhdp6BLxfYowwokD9xLFdsk +sJEJQWXnoHZRw/guvjV4MlOMTN/M0te1AK+iYcBH5ZAZjUZXojBhrCjDi4vn/BUA +QkwhH0cYhegGvLqPXSmLhsE6rYs7kqUKsxkSgpbRVAXvqssYMX7jXPqTYRLcHwVl +EwIDAQAB +-----END PUBLIC KEY----- diff --git a/src/test/java/com/CTF/server/ServerApplicationTests.java b/src/test/java/com/CTF/server/ServerApplicationTests.java new file mode 100644 index 0000000..36d5f23 --- /dev/null +++ b/src/test/java/com/CTF/server/ServerApplicationTests.java @@ -0,0 +1,13 @@ +package com.CTF.server; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class ServerApplicationTests { + +// @Test +// void contextLoads() { +// } + +}