From d9f123cb085006a5bc7e7d3e49266b6e2640cd13 Mon Sep 17 00:00:00 2001 From: Andreas Svanberg <andreass@dsv.su.se> Date: Wed, 8 May 2024 18:12:33 +0200 Subject: [PATCH] wip --- .gitignore | 33 ++ .mvn/wrapper/maven-wrapper.jar | Bin 0 -> 62547 bytes .mvn/wrapper/maven-wrapper.properties | 2 + mvnw | 308 ++++++++++++++++++ mvnw.cmd | 205 ++++++++++++ pom.xml | 84 +++++ .../studentportalenpoc/NewSubscription.java | 6 + .../studentportalenpoc/PushController.java | 136 ++++++++ .../studentportalenpoc/SendPushMessage.java | 289 ++++++++++++++++ .../ServletInitializer.java | 13 + .../StudentportalenPocApplication.java | 34 ++ .../dsv/studentportalenpoc/Subscription.java | 13 + .../SubscriptionDetails.java | 5 + src/main/resources/application.properties | 1 + .../db/migration/V1__subscriptions.sql | 11 + .../static/images/icons/student-hat-128.png | Bin 0 -> 3877 bytes .../static/images/icons/student-hat-256.png | Bin 0 -> 7231 bytes .../static/images/icons/student-hat-32.png | Bin 0 -> 1070 bytes .../static/images/icons/student-hat-512.png | Bin 0 -> 13680 bytes .../static/images/icons/student-hat-64.png | Bin 0 -> 2108 bytes src/main/resources/static/index.html | 61 ++++ src/main/resources/static/manifest.json | 32 ++ src/main/resources/static/offline.html | 18 + src/main/resources/static/sw.js | 40 +++ .../StudentportalenPocApplicationTests.java | 13 + 25 files changed, 1304 insertions(+) create mode 100644 .gitignore create mode 100644 .mvn/wrapper/maven-wrapper.jar create mode 100644 .mvn/wrapper/maven-wrapper.properties create mode 100755 mvnw create mode 100644 mvnw.cmd create mode 100644 pom.xml create mode 100644 src/main/java/se/su/dsv/studentportalenpoc/NewSubscription.java create mode 100644 src/main/java/se/su/dsv/studentportalenpoc/PushController.java create mode 100644 src/main/java/se/su/dsv/studentportalenpoc/SendPushMessage.java create mode 100644 src/main/java/se/su/dsv/studentportalenpoc/ServletInitializer.java create mode 100644 src/main/java/se/su/dsv/studentportalenpoc/StudentportalenPocApplication.java create mode 100644 src/main/java/se/su/dsv/studentportalenpoc/Subscription.java create mode 100644 src/main/java/se/su/dsv/studentportalenpoc/SubscriptionDetails.java create mode 100644 src/main/resources/application.properties create mode 100644 src/main/resources/db/migration/V1__subscriptions.sql create mode 100644 src/main/resources/static/images/icons/student-hat-128.png create mode 100644 src/main/resources/static/images/icons/student-hat-256.png create mode 100644 src/main/resources/static/images/icons/student-hat-32.png create mode 100644 src/main/resources/static/images/icons/student-hat-512.png create mode 100644 src/main/resources/static/images/icons/student-hat-64.png create mode 100644 src/main/resources/static/index.html create mode 100644 src/main/resources/static/manifest.json create mode 100644 src/main/resources/static/offline.html create mode 100644 src/main/resources/static/sw.js create mode 100644 src/test/java/se/su/dsv/studentportalenpoc/StudentportalenPocApplicationTests.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ee6e957 --- /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/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..cb28b0e37c7d206feb564310fdeec0927af4123a GIT binary patch literal 62547 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 A?*IS* literal 0 HcmV?d00001 diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..e70e7bc --- /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.6/apache-maven-3.9.6-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 100755 index 0000000..66df285 --- /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 0000000..95ba6f5 --- /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 0000000..3e19659 --- /dev/null +++ b/pom.xml @@ -0,0 +1,84 @@ +<?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.5</version> + <relativePath/> <!-- lookup parent from repository --> + </parent> + <groupId>se.su.dsv</groupId> + <artifactId>studentportalen-poc</artifactId> + <version>0.0.1-SNAPSHOT</version> + <packaging>war</packaging> + <name>studentportalen-poc</name> + <description>studentportalen-poc</description> + <properties> + <java.version>21</java.version> + </properties> + <dependencies> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-jdbc</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-oauth2-client</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-web</artifactId> + </dependency> + <dependency> + <groupId>org.flywaydb</groupId> + <artifactId>flyway-core</artifactId> + </dependency> + <dependency> + <groupId>org.flywaydb</groupId> + <artifactId>flyway-mysql</artifactId> + </dependency> + + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-devtools</artifactId> + <scope>runtime</scope> + <optional>true</optional> + </dependency> + <dependency> + <groupId>org.mariadb.jdbc</groupId> + <artifactId>mariadb-java-client</artifactId> + <scope>runtime</scope> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-configuration-processor</artifactId> + <optional>true</optional> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-tomcat</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-test</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>com.auth0</groupId> + <artifactId>java-jwt</artifactId> + <version>4.2.1</version> + </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/se/su/dsv/studentportalenpoc/NewSubscription.java b/src/main/java/se/su/dsv/studentportalenpoc/NewSubscription.java new file mode 100644 index 0000000..ed52d43 --- /dev/null +++ b/src/main/java/se/su/dsv/studentportalenpoc/NewSubscription.java @@ -0,0 +1,6 @@ +package se.su.dsv.studentportalenpoc; + +import java.util.UUID; + +public record NewSubscription(UUID id, String applicationServerKey) { +} diff --git a/src/main/java/se/su/dsv/studentportalenpoc/PushController.java b/src/main/java/se/su/dsv/studentportalenpoc/PushController.java new file mode 100644 index 0000000..697fe98 --- /dev/null +++ b/src/main/java/se/su/dsv/studentportalenpoc/PushController.java @@ -0,0 +1,136 @@ +package se.su.dsv.studentportalenpoc; + +import org.springframework.jdbc.core.simple.JdbcClient; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.GeneralSecurityException; +import java.security.InvalidAlgorithmParameterException; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.Principal; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.ECPublicKey; +import java.security.spec.ECGenParameterSpec; +import java.security.spec.ECPoint; +import java.util.Arrays; +import java.util.Base64; +import java.util.List; +import java.util.UUID; + +@RestController +@RequestMapping("/api/push") +public class PushController { + + private final JdbcClient jdbcClient; + + public PushController(JdbcClient jdbcClient) { + this.jdbcClient = jdbcClient; + } + + @PostMapping("/subscription") + public NewSubscription createSubscription(Principal loggedInUser) + throws NoSuchAlgorithmException, InvalidAlgorithmParameterException + { + UUID id = UUID.randomUUID(); + KeyPairGenerator ec = KeyPairGenerator.getInstance("EC"); + ec.initialize(new ECGenParameterSpec("secp256r1")); + KeyPair keyPair = ec.generateKeyPair(); + + save(loggedInUser, id, keyPair); + return new NewSubscription(id, encodeAsBase64Uncompressed((ECPublicKey) keyPair.getPublic())); + } + + @PutMapping("/subscription/{id}") + public void updateSubscription( + @PathVariable("id") UUID id, + @RequestBody SubscriptionDetails subscriptionDetails) + { + String p256dh = subscriptionDetails.keys().p256dh(); + byte[] decoded = Base64.getUrlDecoder().decode(p256dh); + byte[] x = Arrays.copyOfRange(decoded, 1, 33); + byte[] y = Arrays.copyOfRange(decoded, 33, 65); + BigInteger affineX = new BigInteger(1, x); + BigInteger affineY = new BigInteger(1, y); + ECPoint clientPublicW = new ECPoint(affineX, affineY); + + update(id, subscriptionDetails.endpoint(), subscriptionDetails.keys().auth(), clientPublicW); + } + + @PostMapping("/subscription/send") + public void sendNotification(Principal loggedInUser) { + getSubscriptions(loggedInUser).forEach(subscription -> { + try { + SendPushMessage.sendPushMessage(subscription.applicationS(), subscription.applicationPublicW(), subscription.clientPublicW(), subscription.auth(), subscription.endpoint()); + } catch (GeneralSecurityException | IOException | InterruptedException e) { + throw new RuntimeException(e); + } + }); + } + + private List<Subscription> getSubscriptions(Principal owner) { + return jdbcClient.sql(""" + SELECT public_affine_x, public_affine_y, private_s, client_public_affine_x, client_public_affine_y, auth, endpoint + FROM subscriptions + WHERE owner = :owner AND endpoint IS NOT NULL + """) + .param("owner", owner.getName()) + .query((rs, rowNum) -> { + String endpoint = rs.getString("endpoint"); + String auth = rs.getString("auth"); + BigInteger applicationX = new BigInteger(rs.getString("public_affine_x")); + BigInteger applicationY = new BigInteger(rs.getString("public_affine_y")); + ECPoint applicationPublicW = new ECPoint(applicationX, applicationY); + BigInteger applicationS = new BigInteger(rs.getString("private_s")); + + BigInteger clientX = new BigInteger(rs.getString("client_public_affine_x")); + BigInteger clientY = new BigInteger(rs.getString("client_public_affine_y")); + ECPoint clientPublicW = new ECPoint(clientX, clientY); + return new Subscription(endpoint, auth, clientPublicW, applicationPublicW, applicationS); + }) + .list(); + } + + private void update(UUID id, String endpoint, String auth, ECPoint clientPublicW) { + jdbcClient.sql(""" + UPDATE subscriptions + SET endpoint = :endpoint, auth = :auth, client_public_affine_x = :x, client_public_affine_y = :y + WHERE id = :id + """) + .param("id", id.toString()) + .param("endpoint", endpoint) + .param("auth", auth) + .param("x", clientPublicW.getAffineX().toString()) + .param("y", clientPublicW.getAffineY().toString()) + .update(); + } + + private void save(Principal owner, UUID id, KeyPair keyPair) { + ECPoint w = ((ECPublicKey) keyPair.getPublic()).getW(); + jdbcClient.sql("INSERT INTO subscriptions (id, owner, public_affine_x, public_affine_y, private_s) VALUES (:id, :owner, :x, :y, :s)") + .param("id", id.toString()) + .param("owner", owner.getName()) + .param("x", w.getAffineX().toString()) + .param("y", w.getAffineY().toString()) + .param("s", ((ECPrivateKey) keyPair.getPrivate()).getS().toString()) + .update(); + } + + private String encodeAsBase64Uncompressed(ECPublicKey aPublic) { + byte[] uncompressed = new byte[65]; + uncompressed[0] = 0x04; + byte[] x = aPublic.getW().getAffineX().toByteArray(); + byte[] y = aPublic.getW().getAffineY().toByteArray(); + System.arraycopy(x, x.length == 33 ? 1 : 0, uncompressed, 1, x.length == 33 ? 32 : x.length); + System.arraycopy(y, y.length == 33 ? 1 : 0, uncompressed, 33, y.length == 33 ? 32 : y.length); + return Base64.getUrlEncoder().withoutPadding().encodeToString(uncompressed); + } + +} diff --git a/src/main/java/se/su/dsv/studentportalenpoc/SendPushMessage.java b/src/main/java/se/su/dsv/studentportalenpoc/SendPushMessage.java new file mode 100644 index 0000000..e7082bd --- /dev/null +++ b/src/main/java/se/su/dsv/studentportalenpoc/SendPushMessage.java @@ -0,0 +1,289 @@ +package se.su.dsv.studentportalenpoc; + +import com.auth0.jwt.JWT; +import com.auth0.jwt.algorithms.Algorithm; + +import javax.crypto.Cipher; +import javax.crypto.KeyAgreement; +import javax.crypto.Mac; +import javax.crypto.spec.GCMParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import java.io.IOException; +import java.math.BigInteger; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.security.AlgorithmParameters; +import java.security.GeneralSecurityException; +import java.security.InvalidKeyException; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.SecureRandom; +import java.security.interfaces.ECKey; +import java.security.interfaces.ECPublicKey; +import java.security.spec.ECGenParameterSpec; +import java.security.spec.ECParameterSpec; +import java.security.spec.ECPoint; +import java.security.spec.ECPrivateKeySpec; +import java.security.spec.ECPublicKeySpec; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.InvalidParameterSpecException; +import java.time.Duration; +import java.time.Instant; +import java.util.Arrays; +import java.util.Base64; + +public class SendPushMessage { + public static final String WEB_PUSH_APPLICATION_SERVER_KEY_ALGORITHM_CURVE = "secp256r1"; + public static final String WEB_PUSH_APPLICATION_SERVER_KEY_ALGORITHM = "EC"; + + public static void sendPushMessage( + BigInteger applicationPrivateKey, + ECPoint applicationPublicKey, + ECPoint clientP256dh, + String clientAuth, + String endpoint) + throws + GeneralSecurityException, + IOException, InterruptedException + { + PrivateKey privateKey = recreatePrivateKey(applicationPrivateKey); + PublicKey publicKey = recreatePublicKey(applicationPublicKey); + + Instant now = Instant.now().plus(Duration.ofMinutes(60)); + + URI uri = URI.create(endpoint); + String audience = uri.getScheme() + "://" + uri.getHost(); + + String token = JWT.create() + .withAudience(audience) + .withExpiresAt(now) + .withSubject("mailto:andreass@dsv.su.se") + .sign(Algorithm.ECDSA256((ECKey) privateKey)); + System.out.println(token); + + String payload = "Still worky?"; + final PublicKey p256dh = recreatePublicKey(clientP256dh); + System.out.println(toBase64(p256dh)); + final byte[] auth = Base64.getUrlDecoder().decode(clientAuth); + byte[] encrypted = encrypt(payload, p256dh, auth); + + HttpRequest httpRequest = HttpRequest.newBuilder() + .uri(uri) + .headers("Authorization", "vapid t=" + token + ", k=" + toBase64(publicKey)) + .header("TTL", Long.toString(Duration.ofMinutes(5).toSeconds())) + .header("Content-Encoding", "aes128gcm") + .header("Content-Type", "application/octet-stream") + .POST(HttpRequest.BodyPublishers.ofByteArray(encrypted)) + .build(); + + try (HttpClient httpClient = HttpClient.newHttpClient()) { + HttpResponse<String> httpResponse = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); + System.out.println(httpResponse); + System.out.println(httpResponse.headers()); + System.out.println(httpResponse.body()); + } + } + + private static PrivateKey recreatePrivateKey(BigInteger applicationPrivateKey) + throws GeneralSecurityException + { + AlgorithmParameters algorithmParameters = AlgorithmParameters.getInstance(WEB_PUSH_APPLICATION_SERVER_KEY_ALGORITHM); + algorithmParameters.init(new ECGenParameterSpec(WEB_PUSH_APPLICATION_SERVER_KEY_ALGORITHM_CURVE)); + ECParameterSpec parameterSpec = algorithmParameters.getParameterSpec(ECParameterSpec.class); + + KeyFactory keyFactory = KeyFactory.getInstance(WEB_PUSH_APPLICATION_SERVER_KEY_ALGORITHM); + return keyFactory.generatePrivate(new ECPrivateKeySpec(applicationPrivateKey, parameterSpec)); + } + + private static PublicKey recreatePublicKey(ECPoint publicKeyW) + throws GeneralSecurityException + { + AlgorithmParameters algorithmParameters = AlgorithmParameters.getInstance(WEB_PUSH_APPLICATION_SERVER_KEY_ALGORITHM); + algorithmParameters.init(new ECGenParameterSpec(WEB_PUSH_APPLICATION_SERVER_KEY_ALGORITHM_CURVE)); + ECParameterSpec parameterSpec = algorithmParameters.getParameterSpec(ECParameterSpec.class); + + KeyFactory keyFactory = KeyFactory.getInstance(WEB_PUSH_APPLICATION_SERVER_KEY_ALGORITHM); + return keyFactory.generatePublic(new ECPublicKeySpec(publicKeyW, parameterSpec)); + } + + private static byte[] encrypt(final String payload, final PublicKey p256dh, final byte[] auth) throws + GeneralSecurityException + { + KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC"); + keyPairGenerator.initialize(new ECGenParameterSpec(WEB_PUSH_APPLICATION_SERVER_KEY_ALGORITHM_CURVE)); + KeyPair local = keyPairGenerator.generateKeyPair(); + + byte[] salt = new byte[16]; + new SecureRandom().nextBytes(salt); + + byte[] ikm = webPushIKM(p256dh, auth, local); + return ece_encrypt(payload, local.getPublic(), salt, ikm); + } + + private static byte[] webPushIKM(final PublicKey p256dh, final byte[] auth, final KeyPair local) throws GeneralSecurityException { + byte[] secret = generateSharedSecret(local.getPrivate(), p256dh); + byte[] info = concat("WebPush: info\0".getBytes(), encodeUncompressed(p256dh), encodeUncompressed(local.getPublic())); + return extractAndExpand(secret, auth, info, 32); + } + + private static byte[] ece_encrypt(final String payload, final PublicKey publicKey, final byte[] salt, final byte[] ikm) throws + GeneralSecurityException + { + byte[] key = extractAndExpand(ikm, salt, "Content-Encoding: aes128gcm\0".getBytes(), 16); + byte[] none = extractAndExpand(ikm, salt, "Content-Encoding: nonce\0".getBytes(), 12); + + byte[] rawPublicKey = encodeUncompressed(publicKey); + ByteBuffer buffer = ByteBuffer.allocate(4); + buffer.putInt(4096); + byte[] rs = buffer.array(); + byte[] idlen = new byte[] { (byte) rawPublicKey.length }; + byte[] header = concat(salt, rs, idlen, rawPublicKey); + + Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); + cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"), new GCMParameterSpec(16 * 8, none)); + byte[][] parts = { + header, + cipher.update(payload.getBytes(StandardCharsets.UTF_8)), + cipher.update(new byte[]{2}), + cipher.doFinal() + }; + return concat(parts); + } + + private static byte[] concat(final byte[]... arrays) { + int lastPos = 0; + + byte[] combined = new byte[combinedLength(arrays)]; + + for (byte[] array : arrays) { + if (array == null) { + continue; + } + + System.arraycopy(array, 0, combined, lastPos, array.length); + + lastPos += array.length; + } + + return combined; + } + + private static int combinedLength(final byte[][] arrays) { + int combinedLength = 0; + + for (byte[] array : arrays) { + if (array == null) { + continue; + } + + combinedLength += array.length; + } + + return combinedLength; + } + + private static byte[] extractAndExpand(final byte[] ikm, final byte[] salt, final byte[] info, final int outputLength) { + return expand(extract(salt, ikm), info, outputLength); + } + + private static byte[] extract(final byte[] salt, final byte[] ikm) { + try { + Mac hmacSHA256 = Mac.getInstance("HmacSHA256"); + hmacSHA256.init(new SecretKeySpec(salt, "HmacSHA256")); + return hmacSHA256.doFinal(ikm); + } catch (InvalidKeyException e) { + throw new IllegalArgumentException("Invalid key material provided", e); + } catch (NoSuchAlgorithmException e) { + throw new Error(e); + } + } + + private static byte[] expand(final byte[] pseudoRandomKey, final byte[] info, final int length) { + try { + Mac hmacSHA256 = Mac.getInstance("HmacSHA256"); + hmacSHA256.reset(); + hmacSHA256.init(new SecretKeySpec(pseudoRandomKey, "HmacSHA256")); + hmacSHA256.update(info); + hmacSHA256.update((byte) 0x01); + byte[] expanded = hmacSHA256.doFinal(); + return Arrays.copyOfRange(expanded, 0, length); + } catch (NoSuchAlgorithmException | InvalidKeyException e) { + throw new IllegalStateException(e); + } + } + + private static byte[] generateSharedSecret(final PrivateKey local, final PublicKey p256dh) throws + NoSuchAlgorithmException, + InvalidKeyException + { + KeyAgreement keyAgreement = KeyAgreement.getInstance("ECDH"); + keyAgreement.init(local); + keyAgreement.doPhase(p256dh, true); + return keyAgreement.generateSecret(); + } + + private static String toBase64(final PublicKey publicKey) { + byte[] bytes = encodeUncompressed(publicKey); + return Base64.getUrlEncoder().withoutPadding().encodeToString(bytes); + } + + private static byte[] encodeUncompressed(final PublicKey publicKey) { + ECPublicKey ecPublicKey = (ECPublicKey) publicKey; + byte[] bytes = new byte[65]; + bytes[0] = 4; // uncompressed + byte[] x = ecPublicKey.getW().getAffineX().toByteArray(); + byte[] y = ecPublicKey.getW().getAffineY().toByteArray(); + System.arraycopy(x, x.length - 32, bytes, 1, 32); + System.arraycopy(y, y.length - 32, bytes, 1 + 32, 32); + return bytes; + } + + private static PrivateKey decodeBase64ECPrivateKey(final String base64encodedPrivateKey) throws + NoSuchAlgorithmException, + InvalidParameterSpecException, + InvalidKeySpecException + { + AlgorithmParameters algorithmParameters = AlgorithmParameters.getInstance(WEB_PUSH_APPLICATION_SERVER_KEY_ALGORITHM); + algorithmParameters.init(new ECGenParameterSpec(WEB_PUSH_APPLICATION_SERVER_KEY_ALGORITHM_CURVE)); + ECParameterSpec parameterSpec = algorithmParameters.getParameterSpec(ECParameterSpec.class); + + byte[] decoded = Base64.getUrlDecoder().decode(base64encodedPrivateKey); + byte[] bytes = Arrays.copyOfRange(decoded, 1, 33); + ECPrivateKeySpec ecPublicKeySpec = new ECPrivateKeySpec(new BigInteger(decoded), parameterSpec); + + KeyFactory keyFactory = KeyFactory.getInstance(WEB_PUSH_APPLICATION_SERVER_KEY_ALGORITHM); + return keyFactory.generatePrivate(ecPublicKeySpec); + } + + public static PublicKey decodeBase64ECPublicKey(String base64encodedPublicKey) throws + NoSuchAlgorithmException, + InvalidParameterSpecException, + InvalidKeySpecException + { + AlgorithmParameters algorithmParameters = AlgorithmParameters.getInstance(WEB_PUSH_APPLICATION_SERVER_KEY_ALGORITHM); + algorithmParameters.init(new ECGenParameterSpec(WEB_PUSH_APPLICATION_SERVER_KEY_ALGORITHM_CURVE)); + ECParameterSpec parameterSpec = algorithmParameters.getParameterSpec(ECParameterSpec.class); + + ECPoint w = decodeW(base64encodedPublicKey); + ECPublicKeySpec ecPublicKeySpec = new ECPublicKeySpec(w, parameterSpec); + + KeyFactory keyFactory = KeyFactory.getInstance(WEB_PUSH_APPLICATION_SERVER_KEY_ALGORITHM); + return keyFactory.generatePublic(ecPublicKeySpec); + } + + private static ECPoint decodeW(final String base64encodedPublicKey) { + byte[] bytes = Base64.getUrlDecoder().decode(base64encodedPublicKey); + byte[] x = Arrays.copyOfRange(bytes, 1, 33); + byte[] y = Arrays.copyOfRange(bytes, 33, 65); + + return new ECPoint(new BigInteger(1, x), new BigInteger(1, y)); + } +} diff --git a/src/main/java/se/su/dsv/studentportalenpoc/ServletInitializer.java b/src/main/java/se/su/dsv/studentportalenpoc/ServletInitializer.java new file mode 100644 index 0000000..749799e --- /dev/null +++ b/src/main/java/se/su/dsv/studentportalenpoc/ServletInitializer.java @@ -0,0 +1,13 @@ +package se.su.dsv.studentportalenpoc; + +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; + +public class ServletInitializer extends SpringBootServletInitializer { + + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { + return application.sources(StudentportalenPocApplication.class); + } + +} diff --git a/src/main/java/se/su/dsv/studentportalenpoc/StudentportalenPocApplication.java b/src/main/java/se/su/dsv/studentportalenpoc/StudentportalenPocApplication.java new file mode 100644 index 0000000..a32b072 --- /dev/null +++ b/src/main/java/se/su/dsv/studentportalenpoc/StudentportalenPocApplication.java @@ -0,0 +1,34 @@ +package se.su.dsv.studentportalenpoc; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.web.SecurityFilterChain; + +import static org.springframework.security.config.Customizer.withDefaults; + +@SpringBootApplication +public class StudentportalenPocApplication { + + public static void main(String[] args) { + SpringApplication.run(StudentportalenPocApplication.class, args); + } + + /** + * Secures the application with Oauth2 + */ + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + http + .csrf(crsf -> crsf.disable()) + .authorizeHttpRequests(authorize -> authorize + .requestMatchers("manifest.json").anonymous() + .requestMatchers("sw.js").permitAll() + .requestMatchers("images/**").permitAll() + .anyRequest().authenticated()) + .oauth2Login(withDefaults()); + return http.build(); + } +} diff --git a/src/main/java/se/su/dsv/studentportalenpoc/Subscription.java b/src/main/java/se/su/dsv/studentportalenpoc/Subscription.java new file mode 100644 index 0000000..c913894 --- /dev/null +++ b/src/main/java/se/su/dsv/studentportalenpoc/Subscription.java @@ -0,0 +1,13 @@ +package se.su.dsv.studentportalenpoc; + +import java.math.BigInteger; +import java.security.spec.ECPoint; + +public record Subscription( + String endpoint, + String auth, + ECPoint clientPublicW, + ECPoint applicationPublicW, + BigInteger applicationS) +{ +} diff --git a/src/main/java/se/su/dsv/studentportalenpoc/SubscriptionDetails.java b/src/main/java/se/su/dsv/studentportalenpoc/SubscriptionDetails.java new file mode 100644 index 0000000..9c23e8d --- /dev/null +++ b/src/main/java/se/su/dsv/studentportalenpoc/SubscriptionDetails.java @@ -0,0 +1,5 @@ +package se.su.dsv.studentportalenpoc; + +public record SubscriptionDetails(String endpoint, Keys keys) { + public record Keys(String auth, String p256dh) {} +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties new file mode 100644 index 0000000..c594e65 --- /dev/null +++ b/src/main/resources/application.properties @@ -0,0 +1 @@ +spring.application.name=studentportalen-poc diff --git a/src/main/resources/db/migration/V1__subscriptions.sql b/src/main/resources/db/migration/V1__subscriptions.sql new file mode 100644 index 0000000..2057b15 --- /dev/null +++ b/src/main/resources/db/migration/V1__subscriptions.sql @@ -0,0 +1,11 @@ +CREATE TABLE subscriptions ( + id UUID PRIMARY KEY, + owner TEXT NOT NULL, + public_affine_x TEXT NOT NULL, + public_affine_y TEXT NOT NULL, + private_s TEXT NOT NULL, + client_public_affine_x TEXT, + client_public_affine_y TEXT, + auth TEXT, + endpoint TEXT +); diff --git a/src/main/resources/static/images/icons/student-hat-128.png b/src/main/resources/static/images/icons/student-hat-128.png new file mode 100644 index 0000000000000000000000000000000000000000..622845ecdddeaf72d95af04f5367e50103e4f933 GIT binary patch literal 3877 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/static/images/icons/student-hat-256.png b/src/main/resources/static/images/icons/student-hat-256.png new file mode 100644 index 0000000000000000000000000000000000000000..b7deb64358419d866df2238d4a1c3db6f2ded087 GIT binary patch literal 7231 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 MX&Gvks@q5XKO(9zod5s; literal 0 HcmV?d00001 diff --git a/src/main/resources/static/images/icons/student-hat-32.png b/src/main/resources/static/images/icons/student-hat-32.png new file mode 100644 index 0000000000000000000000000000000000000000..9583a3fa3eafdcad5af4eb83f2b903980235dd74 GIT binary patch literal 1070 zcmV+}1kwA6P)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F800009a7bBm0002& z0002&0eL8Ky#N3J8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H11G`B? zK~z|U?Ur3=990y6zjJ42cGK!MKO$NX(iYLQwn^M#w>6>U!J<^qR45ejLGVTEPY|gU z3@lQy{=Eo-4<h(hqO}$gq&|cYYizTdWTQzW=_aWteQBG`HZ(swbB_<%gw>?Uh6=vq zgUe;+&bjB~oIAt7I_s?SKO<`msCYBE$@PP{RpKgIEh@jFlER(qx%xrFjsI34p{8>7 z!h?ttH_ARm<3J5y6h;NcfSthIfJGTWNGX~!NXmw7@AX7HSF*re$9}pq*bu43@~9CS zRM?ABg^&mOQO=8KD#$w>*>@klycn10*&JAniLo(Ji7D&`?kQxrB1%d{Q)*4h&-*{$ zcyG_OB?46^x*xG(&I6&st*fH?S%5h^=}-2NX!2LBXAzYrF5ZU;?NQa|fP;WjSn`cA z`>wrJ-~G=Dd@>R)pP4#>XahnVoi8;iqhPy4_{9oclT*3$vNDPGP{qdRc7+&XVrn%e zLM>1ROc&<w5ILRo?l{G(_s=eAK`|94lbeDv=WCQ|kW0+>zZ|$JkhEx*!HlWsPE=xo z)+&?<Oe>N`G^LgXG5ndE$UYq{FV71co@}ZAsyL6imB7UD-IKUx0?+j3TI!z2W$UVJ zM0aRdUa_7T!E>Ipo_wsXiQ$p5o^v$tLba3GY&6$Ww>S4%{mT+I!?@-qi6&n?L*O|} z@`RSjy@>US3X~8#1%u3wFII|ME?&Lmi@l<NdIr#%4PW*@70NrExfga^FC}sG^MOj= z4H{LX24rYKK+v@bSXbIacpKzfKdg4cso(kq=}>4789H-^=Y^te1C_p|QJ_iD{XV)2 zj8RCdO51{fU8du!ehDLIhN?w%3^)$l3+xAW6_)!8bMbWta0NK2B3ovfYsLY}z8U-- z<oW4CHC<~G2!B8Ln5dkK<Yy|f&GlJ;=nn&xGlA3SV4DB}Onbx$I&+WDSET$*Z~2TH znNZOKvj?~TxYGVBwg3QEL=m##=wbs4iOv=V0CPnlS=W)UCx~&DHvM1R@-<vQT!z&X zB3?eWs%(MC#z;&(K_brZZ41ma)r_kvJ$}f%SgL^U@{+nHIo+`BkJ}aiu%6S3XP$Ao zGe=f?*14E@mau77S6WNiyJSM?OCLJv%$(`VyiR-j(zBCHx+XpPhLg_ZLw%X|OWn8h z9}-nDL*vH~eFyjpI4#HkfT9lphk(rpt@eQ}A0e{p0bHBF0%K#<CXk~ldH~o4qM#WO oIcKq-vUTg_RrgqDopp-%8|vwFyh>7tkN^Mx07*qoM6N<$f(9k@6aWAK literal 0 HcmV?d00001 diff --git a/src/main/resources/static/images/icons/student-hat-512.png b/src/main/resources/static/images/icons/student-hat-512.png new file mode 100644 index 0000000000000000000000000000000000000000..6b21fc1cf028ee40b7454f35a78aa7b685258d8d GIT binary patch literal 13680 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/static/images/icons/student-hat-64.png b/src/main/resources/static/images/icons/student-hat-64.png new file mode 100644 index 0000000000000000000000000000000000000000..9cbf121a168a4a04f4a233a0aacd3785f8acecdd GIT binary patch literal 2108 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�>#p2_g;+<9)hy4-WN1(A)YtOflzaJT>KIgtM%+J)+0ID5|_+Jf2a mgoK2IgoK2IgoK2I<l=uHUjM177AU9y0000<MNUMnLSTaT@9#1I literal 0 HcmV?d00001 diff --git a/src/main/resources/static/index.html b/src/main/resources/static/index.html new file mode 100644 index 0000000..03ed31d --- /dev/null +++ b/src/main/resources/static/index.html @@ -0,0 +1,61 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <title>Studentportalen [proof-of-concept progressive web app]</title> + <link rel="manifest" href="manifest.json"> + <link rel="icon" href="images/icons/student-hat-32.png" type="image/png" sizes="32x32"> + <link rel="icon" href="images/icons/student-hat-64.png" type="image/png" sizes="64x64"> + <link rel="icon" href="images/icons/student-hat-128.png" type="image/png" sizes="128x128"> + <link rel="icon" href="images/icons/student-hat-256.png" type="image/png" sizes="256x256"> + <link rel="icon" href="images/icons/student-hat-512.png" type="image/png" sizes="512x512"> +</head> +<body> +<div id="sw"> + <button id="subscribe">Subscribe to push notifications</button> + <button id="send">Send push notification</button> +</div> +<script> + async function doStuff() { + const registration = await navigator.serviceWorker.register('sw.js') + + const button = document.getElementById('subscribe'); + button.addEventListener('click', async () => { + const permission = await Notification.requestPermission(); + + if (permission !== 'granted') { + alert('Permission not granted for Notification'); + throw new Error('Permission not granted for Notification'); + } + + const {applicationServerKey, id} = await fetch('api/push/subscription', {method:'POST'}).then(res => res.json()); + + const activeSubscription = await registration.pushManager.getSubscription(); + + if (activeSubscription) { + await activeSubscription.unsubscribe(); + } + + const subscription = await registration.pushManager.subscribe({ + userVisibleOnly: true, + applicationServerKey: applicationServerKey + }); + await fetch(`api/push/subscription/${id}`, { + method: 'PUT', + body: JSON.stringify(subscription), + headers: { + 'content-type': 'application/json' + } + }); + }); + + document.getElementById('send').addEventListener('click', async () => { + await fetch('api/push/subscription/send', {method: 'POST'}); + }); + } + + doStuff(); +</script> +</body> +</html> \ No newline at end of file diff --git a/src/main/resources/static/manifest.json b/src/main/resources/static/manifest.json new file mode 100644 index 0000000..0eead0c --- /dev/null +++ b/src/main/resources/static/manifest.json @@ -0,0 +1,32 @@ +{ + "name": "Studentportalen Proof-of-Concept", + "icons": [ + { + "src": "images/icons/student-hat-32.png", + "sizes": "32x32", + "type": "image/png" + }, + { + "src": "images/icons/student-hat-64.png", + "sizes": "64x64", + "type": "image/png" + }, + { + "src": "images/icons/student-hat-128.png", + "sizes": "128x128", + "type": "image/png" + }, + { + "src": "images/icons/student-hat-256.png", + "sizes": "256x256", + "type": "image/png" + }, + { + "src": "images/icons/student-hat-512.png", + "sizes": "512x512", + "type": "image/png" + } + ], + "start_url": "index.html", + "display": "fullscreen" +} diff --git a/src/main/resources/static/offline.html b/src/main/resources/static/offline.html new file mode 100644 index 0000000..494120f --- /dev/null +++ b/src/main/resources/static/offline.html @@ -0,0 +1,18 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <title>Studentportalen [proof-of-concept progressive web app]</title> + <link rel="manifest" href="manifest.json"> + <link rel="icon" href="images/icons/student-hat-32.png" type="image/png" sizes="32x32"> + <link rel="icon" href="images/icons/student-hat-64.png" type="image/png" sizes="64x64"> + <link rel="icon" href="images/icons/student-hat-128.png" type="image/png" sizes="128x128"> + <link rel="icon" href="images/icons/student-hat-256.png" type="image/png" sizes="256x256"> + <link rel="icon" href="images/icons/student-hat-512.png" type="image/png" sizes="512x512"> +</head> +<body> +<h1>Offline</h1> +<p>Oh no, you are offline. Please check your internet connection.</p> +</body> +</html> \ No newline at end of file diff --git a/src/main/resources/static/sw.js b/src/main/resources/static/sw.js new file mode 100644 index 0000000..ee6c5ac --- /dev/null +++ b/src/main/resources/static/sw.js @@ -0,0 +1,40 @@ +self.addEventListener('install', function (event) { + console.log('Service Worker installing.', event); + caches.open('v1').then(function (cache) { + return cache.addAll([ + 'offline.html', + ]); + }); +}); + +self.addEventListener('activate', function (event) { + console.log('Service Worker activating.', event); +}); + +self.addEventListener('push', /** @param {PushEvent} event */ function (event) { + console.log('Service Worker received message:', event); + + const showPromise = self.registration.showNotification('Push message', { + body: event.data.text() + }); + + event.waitUntil(showPromise); +}); + +self.addEventListener('fetch', /** @param {FetchEvent} event */ async function (event) { + console.log('Service Worker fetching.', event); + + const cache = await caches.open('v1'); + const cachedResponse = await cache.match(event.request); + + const fetchedResponse = fetch(event.request) + .then(function (networkResponse) { + cache.put(event.request, networkResponse.clone()); + return networkResponse; + }) + .catch(function () { + return cache.match('offline.html'); + }); + + event.respondWith(cachedResponse || fetchedResponse); +}); diff --git a/src/test/java/se/su/dsv/studentportalenpoc/StudentportalenPocApplicationTests.java b/src/test/java/se/su/dsv/studentportalenpoc/StudentportalenPocApplicationTests.java new file mode 100644 index 0000000..dae5bcb --- /dev/null +++ b/src/test/java/se/su/dsv/studentportalenpoc/StudentportalenPocApplicationTests.java @@ -0,0 +1,13 @@ +package se.su.dsv.studentportalenpoc; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class StudentportalenPocApplicationTests { + + @Test + void contextLoads() { + } + +}