commit 2fe26bb5edb71f33ff4781aaa2cd8fd3d70f7a7f Author: lorenzhohermuth Date: Fri Mar 28 16:03:38 2025 +0100 existierendes front und back end diff --git a/183_12_1_tresorbackend_rupe-master/.gitignore b/183_12_1_tresorbackend_rupe-master/.gitignore new file mode 100644 index 0000000..7ed0d6b --- /dev/null +++ b/183_12_1_tresorbackend_rupe-master/.gitignore @@ -0,0 +1,32 @@ +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/183_12_1_tresorbackend_rupe-master/.mvn/wrapper/maven-wrapper.jar b/183_12_1_tresorbackend_rupe-master/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 0000000..cb28b0e Binary files /dev/null and b/183_12_1_tresorbackend_rupe-master/.mvn/wrapper/maven-wrapper.jar differ diff --git a/183_12_1_tresorbackend_rupe-master/.mvn/wrapper/maven-wrapper.properties b/183_12_1_tresorbackend_rupe-master/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..5f0536e --- /dev/null +++ b/183_12_1_tresorbackend_rupe-master/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,2 @@ +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar diff --git a/183_12_1_tresorbackend_rupe-master/Dockerfile b/183_12_1_tresorbackend_rupe-master/Dockerfile new file mode 100644 index 0000000..21ef302 --- /dev/null +++ b/183_12_1_tresorbackend_rupe-master/Dockerfile @@ -0,0 +1,52 @@ +# First part +#============ + +# Start with an image containing JDK 17 +FROM openjdk:17-jdk-slim AS build + +# Install Maven +RUN apt-get update && apt-get install -y --no-install-recommends maven git \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# Setup working directory +WORKDIR /App + +# Copy the pom.xml file to the image +COPY ./pom.xml /App/ + +# Cache maven dependencies +RUN mvn dependency:resolve + +# Copy the entire src directory to the image +COPY ./src /App/src + +# Build the app +RUN mvn clean package -Dmaven.test.skip=true + +# Current dir is /App +# ==> You will find the result in folder target/ + +# Second part +#============ + +# start with a small image +FROM alpine:latest + +# add JRE 17 +RUN apk add --no-cache openjdk17-jre + +# Set working directory +WORKDIR /App + +# copy jar form first image to second image +COPY --from=build /App/target/*.jar /App/ + +# db has to start for backend +COPY wait-for-db.sh /usr/local/bin/wait-for-db.sh +RUN chmod +x /usr/local/bin/wait-for-db.sh + +# Expose Port +EXPOSE 8080 + +ENTRYPOINT ["sh", "-c", "java -jar *.jar"] \ No newline at end of file diff --git a/183_12_1_tresorbackend_rupe-master/README.md b/183_12_1_tresorbackend_rupe-master/README.md new file mode 100644 index 0000000..32ca7bf --- /dev/null +++ b/183_12_1_tresorbackend_rupe-master/README.md @@ -0,0 +1,40 @@ +# Backend for the _secret tresor application_ + +This is the backend is a Java Springboot application. + +It can be used by API-calls. + +The data's are stored in a database. + +### information about database + +prepare a database server and the database used by the application
+see [tresordb.sql](tresordb.sql) for an example database
+see [application.properties](src/main/resources/application.properties) about database access + +## Requests examples + +see [UserRequests.http](httprequest/UserRequests.http)
+see [SecretRequests.http](httprequest/SecretRequests.http) + +## Environment variables + +see [application.properties](src/main/resources/application.properties) + +## Build image + +see Dockerfile + +```Bash +docker build -t tresorbackendimg . +``` + + + +## Start container local + +```Bash +docker run -p 8080:8080 --name tresorbackend tresorbackendimg +``` + +(c) P.Rutschmann diff --git a/183_12_1_tresorbackend_rupe-master/httprequest/SecretRequests.http b/183_12_1_tresorbackend_rupe-master/httprequest/SecretRequests.http new file mode 100644 index 0000000..21cce3b --- /dev/null +++ b/183_12_1_tresorbackend_rupe-master/httprequest/SecretRequests.http @@ -0,0 +1,73 @@ +### +#Get all secrets +GET http://localhost:8080/api/secrets +Accept: application/json + +### +# Create new secret +POST http://localhost:8080/api/secrets +Content-Type: application/json + +{ + "email": "hans.muster@bbw.ch", + "content": { + "kindid": 3, + "kind": "note", + "title": "Spaphira", + "content": "Saphira roch an dem kleinen Erdling." + }, + "encryptPassword": "xxxyyy" +} + +### +#Post to get secrets with userid 1 and encryptpassword +POST http://localhost:8080/api/secrets/byuserid +Content-Type: application/json + +{ + "userId": 1, + "encryptPassword": "xxxyyy" +} + +### +#Post to get secrets with email and encryptpassword +POST http://localhost:8080/api/secrets/byemail +Content-Type: application/json + +{ + "email": "hans.muster@bbw.ch", + "encryptPassword": "xxxyyy" +} + +### +# Update secret with id 3 +PUT http://localhost:8080/api/secrets/3 +Content-Type: application/json + +{ + "userId": 1, + "content": { + "kindid": 3, + "kind": "note", + "title": "Red drageon", + "content": "Er war gewaltig und rot." + }, + "encryptPassword": "xxxyyy" +} + +### +#Delete secret with id 3 +DELETE http://localhost:8080/api/secrets/3 +Accept: application/json + + +### +#Delete secret with id 4 +DELETE http://localhost:8080/api/secrets/4 +Accept: application/json + +### +#Delete secret with id 5 +DELETE http://localhost:8080/api/secrets/5 +Accept: application/json + diff --git a/183_12_1_tresorbackend_rupe-master/httprequest/UserRequests.http b/183_12_1_tresorbackend_rupe-master/httprequest/UserRequests.http new file mode 100644 index 0000000..bf8d5d8 --- /dev/null +++ b/183_12_1_tresorbackend_rupe-master/httprequest/UserRequests.http @@ -0,0 +1,47 @@ +### +#Get all users +GET http://localhost:8080/api/users +Accept: application/json + +### +# Create user Violett Weber +POST http://localhost:8080/api/users +Content-Type: application/json + +{ + "firstName": "Violett", + "lastName": "Weber", + "email": "violett.weber@bbw.ch", + "password": "1234", + "passwordConfirmation": "1234" +} + +### +#Get user with id 4 +GET http://localhost:8080/api/users/4 +Accept: application/json + +### +# Update user with id 4 +PUT http://localhost:8080/api/users/4 +Content-Type: application/json + +{ + "firstName": "Iris", + "lastName":"Weber", + "email": "iris.weber@bbw.ch" +} + +### +#Delete user with id 4 +DELETE http://localhost:8080/api/users/4 +Accept: application/json + +### +# Post: get user by email +POST http://localhost:8080/api/users/byemail +Content-Type: application/json + +{ + "email": "paula.kuster@bbw.ch" +} \ No newline at end of file diff --git a/183_12_1_tresorbackend_rupe-master/mvnw b/183_12_1_tresorbackend_rupe-master/mvnw new file mode 100644 index 0000000..66df285 --- /dev/null +++ b/183_12_1_tresorbackend_rupe-master/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/183_12_1_tresorbackend_rupe-master/mvnw.cmd b/183_12_1_tresorbackend_rupe-master/mvnw.cmd new file mode 100644 index 0000000..95ba6f5 --- /dev/null +++ b/183_12_1_tresorbackend_rupe-master/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/183_12_1_tresorbackend_rupe-master/pom.xml b/183_12_1_tresorbackend_rupe-master/pom.xml new file mode 100644 index 0000000..b0dc20d --- /dev/null +++ b/183_12_1_tresorbackend_rupe-master/pom.xml @@ -0,0 +1,80 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.2.4 + + + ch.bbw.pr + tresorbackend + 0.0.1-SNAPSHOT + tresorbackend + tresorbackend + + 17 + 17 + 17 + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-web + + + + org.mariadb.jdbc + mariadb-java-client + runtime + + + com.mysql + mysql-connector-j + runtime + + + org.projectlombok + lombok + true + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.boot + spring-boot-starter-validation + + + com.google.code.gson + gson + + + org.springframework.security + spring-security-crypto + + + + com.github.ulisesbocchio + jasypt-spring-boot-starter + 3.0.5 + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/TresorbackendApplication.java b/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/TresorbackendApplication.java new file mode 100644 index 0000000..6ae8ad7 --- /dev/null +++ b/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/TresorbackendApplication.java @@ -0,0 +1,13 @@ +package ch.bbw.pr.tresorbackend; + +import ch.bbw.pr.tresorbackend.model.ConfigProperties; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.web.bind.annotation.CrossOrigin; + +@SpringBootApplication +public class TresorbackendApplication { + public static void main(String[] args) { + SpringApplication.run(TresorbackendApplication.class, args); + } +} diff --git a/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/controller/SecretController.java b/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/controller/SecretController.java new file mode 100644 index 0000000..124b556 --- /dev/null +++ b/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/controller/SecretController.java @@ -0,0 +1,220 @@ +package ch.bbw.pr.tresorbackend.controller; + +import ch.bbw.pr.tresorbackend.model.Secret; +import ch.bbw.pr.tresorbackend.model.NewSecret; +import ch.bbw.pr.tresorbackend.model.EncryptCredentials; +import ch.bbw.pr.tresorbackend.model.User; +import ch.bbw.pr.tresorbackend.service.SecretService; +import ch.bbw.pr.tresorbackend.service.UserService; +import ch.bbw.pr.tresorbackend.util.EncryptUtil; +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import jakarta.validation.Valid; +import lombok.AllArgsConstructor; +import org.jasypt.exceptions.EncryptionOperationNotPossibleException; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * SecretController + * @author Peter Rutschmann + */ +@RestController +@AllArgsConstructor +@RequestMapping("api/secrets") +public class SecretController { + + private SecretService secretService; + private UserService userService; + + // create secret REST API + @CrossOrigin(origins = "${CROSS_ORIGIN}") + @PostMapping + public ResponseEntity createSecret2(@Valid @RequestBody NewSecret newSecret, BindingResult bindingResult) { + //input validation + if (bindingResult.hasErrors()) { + List errors = bindingResult.getFieldErrors().stream() + .map(fieldError -> fieldError.getField() + ": " + fieldError.getDefaultMessage()) + .collect(Collectors.toList()); + System.out.println("SecretController.createSecret " + errors); + + JsonArray arr = new JsonArray(); + errors.forEach(arr::add); + JsonObject obj = new JsonObject(); + obj.add("message", arr); + String json = new Gson().toJson(obj); + + System.out.println("SecretController.createSecret, validation fails: " + json); + return ResponseEntity.badRequest().body(json); + } + System.out.println("SecretController.createSecret, input validation passed"); + + User user = userService.findByEmail(newSecret.getEmail()); + + //transfer secret and encrypt content + Secret secret = new Secret( + null, + user.getId(), + new EncryptUtil(newSecret.getEncryptPassword()).encrypt(newSecret.getContent().toString()) + ); + //save secret in db + secretService.createSecret(secret); + System.out.println("SecretController.createSecret, secret saved in db"); + JsonObject obj = new JsonObject(); + obj.addProperty("answer", "Secret saved"); + String json = new Gson().toJson(obj); + System.out.println("SecretController.createSecret " + json); + return ResponseEntity.accepted().body(json); + } + + // Build Get Secrets by userId REST API + @CrossOrigin(origins = "${CROSS_ORIGIN}") + @PostMapping("/byuserid") + public ResponseEntity> getSecretsByUserId(@RequestBody EncryptCredentials credentials) { + System.out.println("SecretController.getSecretsByUserId " + credentials); + + List secrets = secretService.getSecretsByUserId(credentials.getUserId()); + if (secrets.isEmpty()) { + System.out.println("SecretController.getSecretsByUserId secret isEmpty"); + return ResponseEntity.notFound().build(); + } + //Decrypt content + for(Secret secret: secrets) { + try { + secret.setContent(new EncryptUtil(credentials.getEncryptPassword()).decrypt(secret.getContent())); + } catch (EncryptionOperationNotPossibleException e) { + System.out.println("SecretController.getSecretsByUserId " + e + " " + secret); + secret.setContent("not encryptable. Wrong password?"); + } + } + + System.out.println("SecretController.getSecretsByUserId " + secrets); + return ResponseEntity.ok(secrets); + } + + // Build Get Secrets by email REST API + @CrossOrigin(origins = "${CROSS_ORIGIN}") + @PostMapping("/byemail") + public ResponseEntity> getSecretsByEmail(@RequestBody EncryptCredentials credentials) { + System.out.println("SecretController.getSecretsByEmail " + credentials); + + User user = userService.findByEmail(credentials.getEmail()); + + List secrets = secretService.getSecretsByUserId(user.getId()); + if (secrets.isEmpty()) { + System.out.println("SecretController.getSecretsByEmail secret isEmpty"); + return ResponseEntity.notFound().build(); + } + //Decrypt content + for(Secret secret: secrets) { + try { + secret.setContent(new EncryptUtil(credentials.getEncryptPassword()).decrypt(secret.getContent())); + } catch (EncryptionOperationNotPossibleException e) { + System.out.println("SecretController.getSecretsByEmail " + e + " " + secret); + secret.setContent("not encryptable. Wrong password?"); + } + } + + System.out.println("SecretController.getSecretsByEmail " + secrets); + return ResponseEntity.ok(secrets); + } + + // Build Get All Secrets REST API + // http://localhost:8080/api/secrets + @CrossOrigin(origins = "${CROSS_ORIGIN}") + @GetMapping + public ResponseEntity> getAllSecrets() { + List secrets = secretService.getAllSecrets(); + return new ResponseEntity<>(secrets, HttpStatus.OK); + } + + // Build Update Secrete REST API + // http://localhost:8080/api/secrets/1 + @CrossOrigin(origins = "${CROSS_ORIGIN}") + @PutMapping("{id}") + public ResponseEntity updateSecret( + @PathVariable("id") Long secretId, + @Valid @RequestBody NewSecret newSecret, + BindingResult bindingResult) { + //input validation + if (bindingResult.hasErrors()) { + List errors = bindingResult.getFieldErrors().stream() + .map(fieldError -> fieldError.getField() + ": " + fieldError.getDefaultMessage()) + .collect(Collectors.toList()); + System.out.println("SecretController.createSecret " + errors); + + JsonArray arr = new JsonArray(); + errors.forEach(arr::add); + JsonObject obj = new JsonObject(); + obj.add("message", arr); + String json = new Gson().toJson(obj); + + System.out.println("SecretController.updateSecret, validation fails: " + json); + return ResponseEntity.badRequest().body(json); + } + + //get Secret with id + Secret dbSecrete = secretService.getSecretById(secretId); + if(dbSecrete == null){ + System.out.println("SecretController.updateSecret, secret not found in db"); + JsonObject obj = new JsonObject(); + obj.addProperty("answer", "Secret not found in db"); + String json = new Gson().toJson(obj); + System.out.println("SecretController.updateSecret failed:" + json); + return ResponseEntity.badRequest().body(json); + } + User user = userService.findByEmail(newSecret.getEmail()); + + //check if Secret in db has not same userid + if(dbSecrete.getUserId() != user.getId()){ + System.out.println("SecretController.updateSecret, not same user id"); + JsonObject obj = new JsonObject(); + obj.addProperty("answer", "Secret has not same user id"); + String json = new Gson().toJson(obj); + System.out.println("SecretController.updateSecret failed:" + json); + return ResponseEntity.badRequest().body(json); + } + //check if Secret can be decrypted with password + try { + new EncryptUtil(newSecret.getEncryptPassword()).decrypt(dbSecrete.getContent()); + } catch (EncryptionOperationNotPossibleException e) { + System.out.println("SecretController.updateSecret, invalid password"); + JsonObject obj = new JsonObject(); + obj.addProperty("answer", "Password not correct."); + String json = new Gson().toJson(obj); + System.out.println("SecretController.updateSecret failed:" + json); + return ResponseEntity.badRequest().body(json); + } + //modify Secret in db. + Secret secret = new Secret( + secretId, + user.getId(), + new EncryptUtil(newSecret.getEncryptPassword()).encrypt(newSecret.getContent().toString()) + ); + Secret updatedSecret = secretService.updateSecret(secret); + //save secret in db + secretService.createSecret(secret); + System.out.println("SecretController.updateSecret, secret updated in db"); + JsonObject obj = new JsonObject(); + obj.addProperty("answer", "Secret updated"); + String json = new Gson().toJson(obj); + System.out.println("SecretController.updateSecret " + json); + return ResponseEntity.accepted().body(json); + } + + // Build Delete Secret REST API + @CrossOrigin(origins = "${CROSS_ORIGIN}") + @DeleteMapping("{id}") + public ResponseEntity deleteSecret(@PathVariable("id") Long secretId) { + //todo: Some kind of brute force delete, perhaps test first userid and encryptpassword + secretService.deleteSecret(secretId); + System.out.println("SecretController.deleteSecret succesfully: " + secretId); + return new ResponseEntity<>("Secret successfully deleted!", HttpStatus.OK); + } +} diff --git a/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/controller/UserController.java b/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/controller/UserController.java new file mode 100644 index 0000000..758102b --- /dev/null +++ b/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/controller/UserController.java @@ -0,0 +1,181 @@ +package ch.bbw.pr.tresorbackend.controller; + +import ch.bbw.pr.tresorbackend.model.ConfigProperties; +import ch.bbw.pr.tresorbackend.model.EmailAdress; +import ch.bbw.pr.tresorbackend.model.RegisterUser; +import ch.bbw.pr.tresorbackend.model.User; +import ch.bbw.pr.tresorbackend.service.PasswordEncryptionService; +import ch.bbw.pr.tresorbackend.service.UserService; + +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import jakarta.validation.Valid; +import lombok.AllArgsConstructor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * UserController + * @author Peter Rutschmann + */ +@RestController +@AllArgsConstructor +@RequestMapping("api/users") +public class UserController { + + private UserService userService; + private PasswordEncryptionService passwordService; + private final ConfigProperties configProperties; + private static final Logger logger = LoggerFactory.getLogger(UserController.class); + + @Autowired + public UserController(ConfigProperties configProperties, UserService userService, + PasswordEncryptionService passwordService) { + this.configProperties = configProperties; + System.out.println("UserController.UserController: cross origin: " + configProperties.getOrigin()); + // Logging in the constructor + logger.info("UserController initialized: " + configProperties.getOrigin()); + logger.debug("UserController.UserController: Cross Origin Config: {}", configProperties.getOrigin()); + this.userService = userService; + this.passwordService = passwordService; + } + + // build create User REST API + @CrossOrigin(origins = "${CROSS_ORIGIN}") + @PostMapping + public ResponseEntity createUser(@Valid @RequestBody RegisterUser registerUser, BindingResult bindingResult) { + //captcha + //todo ergänzen + + System.out.println("UserController.createUser: captcha passed."); + + //input validation + if (bindingResult.hasErrors()) { + List errors = bindingResult.getFieldErrors().stream() + .map(fieldError -> fieldError.getField() + ": " + fieldError.getDefaultMessage()) + .collect(Collectors.toList()); + System.out.println("UserController.createUser " + errors); + + JsonArray arr = new JsonArray(); + errors.forEach(arr::add); + JsonObject obj = new JsonObject(); + obj.add("message", arr); + String json = new Gson().toJson(obj); + + System.out.println("UserController.createUser, validation fails: " + json); + return ResponseEntity.badRequest().body(json); + } + System.out.println("UserController.createUser: input validation passed"); + + //password validation + //todo ergänzen + System.out.println("UserController.createUser, password validation passed"); + + //transform registerUser to user + User user = new User( + null, + registerUser.getFirstName(), + registerUser.getLastName(), + registerUser.getEmail(), + passwordService.hashPassword(registerUser.getPassword()) + ); + + User savedUser = userService.createUser(user); + System.out.println("UserController.createUser, user saved in db"); + JsonObject obj = new JsonObject(); + obj.addProperty("answer", "User Saved"); + String json = new Gson().toJson(obj); + System.out.println("UserController.createUser " + json); + return ResponseEntity.accepted().body(json); + } + + // build get user by id REST API + // http://localhost:8080/api/users/1 + @CrossOrigin(origins = "${CROSS_ORIGIN}") + @GetMapping("{id}") + public ResponseEntity getUserById(@PathVariable("id") Long userId) { + User user = userService.getUserById(userId); + return new ResponseEntity<>(user, HttpStatus.OK); + } + + // Build Get All Users REST API + // http://localhost:8080/api/users + @CrossOrigin(origins = "${CROSS_ORIGIN}") + @GetMapping + public ResponseEntity> getAllUsers() { + List users = userService.getAllUsers(); + return new ResponseEntity<>(users, HttpStatus.OK); + } + + // Build Update User REST API + // http://localhost:8080/api/users/1 + @CrossOrigin(origins = "${CROSS_ORIGIN}") + @PutMapping("{id}") + public ResponseEntity updateUser(@PathVariable("id") Long userId, + @RequestBody User user) { + user.setId(userId); + User updatedUser = userService.updateUser(user); + return new ResponseEntity<>(updatedUser, HttpStatus.OK); + } + + // Build Delete User REST API + @CrossOrigin(origins = "${CROSS_ORIGIN}") + @DeleteMapping("{id}") + public ResponseEntity deleteUser(@PathVariable("id") Long userId) { + userService.deleteUser(userId); + return new ResponseEntity<>("User successfully deleted!", HttpStatus.OK); + } + + + // get user id by email + @CrossOrigin(origins = "${CROSS_ORIGIN}") + @PostMapping("/byemail") + public ResponseEntity getUserIdByEmail(@RequestBody EmailAdress email, BindingResult bindingResult) { + System.out.println("UserController.getUserIdByEmail: " + email); + //input validation + if (bindingResult.hasErrors()) { + List errors = bindingResult.getFieldErrors().stream() + .map(fieldError -> fieldError.getField() + ": " + fieldError.getDefaultMessage()) + .collect(Collectors.toList()); + System.out.println("UserController.createUser " + errors); + + JsonArray arr = new JsonArray(); + errors.forEach(arr::add); + JsonObject obj = new JsonObject(); + obj.add("message", arr); + String json = new Gson().toJson(obj); + + System.out.println("UserController.createUser, validation fails: " + json); + return ResponseEntity.badRequest().body(json); + } + + System.out.println("UserController.getUserIdByEmail: input validation passed"); + + User user = userService.findByEmail(email.getEmail()); + if (user == null) { + System.out.println("UserController.getUserIdByEmail, no user found with email: " + email); + JsonObject obj = new JsonObject(); + obj.addProperty("message", "No user found with this email"); + String json = new Gson().toJson(obj); + + System.out.println("UserController.getUserIdByEmail, fails: " + json); + return ResponseEntity.badRequest().body(json); + } + System.out.println("UserController.getUserIdByEmail, user find by email"); + JsonObject obj = new JsonObject(); + obj.addProperty("answer", user.getId()); + String json = new Gson().toJson(obj); + System.out.println("UserController.getUserIdByEmail " + json); + return ResponseEntity.accepted().body(json); + } + +} diff --git a/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/model/ConfigProperties.java b/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/model/ConfigProperties.java new file mode 100644 index 0000000..df7337c --- /dev/null +++ b/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/model/ConfigProperties.java @@ -0,0 +1,19 @@ +package ch.bbw.pr.tresorbackend.model; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +/** + * ConfigProperties + * @author Peter Rutschmann + */ +@Component +public class ConfigProperties { + + @Value("${CROSS_ORIGIN}") + private String crossOrigin; + + public String getOrigin() { + return crossOrigin; + } +} diff --git a/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/model/EmailAdress.java b/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/model/EmailAdress.java new file mode 100644 index 0000000..55ddae7 --- /dev/null +++ b/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/model/EmailAdress.java @@ -0,0 +1,18 @@ +package ch.bbw.pr.tresorbackend.model; + +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.Size; +import lombok.*; + +/** + * EmailAdress + * @author Peter Rutschmann + */ +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class EmailAdress { + @NotEmpty (message="E-Mail is required.") + private String email; +} \ No newline at end of file diff --git a/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/model/EncryptCredentials.java b/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/model/EncryptCredentials.java new file mode 100644 index 0000000..00edd5f --- /dev/null +++ b/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/model/EncryptCredentials.java @@ -0,0 +1,20 @@ +package ch.bbw.pr.tresorbackend.model; + +import jakarta.validation.constraints.NotEmpty; +import lombok.*; + +/** + * EncryptCredentials + * @author Peter Rutschmann + */ +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@ToString +public class EncryptCredentials { + private long userId; + private String email; + @NotEmpty(message="encryption password id is required.") + private String encryptPassword; +} diff --git a/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/model/NewSecret.java b/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/model/NewSecret.java new file mode 100644 index 0000000..c1f0973 --- /dev/null +++ b/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/model/NewSecret.java @@ -0,0 +1,30 @@ +package ch.bbw.pr.tresorbackend.model; + +import com.fasterxml.jackson.annotation.JsonRawValue; +import com.fasterxml.jackson.databind.JsonNode; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +/** + * NewSecret + * @author Peter Rutschmann + */ +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class NewSecret { + @NotEmpty (message="email is required.") + private String email; + + @NotNull (message="secret is required.") + private JsonNode content; + + @NotEmpty (message="encryption password id is required.") + private String encryptPassword; +} \ No newline at end of file diff --git a/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/model/RegisterUser.java b/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/model/RegisterUser.java new file mode 100644 index 0000000..b452de4 --- /dev/null +++ b/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/model/RegisterUser.java @@ -0,0 +1,33 @@ +package ch.bbw.pr.tresorbackend.model; + +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.Pattern; +import jakarta.validation.constraints.Size; +import lombok.*; + +/** + * RegisterUser + * @author Peter Rutschmann + */ +@Value +public class RegisterUser { + + @NotEmpty(message="Firstname is required.") + @Size(min=2, max=25, message="Firstname size has to be 2 up to 25 characters.") + private String firstName; + + @NotEmpty (message="Lastname is required.") + @Size(min=2, max=25, message="Lastname size has to be 2 up to 25 characters.") + private String lastName; + + @NotEmpty (message="E-Mail is required.") + private String email; + + @NotEmpty (message="Password is required.") + private String password; + + @NotEmpty (message="Password-confirmation is required.") + private String passwordConfirmation; + + private String recaptchaToken; +} \ No newline at end of file diff --git a/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/model/Secret.java b/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/model/Secret.java new file mode 100644 index 0000000..cf3703b --- /dev/null +++ b/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/model/Secret.java @@ -0,0 +1,28 @@ +package ch.bbw.pr.tresorbackend.model; + +import com.fasterxml.jackson.annotation.JsonRawValue; +import jakarta.persistence.*; +import lombok.*; + +/** + * Secret + * @author Peter Rutschmann + */ +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@ToString +@Entity +@Table(name = "secret") +public class Secret { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false, name="user_id") + private Long userId; + + @Column(nullable = false, name="content") + private String content; +} \ No newline at end of file diff --git a/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/model/User.java b/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/model/User.java new file mode 100644 index 0000000..01d4f6c --- /dev/null +++ b/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/model/User.java @@ -0,0 +1,35 @@ +package ch.bbw.pr.tresorbackend.model; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +/** + * User + * @author Peter Rutschmann + */ +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Table(name = "user") +public class User { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false, name="first_name") + private String firstName; + + @Column(nullable = false, name="last_name") + private String lastName; + + @Column(nullable = false, unique = true) + private String email; + + @Column(nullable = false) + private String password; +} \ No newline at end of file diff --git a/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/repository/SecretRepository.java b/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/repository/SecretRepository.java new file mode 100644 index 0000000..8419139 --- /dev/null +++ b/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/repository/SecretRepository.java @@ -0,0 +1,14 @@ +package ch.bbw.pr.tresorbackend.repository; + +import ch.bbw.pr.tresorbackend.model.Secret; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +/** + * SecretRepository + * @author Peter Rutschmann + */ +public interface SecretRepository extends JpaRepository { + List findByUserId(Long userId); +} diff --git a/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/repository/UserRepository.java b/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/repository/UserRepository.java new file mode 100644 index 0000000..a443ba0 --- /dev/null +++ b/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/repository/UserRepository.java @@ -0,0 +1,14 @@ +package ch.bbw.pr.tresorbackend.repository; + +import ch.bbw.pr.tresorbackend.model.User; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +/** + * UserRepository + * @author Peter Rutschmann + */ +public interface UserRepository extends JpaRepository { + Optional findByEmail(String email); +} diff --git a/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/service/PasswordEncryptionService.java b/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/service/PasswordEncryptionService.java new file mode 100644 index 0000000..95586db --- /dev/null +++ b/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/service/PasswordEncryptionService.java @@ -0,0 +1,21 @@ +package ch.bbw.pr.tresorbackend.service; + +import org.springframework.stereotype.Service; + +/** + * PasswordEncryptionService + * @author Peter Rutschmann + */ +@Service +public class PasswordEncryptionService { + //todo ergänzen! + + public PasswordEncryptionService() { + //todo anpassen! + } + + public String hashPassword(String password) { + //todo anpassen! + return password; + } +} diff --git a/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/service/SecretService.java b/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/service/SecretService.java new file mode 100644 index 0000000..46b3024 --- /dev/null +++ b/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/service/SecretService.java @@ -0,0 +1,22 @@ +package ch.bbw.pr.tresorbackend.service; + +import ch.bbw.pr.tresorbackend.model.Secret; +import java.util.List; + +/** + * SecretService + * @author Peter Rutschmann + */ +public interface SecretService { + Secret createSecret(Secret secret); + + Secret getSecretById(Long secretId); + + List getAllSecrets(); + + Secret updateSecret(Secret secret); + + void deleteSecret(Long secretId); + + List getSecretsByUserId(Long userId); +} diff --git a/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/service/UserService.java b/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/service/UserService.java new file mode 100644 index 0000000..5979c5f --- /dev/null +++ b/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/service/UserService.java @@ -0,0 +1,22 @@ +package ch.bbw.pr.tresorbackend.service; + +import ch.bbw.pr.tresorbackend.model.User; +import java.util.List; + +/** + * UserService + * @author Peter Rutschmann + */ +public interface UserService { + User createUser(User user); + + User getUserById(Long userId); + + User findByEmail(String email); + + List getAllUsers(); + + User updateUser(User user); + + void deleteUser(Long userId); +} diff --git a/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/service/impl/SecretServiceImpl.java b/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/service/impl/SecretServiceImpl.java new file mode 100644 index 0000000..b84b4aa --- /dev/null +++ b/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/service/impl/SecretServiceImpl.java @@ -0,0 +1,57 @@ +package ch.bbw.pr.tresorbackend.service.impl; + +import ch.bbw.pr.tresorbackend.model.Secret; +import ch.bbw.pr.tresorbackend.repository.SecretRepository; +import ch.bbw.pr.tresorbackend.service.SecretService; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Optional; + +/** + * SecretServiceImpl + * @author Peter Rutschmann + */ +@Service +@AllArgsConstructor +public class SecretServiceImpl implements SecretService { + + private SecretRepository secretRepository; + + @Override + public Secret createSecret(Secret card) { + return secretRepository.save(card); + } + + @Override + public Secret getSecretById(Long secretId) { + Optional optionalSecret = secretRepository.findById(secretId); + return optionalSecret.get(); + } + + @Override + public List getAllSecrets() { + return (List) secretRepository.findAll(); + } + + @Override + public Secret updateSecret(Secret secret) { + Secret existingSecret = secretRepository.findById(secret.getId()).get(); + existingSecret.setUserId(secret.getUserId()); + existingSecret.setContent(secret.getContent()); + Secret updatedSecret = secretRepository.save(existingSecret); + return updatedSecret; + } + + @Override + public void deleteSecret(Long secretId) { + secretRepository.deleteById(secretId); + } + + @Override + public List getSecretsByUserId(Long userId) { + return secretRepository.findByUserId(userId); + } + +} diff --git a/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/service/impl/UserServiceImpl.java b/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/service/impl/UserServiceImpl.java new file mode 100644 index 0000000..efe85ef --- /dev/null +++ b/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/service/impl/UserServiceImpl.java @@ -0,0 +1,58 @@ +package ch.bbw.pr.tresorbackend.service.impl; + +import ch.bbw.pr.tresorbackend.model.User; +import ch.bbw.pr.tresorbackend.repository.UserRepository; +import ch.bbw.pr.tresorbackend.service.UserService; + +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Service; +import java.util.List; +import java.util.Optional; + +/** + * UserServiceImpl + * @author Peter Rutschmann + */ +@Service +@AllArgsConstructor +public class UserServiceImpl implements UserService { + + private UserRepository userRepository; + + @Override + public User createUser(User user) { + return userRepository.save(user); + } + + @Override + public User getUserById(Long userId) { + Optional optionalUser = userRepository.findById(userId); + return optionalUser.get(); + } + + @Override + public User findByEmail(String email) { + Optional optionalUser = userRepository.findByEmail(email); + return optionalUser.get(); + } + + @Override + public List getAllUsers() { + return (List) userRepository.findAll(); + } + + @Override + public User updateUser(User user) { + User existingUser = userRepository.findById(user.getId()).get(); + existingUser.setFirstName(user.getFirstName()); + existingUser.setLastName(user.getLastName()); + existingUser.setEmail(user.getEmail()); + User updatedUser = userRepository.save(existingUser); + return updatedUser; + } + + @Override + public void deleteUser(Long userId) { + userRepository.deleteById(userId); + } +} diff --git a/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/util/EncryptUtil.java b/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/util/EncryptUtil.java new file mode 100644 index 0000000..dc37ad9 --- /dev/null +++ b/183_12_1_tresorbackend_rupe-master/src/main/java/ch/bbw/pr/tresorbackend/util/EncryptUtil.java @@ -0,0 +1,28 @@ +package ch.bbw.pr.tresorbackend.util; + +import org.jasypt.util.text.AES256TextEncryptor; + +/** + * EncryptUtil + * Used to encrypt content. + * Not implemented yet. + * @author Peter Rutschmann + */ +public class EncryptUtil { + + //todo ergänzen! + + public EncryptUtil(String secretKey) { + //todo ergänzen! + } + + public String encrypt(String data) { + //todo anpassen! + return data; + } + + public String decrypt(String data) { + //todo anpassen! + return data; + } +} diff --git a/183_12_1_tresorbackend_rupe-master/src/main/resources/application.properties b/183_12_1_tresorbackend_rupe-master/src/main/resources/application.properties new file mode 100644 index 0000000..8d10bd5 --- /dev/null +++ b/183_12_1_tresorbackend_rupe-master/src/main/resources/application.properties @@ -0,0 +1,11 @@ +spring.application.name=tresorbackend + +#variables can be overwritten by environment variables +spring.datasource.url=jdbc:mysql://localhost:3306/tresordb +spring.datasource.username=root +spring.datasource.password=1234 + +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect +spring.jpa.hibernate.ddl-auto=update + +CROSS_ORIGIN=http://localhost:3000 \ No newline at end of file diff --git a/183_12_1_tresorbackend_rupe-master/src/test/java/ch/bbw/pr/tresorbackend/TresorbackendApplicationTests.java b/183_12_1_tresorbackend_rupe-master/src/test/java/ch/bbw/pr/tresorbackend/TresorbackendApplicationTests.java new file mode 100644 index 0000000..9172b1d --- /dev/null +++ b/183_12_1_tresorbackend_rupe-master/src/test/java/ch/bbw/pr/tresorbackend/TresorbackendApplicationTests.java @@ -0,0 +1,13 @@ +package ch.bbw.pr.tresorbackend; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class TresorbackendApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/183_12_1_tresorbackend_rupe-master/tresordb.sql b/183_12_1_tresorbackend_rupe-master/tresordb.sql new file mode 100644 index 0000000..7353447 --- /dev/null +++ b/183_12_1_tresorbackend_rupe-master/tresordb.sql @@ -0,0 +1,51 @@ +-- +-- Datenbank: `tresordb` +-- + +DROP DATABASE IF EXISTS tresordb; +CREATE DATABASE tresordb; +USE tresordb; + +-- -------------------------------------------------------- + +-- +-- table user +-- + +CREATE TABLE user ( + id int NOT NULL AUTO_INCREMENT, + first_name varchar(30) NOT NULL, + last_name varchar(30) NOT NULL, + email varchar(30) NOT NULL, + password longtext NOT NULL, + PRIMARY KEY (id) +); + +-- +-- table user content +-- + +INSERT INTO `user` (`id`, `first_name`, `last_name`, `email`, `password`) VALUES +(1, 'Hans', 'Muster', 'hans.muster@bbw.ch', 'abcd'), +(2, 'Paula', 'Kuster', 'paula.kuster@bbw.ch', 'efgh'), +(3, 'Andrea', 'Oester', 'andrea.oester@bbw.ch', 'ijkl'); + +-- +-- table secret +-- + +CREATE TABLE secret ( + id int NOT NULL AUTO_INCREMENT, + user_id int NOT NULL, + content json NOT NULL, + PRIMARY KEY (id) +); + +-- +-- table secret content +-- + +INSERT INTO `secret` (`id`, `user_id`, `content`) VALUES + (1, 1, '{"kindid":1,"kind":"credential","userName":"muster","password":"1234","url":"www.bbw.ch"}'), + (2, 1, '{"kindid":2,"kind":"creditcard","cardtype":"Visa","cardnumber":"4242 4242 4242 4241","expiration":"12/27","cvv":"789"}'), + (3, 1, '{"kindid":3,"kind":"note","title":"Eragon","content":"Und Eragon ging auf den Drachen zu."}'); diff --git a/183_12_1_tresorbackend_rupe-master/wait-for-db.sh b/183_12_1_tresorbackend_rupe-master/wait-for-db.sh new file mode 100644 index 0000000..c7ff735 --- /dev/null +++ b/183_12_1_tresorbackend_rupe-master/wait-for-db.sh @@ -0,0 +1,16 @@ +#!/bin/bash +set -e + +host="$1" +shift +cmd="$@" + +echo "Waiting for $host to be ready..." + +until mysqladmin ping -h "$host" --silent; do + echo "MariaDB is unavailable - waiting..." + sleep 2 +done + +echo "MariaDB is up - executing command" +exec $cmd \ No newline at end of file diff --git a/183_12_2_tresorfrontend_rupe-master/.env b/183_12_2_tresorfrontend_rupe-master/.env new file mode 100644 index 0000000..616f1c3 --- /dev/null +++ b/183_12_2_tresorfrontend_rupe-master/.env @@ -0,0 +1,7 @@ +#connection to backend api +# example http://localhost:8080/api +# port is optional +REACT_APP_API_PROTOCOL=http +REACT_APP_API_HOST=localhost +REACT_APP_API_PORT=8080 +REACT_APP_API_PATH=/api diff --git a/183_12_2_tresorfrontend_rupe-master/.gitignore b/183_12_2_tresorfrontend_rupe-master/.gitignore new file mode 100644 index 0000000..86b7d68 --- /dev/null +++ b/183_12_2_tresorfrontend_rupe-master/.gitignore @@ -0,0 +1,41 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# Node.js Modules +node_modules/ +package-lock.json +yarn.lock + +# Build Artifacts +build/ +dist/ + +# IntelliJ IDEA Files +.idea/ +*.iml +*.ipr +*.iws + +# Logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +*.log + +# testing +coverage/ + +# misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Editor Settings +.vscode/ +*.swp diff --git a/183_12_2_tresorfrontend_rupe-master/Dockerfile b/183_12_2_tresorfrontend_rupe-master/Dockerfile new file mode 100644 index 0000000..0bf1de5 --- /dev/null +++ b/183_12_2_tresorfrontend_rupe-master/Dockerfile @@ -0,0 +1,36 @@ +# Step one + +# Build Stage: Node.js wird verwendet, um die App zu bauen +FROM node:14 AS build + +# Set working directory +WORKDIR /App + +# copy package.json and package-lock.json +COPY package*.json /App/ + +# install Node.js-dependencies +RUN npm install + +# copy application files +COPY . /App/ + +# build the app +RUN npm run build + +# Step two + +# Serve Stage: use Nginx +FROM nginx:latest + +# Copy the build files from the build stage to Nginx's html directory +COPY --from=build /App/build /usr/share/nginx/html + +# copy nginx config to get a perfomanter app +COPY nginx.conf /etc/nginx/conf.d/default.conf + +# Expose the default Nginx port +EXPOSE 80 + +# Start Nginx +CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/183_12_2_tresorfrontend_rupe-master/README.md b/183_12_2_tresorfrontend_rupe-master/README.md new file mode 100644 index 0000000..826bd0f --- /dev/null +++ b/183_12_2_tresorfrontend_rupe-master/README.md @@ -0,0 +1,45 @@ +# The secret tresor application frontend + +## Technik + +- basiert auf React + +## Umgebungsvariablen + +- In der **Datei .env** sind die von der Applikation **verwendeten Umgebungsvariablen** deklariert. +- Falls die Umgebungsvariablen _aussen_ nicht gesetzt sind, wird ein Default-Wert verwendet. + +## Hinweise zur Anwendung der Applikation + +- Die Applikation ist für den Unterricht gedacht. +- Die vorliegende Version hat keine Security implementiert. +- So spielt das Passwort (noch) keine Rolle. + +- Wenn die Applikation gestartet ist, kann man mit
+ _Admin->All user_
+ Vom Backend das Verzeichnis aller User abrufen. + +- Mit
+ _User->Register_
+ Kein ein neuer User via Backend gespeichert werden +- Danach ist ein Login des Users notwendig.
+ _User->Login_ mit Email und Passwort
+ Diese Login-Daten sind für die _Secrets_ Funktionen notwendig. +- Es können drei unterschiedliche Secrets gespeicher werden. +- Und es können die eigenen Secrets abgerufen werden. + +## Build image + +see Dockerfile + +```Bash +docker build -t tresorfrontendimg . +``` + +## Start container local + +```Bash +docker run -p 80:80 --name tresorfrontend tresorfrontendimg + +(c) 2024 P. Rutschmann + diff --git a/183_12_2_tresorfrontend_rupe-master/nginx.conf b/183_12_2_tresorfrontend_rupe-master/nginx.conf new file mode 100644 index 0000000..b152632 --- /dev/null +++ b/183_12_2_tresorfrontend_rupe-master/nginx.conf @@ -0,0 +1,10 @@ +server { + listen 80; + server_name localhost; + + location / { + root /usr/share/nginx/html; + index index.html; + try_files $uri /index.html; + } +} \ No newline at end of file diff --git a/183_12_2_tresorfrontend_rupe-master/package.json b/183_12_2_tresorfrontend_rupe-master/package.json new file mode 100644 index 0000000..fb4acae --- /dev/null +++ b/183_12_2_tresorfrontend_rupe-master/package.json @@ -0,0 +1,42 @@ +{ + "name": "01_tresorfrontend", + "version": "0.1.0", + "private": true, + "dependencies": { + "@testing-library/jest-dom": "^5.17.0", + "@testing-library/react": "^13.4.0", + "@testing-library/user-event": "^13.5.0", + "axios": "^1.6.8", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-google-recaptcha": "^3.1.0", + "react-router-dom": "^6.22.3", + "react-scripts": "5.0.1", + "reactstrap": "^9.2.2", + "web-vitals": "^2.1.4" + }, + "scripts": { + "start": "react-scripts start", + "build": "react-scripts build", + "test": "react-scripts test", + "eject": "react-scripts eject" + }, + "eslintConfig": { + "extends": [ + "react-app", + "react-app/jest" + ] + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + } +} diff --git a/183_12_2_tresorfrontend_rupe-master/public/favicon.ico b/183_12_2_tresorfrontend_rupe-master/public/favicon.ico new file mode 100644 index 0000000..a11777c Binary files /dev/null and b/183_12_2_tresorfrontend_rupe-master/public/favicon.ico differ diff --git a/183_12_2_tresorfrontend_rupe-master/public/index.html b/183_12_2_tresorfrontend_rupe-master/public/index.html new file mode 100644 index 0000000..964dec7 --- /dev/null +++ b/183_12_2_tresorfrontend_rupe-master/public/index.html @@ -0,0 +1,43 @@ + + + + + + + + + + + + + React App + + + +
+ + + diff --git a/183_12_2_tresorfrontend_rupe-master/public/manifest.json b/183_12_2_tresorfrontend_rupe-master/public/manifest.json new file mode 100644 index 0000000..1f2f141 --- /dev/null +++ b/183_12_2_tresorfrontend_rupe-master/public/manifest.json @@ -0,0 +1,15 @@ +{ + "short_name": "React App", + "name": "Create React App Sample", + "icons": [ + { + "src": "favicon.ico", + "sizes": "64x64 32x32 24x24 16x16", + "type": "image/x-icon" + } + ], + "start_url": ".", + "display": "standalone", + "theme_color": "#000000", + "background_color": "#ffffff" +} diff --git a/183_12_2_tresorfrontend_rupe-master/public/robots.txt b/183_12_2_tresorfrontend_rupe-master/public/robots.txt new file mode 100644 index 0000000..e9e57dc --- /dev/null +++ b/183_12_2_tresorfrontend_rupe-master/public/robots.txt @@ -0,0 +1,3 @@ +# https://www.robotstxt.org/robotstxt.html +User-agent: * +Disallow: diff --git a/183_12_2_tresorfrontend_rupe-master/src/App.css b/183_12_2_tresorfrontend_rupe-master/src/App.css new file mode 100644 index 0000000..74b5e05 --- /dev/null +++ b/183_12_2_tresorfrontend_rupe-master/src/App.css @@ -0,0 +1,38 @@ +.App { + text-align: center; +} + +.App-logo { + height: 40vmin; + pointer-events: none; +} + +@media (prefers-reduced-motion: no-preference) { + .App-logo { + animation: App-logo-spin infinite 20s linear; + } +} + +.App-header { + background-color: #282c34; + min-height: 100vh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + font-size: calc(10px + 2vmin); + color: white; +} + +.App-link { + color: #61dafb; +} + +@keyframes App-logo-spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} diff --git a/183_12_2_tresorfrontend_rupe-master/src/App.js b/183_12_2_tresorfrontend_rupe-master/src/App.js new file mode 100644 index 0000000..1980877 --- /dev/null +++ b/183_12_2_tresorfrontend_rupe-master/src/App.js @@ -0,0 +1,44 @@ +import React, {useState} from 'react'; +import {BrowserRouter, Route, Routes} from "react-router-dom"; +import './App.css'; +import './css/mvp.css'; +import Home from './pages/Home'; +import Layout from "./pages/Layout"; +import NoPage from "./pages/NoPage"; +import Users from './pages/user/Users'; +import LoginUser from "./pages/user/LoginUser"; +import RegisterUser from "./pages/user/RegisterUser"; +import Secrets from "./pages/secret/Secrets"; +import NewCredential from "./pages/secret/NewCredential"; +import NewCreditCard from "./pages/secret/NewCreditCard"; +import NewNote from "./pages/secret/NewNote"; + +/** + * App + * @author Peter Rutschmann + */ +function App() { + const [loginValues, setLoginValues] = useState({ + email: "", + password: "", + }); + return ( + + + }> + }/>}/> + }/> + }/> + }/> + }/> + }/> + }/> + }/> + }/> + + + + ) +} + +export default App; \ No newline at end of file diff --git a/183_12_2_tresorfrontend_rupe-master/src/App.test.js b/183_12_2_tresorfrontend_rupe-master/src/App.test.js new file mode 100644 index 0000000..1f03afe --- /dev/null +++ b/183_12_2_tresorfrontend_rupe-master/src/App.test.js @@ -0,0 +1,8 @@ +import { render, screen } from '@testing-library/react'; +import App from './App'; + +test('renders learn react link', () => { + render(); + const linkElement = screen.getByText(/learn react/i); + expect(linkElement).toBeInTheDocument(); +}); diff --git a/183_12_2_tresorfrontend_rupe-master/src/comunication/FetchSecrets.js b/183_12_2_tresorfrontend_rupe-master/src/comunication/FetchSecrets.js new file mode 100644 index 0000000..7d2bd00 --- /dev/null +++ b/183_12_2_tresorfrontend_rupe-master/src/comunication/FetchSecrets.js @@ -0,0 +1,75 @@ +/** + * Fetch methodes for secret api calls + * @author Peter Rutschmann + */ + +//Post secret to server +export const postSecret = async ({loginValues, content}) => { + const protocol = process.env.REACT_APP_API_PROTOCOL; // "http" + const host = process.env.REACT_APP_API_HOST; // "localhost" + const port = process.env.REACT_APP_API_PORT; // "8080" + const path = process.env.REACT_APP_API_PATH; // "/api" + const portPart = port ? `:${port}` : ''; // port is optional + const API_URL = `${protocol}://${host}${portPart}${path}`; + console.log(loginValues) + + try { + const response = await fetch(`${API_URL}/secrets`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + email: loginValues.email, + encryptPassword: loginValues.password, + content: content + }) + }); + + if (!response.ok) { + const errorData = await response.json(); + throw new Error(errorData.message || 'Server response failed.'); + } + + const data = await response.json(); + console.log('Secret successfully posted:', data); + return data; + } catch (error) { + console.error('Error posting secret:', error.message); + throw new Error('Failed to save secret. ' || error.message); + } +}; + +//get all secrets for a user identified by its email +export const getSecretsforUser = async (loginValues) => { + const protocol = process.env.REACT_APP_API_PROTOCOL; // "http" + const host = process.env.REACT_APP_API_HOST; // "localhost" + const port = process.env.REACT_APP_API_PORT; // "8080" + const path = process.env.REACT_APP_API_PATH; // "/api" + const portPart = port ? `:${port}` : ''; // port is optional + const API_URL = `${protocol}://${host}${portPart}${path}`; + + try { + const response = await fetch(`${API_URL}/secrets/byemail`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + email: loginValues.email, + encryptPassword: loginValues.password + }) + }); + + if (!response.ok) { + const errorData = await response.json(); + throw new Error(errorData.message || 'Server response failed.'); + } + const data = await response.json(); + console.log('Secret successfully got:', data); + return data; + } catch (error) { + console.error('Failed to get secrets:', error.message); + throw new Error('Failed to get secrets. ' || error.message); + } +}; \ No newline at end of file diff --git a/183_12_2_tresorfrontend_rupe-master/src/comunication/FetchUser.js b/183_12_2_tresorfrontend_rupe-master/src/comunication/FetchUser.js new file mode 100644 index 0000000..25aef35 --- /dev/null +++ b/183_12_2_tresorfrontend_rupe-master/src/comunication/FetchUser.js @@ -0,0 +1,71 @@ +/** + * Fetch methodes for user api calls + * @author Peter Rutschmann + */ + + +export const getUsers = async () => { + const protocol = process.env.REACT_APP_API_PROTOCOL; // "http" + const host = process.env.REACT_APP_API_HOST; // "localhost" + const port = process.env.REACT_APP_API_PORT; // "8080" + const path = process.env.REACT_APP_API_PATH; // "/api" + const portPart = port ? `:${port}` : ''; // port is optional + const API_URL = `${protocol}://${host}${portPart}${path}`; + + try { + const response = await fetch(`${API_URL}/users`, { + method: 'Get', + headers: { + 'Accept': 'application/json' + } + }); + + if (!response.ok) { + const errorData = await response.json(); + throw new Error(errorData.message || 'Server response failed.'); + } + + const data = await response.json(); + console.log('User successfully got:', data); + return data; + } catch (error) { + console.error('Failed to get user:', error.message); + throw new Error('Failed to get user. ' || error.message); + } +} + +export const postUser = async (content) => { + const protocol = process.env.REACT_APP_API_PROTOCOL; // "http" + const host = process.env.REACT_APP_API_HOST; // "localhost" + const port = process.env.REACT_APP_API_PORT; // "8080" + const path = process.env.REACT_APP_API_PATH; // "/api" + const portPart = port ? `:${port}` : ''; // port is optional + const API_URL = `${protocol}://${host}${portPart}${path}`; + + try { + const response = await fetch(`${API_URL}/users`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + firstName: `${content.firstName}`, + lastName: `${content.lastName}`, + email: `${content.email}`, + password: `${content.password}`, + passwordConfirmation: `${content.passwordConfirmation}` + }) + }); + + if (!response.ok) { + const errorData = await response.json(); + throw new Error(errorData.message || 'Server response failed.'); + } + const data = await response.json(); + console.log('User successfully posted:', data); + return data; + } catch (error) { + console.error('Failed to post user:', error.message); + throw new Error('Failed to save user. ' || error.message); + } +}; \ No newline at end of file diff --git a/183_12_2_tresorfrontend_rupe-master/src/css/mvp.css b/183_12_2_tresorfrontend_rupe-master/src/css/mvp.css new file mode 100644 index 0000000..36085b8 --- /dev/null +++ b/183_12_2_tresorfrontend_rupe-master/src/css/mvp.css @@ -0,0 +1,470 @@ +/* MVP.css v1.7.4 - https://github.com/andybrewer/mvp */ + +:root { + --border-radius: 5px; + --box-shadow: 2px 2px 10px; + --color: #118bee; + --color-accent: #118bee15; + --color-bg: #fff; + --color-bg-secondary: #e9e9e9; + --color-secondary: #920de9; + --color-secondary-accent: #920de90b; + --color-shadow: #f4f4f4; + --color-text: #000; + --color-text-secondary: #999; + --font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; + --hover-brightness: 1.2; + --justify-important: center; + --justify-normal: left; + --line-height: 1.5; + --width-card: 285px; + --width-card-medium: 460px; + --width-card-wide: 800px; + --width-content: 1080px; +} + +/* +@media (prefers-color-scheme: dark) { + :root { + --color: #0097fc; + --color-accent: #0097fc4f; + --color-bg: #333; + --color-bg-secondary: #555; + --color-secondary: #e20de9; + --color-secondary-accent: #e20de94f; + --color-shadow: #bbbbbb20; + --color-text: #f7f7f7; + --color-text-secondary: #aaa; + } +} +*/ + +/* Layout */ +article aside { + background: var(--color-secondary-accent); + border-left: 4px solid var(--color-secondary); + padding: 0.01rem 0.8rem; +} + +body { + background: var(--color-bg); + color: var(--color-text); + font-family: var(--font-family); + line-height: var(--line-height); + margin: 0; + overflow-x: hidden; + padding: 0; +} + +footer, +header, +main { + margin: 0 auto; + max-width: var(--width-content); + padding: 3rem 1rem; +} + +hr { + background-color: var(--color-bg-secondary); + border: none; + height: 1px; + margin: 4rem 0; + width: 100%; +} + +section { + display: flex; + flex-wrap: wrap; + justify-content: var(--justify-important); +} + +section img, +article img { + max-width: 100%; +} + +section pre { + overflow: auto; +} + +section aside { + border: 1px solid var(--color-bg-secondary); + border-radius: var(--border-radius); + box-shadow: var(--box-shadow) var(--color-shadow); + margin: 1rem; + padding: 1.25rem; + width: var(--width-card); +} + +section aside:hover { + box-shadow: var(--box-shadow) var(--color-bg-secondary); +} + +[hidden] { + display: none; +} + +/* Headers */ +article header, +div header, +main header { + padding-top: 0; +} + +header { + text-align: var(--justify-important); +} + +header a b, +header a em, +header a i, +header a strong { + margin-left: 0.5rem; + margin-right: 0.5rem; +} + +header nav img { + margin: 1rem 0; +} + +section header { + padding-top: 0; + width: 100%; +} + +/* Nav */ +nav { + align-items: center; + display: flex; + font-weight: bold; + justify-content: space-between; + /*Peru margin-bottom: 7rem; */ + margin-bottom: 1rem; +} + +nav ul { + list-style: none; + padding: 0; +} + +nav ul li { + display: inline-block; + margin: 0 0.5rem; + position: relative; + text-align: left; +} + +/* Nav Dropdown */ +nav ul li:hover ul { + display: block; +} + +nav ul li ul { + background: var(--color-bg); + border: 1px solid var(--color-bg-secondary); + border-radius: var(--border-radius); + box-shadow: var(--box-shadow) var(--color-shadow); + display: none; + height: auto; + left: -2px; + padding: .5rem 1rem; + position: absolute; + top: 1.7rem; + white-space: nowrap; + width: auto; + z-index: 1; +} + +nav ul li ul::before { + /* fill gap above to make mousing over them easier */ + content: ""; + position: absolute; + left: 0; + right: 0; + top: -0.5rem; + height: 0.5rem; +} + +nav ul li ul li, +nav ul li ul li a { + display: block; +} + +/* Typography */ +code, +samp { + background-color: var(--color-accent); + border-radius: var(--border-radius); + color: var(--color-text); + display: inline-block; + margin: 0 0.1rem; + padding: 0 0.5rem; +} + +details { + margin: 1.3rem 0; +} + +details summary { + font-weight: bold; + cursor: pointer; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + line-height: var(--line-height); +} + +mark { + padding: 0.1rem; +} + +ol li, +ul li { + padding: 0.2rem 0; +} + +p { + margin: 0.75rem 0; + padding: 0; +} + +pre { + margin: 1rem 0; + max-width: var(--width-card-wide); + padding: 1rem 0; +} + +pre code, +pre samp { + display: block; + max-width: var(--width-card-wide); + padding: 0.5rem 2rem; + white-space: pre-wrap; +} + +small { + color: var(--color-text-secondary); +} + +sup { + background-color: var(--color-secondary); + border-radius: var(--border-radius); + color: var(--color-bg); + font-size: xx-small; + font-weight: bold; + margin: 0.2rem; + padding: 0.2rem 0.3rem; + position: relative; + top: -2px; +} + +/* Links */ +a { + color: var(--color); + display: inline-block; + font-weight: bold; + text-decoration: none; +} + +a:hover { + filter: brightness(var(--hover-brightness)); + text-decoration: underline; +} + +a b, +a em, +a i, +a strong, +button { + border-radius: var(--border-radius); + display: inline-block; + font-size: medium; + font-weight: bold; + line-height: var(--line-height); + margin: 0.5rem 0; + padding: 1rem 2rem; +} + +button { + font-family: var(--font-family); +} + +button:hover { + cursor: pointer; + filter: brightness(var(--hover-brightness)); +} + +a b, +a strong, +button { + background-color: var(--color); + border: 2px solid var(--color); + color: var(--color-bg); +} + +a em, +a i { + border: 2px solid var(--color); + border-radius: var(--border-radius); + color: var(--color); + display: inline-block; + padding: 1rem 2rem; +} + +article aside a { + color: var(--color-secondary); +} + +/* Images */ +figure { + margin: 0; + padding: 0; +} + +figure img { + max-width: 100%; +} + +figure figcaption { + color: var(--color-text-secondary); +} + +/* Forms */ + +button:disabled, +input:disabled { + background: var(--color-bg-secondary); + border-color: var(--color-bg-secondary); + color: var(--color-text-secondary); + cursor: not-allowed; +} + +button[disabled]:hover { + filter: none; +} + +form { + border: 1px solid var(--color-bg-secondary); + border-radius: var(--border-radius); + box-shadow: var(--box-shadow) var(--color-shadow); + display: block; + max-width: var(--width-card-wide); + min-width: var(--width-card); + padding: 1.5rem; + text-align: var(--justify-normal); +} + +form header { + margin: 1.5rem 0; + padding: 1.5rem 0; +} + +input, +label, +select, +textarea { + display: block; + font-size: inherit; + max-width: var(--width-card-wide); +} + +input[type="checkbox"], +input[type="radio"] { + display: inline-block; +} + +input[type="checkbox"]+label, +input[type="radio"]+label { + display: inline-block; + font-weight: normal; + position: relative; + top: 1px; +} + +input, +select, +textarea { + border: 1px solid var(--color-bg-secondary); + border-radius: var(--border-radius); + margin-bottom: 1rem; + padding: 0.4rem 0.8rem; +} + +input[readonly], +textarea[readonly] { + background-color: var(--color-bg-secondary); +} + +label { + font-weight: bold; + margin-bottom: 0.2rem; +} + +/* Tables */ +table { + border: 1px solid var(--color-bg-secondary); + border-radius: var(--border-radius); + border-spacing: 0; + display: inline-block; + max-width: 100%; + overflow-x: auto; + padding: 0; + white-space: nowrap; +} + +table td, +table th, +table tr { + padding: 0.4rem 0.8rem; + text-align: var(--justify-important); +} + +table thead { + background-color: var(--color); + border-collapse: collapse; + border-radius: var(--border-radius); + color: var(--color-bg); + margin: 0; + padding: 0; +} + +table thead th:first-child { + border-top-left-radius: var(--border-radius); +} + +table thead th:last-child { + border-top-right-radius: var(--border-radius); +} + +table thead th:first-child, +table tr td:first-child { + text-align: var(--justify-normal); +} + +table tr:nth-child(even) { + background-color: var(--color-accent); +} + +/* Quotes */ +blockquote { + display: block; + font-size: x-large; + line-height: var(--line-height); + margin: 1rem auto; + max-width: var(--width-card-medium); + padding: 1.5rem 1rem; + text-align: var(--justify-important); +} + +blockquote footer { + color: var(--color-text-secondary); + display: block; + font-size: small; + line-height: var(--line-height); + padding: 1.5rem 0; +} \ No newline at end of file diff --git a/183_12_2_tresorfrontend_rupe-master/src/index.css b/183_12_2_tresorfrontend_rupe-master/src/index.css new file mode 100644 index 0000000..ec2585e --- /dev/null +++ b/183_12_2_tresorfrontend_rupe-master/src/index.css @@ -0,0 +1,13 @@ +body { + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', + 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +code { + font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', + monospace; +} diff --git a/183_12_2_tresorfrontend_rupe-master/src/index.js b/183_12_2_tresorfrontend_rupe-master/src/index.js new file mode 100644 index 0000000..d563c0f --- /dev/null +++ b/183_12_2_tresorfrontend_rupe-master/src/index.js @@ -0,0 +1,17 @@ +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import './index.css'; +import App from './App'; +import reportWebVitals from './reportWebVitals'; + +const root = ReactDOM.createRoot(document.getElementById('root')); +root.render( + + + +); + +// If you want to start measuring performance in your app, pass a function +// to log results (for example: reportWebVitals(console.log)) +// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals +reportWebVitals(); diff --git a/183_12_2_tresorfrontend_rupe-master/src/pages/Home.js b/183_12_2_tresorfrontend_rupe-master/src/pages/Home.js new file mode 100644 index 0000000..f9bdea0 --- /dev/null +++ b/183_12_2_tresorfrontend_rupe-master/src/pages/Home.js @@ -0,0 +1,20 @@ +import '../App.css'; + +/** + * Home + * @author Peter Rutschmann + */ +const Home = () => { + return ( + <> +

Speichern Sie Ihre Daten sicher ab.

+
+

In dieser Applikation können Sie, nachdem Sie sich registriert haben, Ihre sensitiven Daten verschlüsselt + in einer Datenbank speichern.

+

Erstellen Sie ein neues Secret. Wählen Sie zwischen Credentials, Credit-Cards und Notes.

+
+ + ); +}; + +export default Home; \ No newline at end of file diff --git a/183_12_2_tresorfrontend_rupe-master/src/pages/Layout.js b/183_12_2_tresorfrontend_rupe-master/src/pages/Layout.js new file mode 100644 index 0000000..bcb86d6 --- /dev/null +++ b/183_12_2_tresorfrontend_rupe-master/src/pages/Layout.js @@ -0,0 +1,47 @@ +import { Outlet, Link } from "react-router-dom"; + +/** + * Layout + * @author Peter Rutschmann + */ +const Layout = ({loginValues}) => { + return ( + <> + +
+ + + ) +}; + +export default Layout; \ No newline at end of file diff --git a/183_12_2_tresorfrontend_rupe-master/src/pages/NoPage.js b/183_12_2_tresorfrontend_rupe-master/src/pages/NoPage.js new file mode 100644 index 0000000..20f0dca --- /dev/null +++ b/183_12_2_tresorfrontend_rupe-master/src/pages/NoPage.js @@ -0,0 +1,16 @@ +import '../App.css'; + +/** + * NoPage + * @author Peter Rutschmann + */ +const NoPage = () => { + return( +
+

404

+

Page currently not supported.

+
+ ) +}; + +export default NoPage; \ No newline at end of file diff --git a/183_12_2_tresorfrontend_rupe-master/src/pages/secret/NewCredential.js b/183_12_2_tresorfrontend_rupe-master/src/pages/secret/NewCredential.js new file mode 100644 index 0000000..bdd127e --- /dev/null +++ b/183_12_2_tresorfrontend_rupe-master/src/pages/secret/NewCredential.js @@ -0,0 +1,85 @@ +import React, { useState } from 'react'; +import { useNavigate } from 'react-router-dom'; +import {postSecret} from "../../comunication/FetchSecrets"; + +/** + * NewCredential + * @author Peter Rutschmann + */ +function NewCredential({loginValues}) { + const initialState = { + kindid: 1, + kind:"credential", + userName: "", + password: "", + url: "" + }; + const [credentialValues, setCredentialValues] = useState(initialState); + const [errorMessage, setErrorMessage] = useState(''); + + const navigate = useNavigate(); + + const handleSubmit = async (e) => { + e.preventDefault(); + setErrorMessage(''); + console.log(loginValues) + try { + const content = credentialValues; + await postSecret({loginValues, content}); + setCredentialValues(initialState); + navigate('/secret/secrets'); + } catch (error) { + console.error('Failed to fetch to server:', error.message); + setErrorMessage(error.message); + } + }; + + return ( +
+

Add new credential secret

+
+
+ +
+
+
+ ); +} + +export default NewCredential; diff --git a/183_12_2_tresorfrontend_rupe-master/src/pages/secret/NewCreditCard.js b/183_12_2_tresorfrontend_rupe-master/src/pages/secret/NewCreditCard.js new file mode 100644 index 0000000..5cc5521 --- /dev/null +++ b/183_12_2_tresorfrontend_rupe-master/src/pages/secret/NewCreditCard.js @@ -0,0 +1,103 @@ +import React, { useState } from 'react'; +import { useNavigate } from 'react-router-dom'; +import {postSecret} from "../../comunication/FetchSecrets"; + +/** + * NewCreditCard + * @author Peter Rutschmann + */ +function NewCreditCard({loginValues}) { + const initialState = { + kindid: 2, + kind:"creditcard", + cardtype: "", + cardnumber: "", + expiration: "", + cvv: "" + }; + const [creditCardValues, setCreditCardValues] = useState(initialState); + const [errorMessage, setErrorMessage] = useState(''); + + const navigate = useNavigate(); + + const handleSubmit = async (e) => { + e.preventDefault(); + setErrorMessage(''); + try { + const content = creditCardValues; + await postSecret({loginValues, content}); + setCreditCardValues(initialState); + navigate('/secret/secrets'); + } catch (error) { + console.error('Failed to fetch to server:', error.message); + setErrorMessage(error.message); + } + }; + + return ( +
+

Add new credit-card secret

+
+
+ +
+
+
+ ); +} + +export default NewCreditCard; diff --git a/183_12_2_tresorfrontend_rupe-master/src/pages/secret/NewNote.js b/183_12_2_tresorfrontend_rupe-master/src/pages/secret/NewNote.js new file mode 100644 index 0000000..5fa7915 --- /dev/null +++ b/183_12_2_tresorfrontend_rupe-master/src/pages/secret/NewNote.js @@ -0,0 +1,79 @@ +import React, { useState } from 'react'; +import { useNavigate } from 'react-router-dom'; +import {postSecret} from "../../comunication/FetchSecrets"; + +/** + * NewNote + * @author Peter Rutschmann + */ +function NewNote({loginValues}) { + const initialState = { + kindid: 3, + kind:"note", + title: "", + content: "", + }; + const [noteValues, setNoteValues] = useState(initialState); + const [errorMessage, setErrorMessage] = useState(''); + + const navigate = useNavigate(); + + const handleSubmit = async (e) => { + e.preventDefault(); + setErrorMessage(''); + try { + const content = noteValues; + await postSecret({loginValues, content}); + setNoteValues(initialState); + navigate('/secret/secrets'); + } catch (error) { + console.error('Failed to fetch to server:', error.message); + setErrorMessage(error.message); + } + }; + + return ( +
+

Add new note secret

+
+
+