diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..73f69e0958611ac6e00bde95641f6699030ad235 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/.idea/back-practice1.iml b/.idea/back-practice1.iml new file mode 100644 index 0000000000000000000000000000000000000000..d6ebd4805981b8400db3e3291c74a743fef9a824 --- /dev/null +++ b/.idea/back-practice1.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000000000000000000000000000000000000..639900d13c6182e452e33a3bd638e70a0146c785 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000000000000000000000000000000000000..a94ec83c3004e85291a0f465de68c46c8095ffee --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000000000000000000000000000000000000..35eb1ddfbbc029bcab630581847471d7f238ec53 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/bookstore/.gitignore b/bookstore/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..549e00a2a96fa9d7c5dbc9859664a78d980158c2 --- /dev/null +++ b/bookstore/.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/bookstore/.mvn/wrapper/MavenWrapperDownloader.java b/bookstore/.mvn/wrapper/MavenWrapperDownloader.java new file mode 100644 index 0000000000000000000000000000000000000000..2943987ff491eee87d3d8f62ec2bc3685db248dc --- /dev/null +++ b/bookstore/.mvn/wrapper/MavenWrapperDownloader.java @@ -0,0 +1,118 @@ +/* + * Copyright 2007-present the original author or authors. + * + * Licensed 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. + */ + +import java.net.*; +import java.io.*; +import java.nio.channels.*; +import java.util.Properties; + +public class MavenWrapperDownloader { + + private static final String WRAPPER_VERSION = "0.5.6"; + /** + * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. + */ + private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" + + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; + + /** + * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to + * use instead of the default one. + */ + private static final String MAVEN_WRAPPER_PROPERTIES_PATH = + ".mvn/wrapper/maven-wrapper.properties"; + + /** + * Path where the maven-wrapper.jar will be saved to. + */ + private static final String MAVEN_WRAPPER_JAR_PATH = + ".mvn/wrapper/maven-wrapper.jar"; + + /** + * Name of the property which should be used to override the default download url for the wrapper. + */ + private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; + + public static void main(String args[]) { + System.out.println("- Downloader started"); + File baseDirectory = new File(args[0]); + System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); + + // If the maven-wrapper.properties exists, read it and check if it contains a custom + // wrapperUrl parameter. + File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); + String url = DEFAULT_DOWNLOAD_URL; + if (mavenWrapperPropertyFile.exists()) { + FileInputStream mavenWrapperPropertyFileInputStream = null; + try { + mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); + Properties mavenWrapperProperties = new Properties(); + mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); + url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); + } catch (IOException e) { + System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); + } finally { + try { + if (mavenWrapperPropertyFileInputStream != null) { + mavenWrapperPropertyFileInputStream.close(); + } + } catch (IOException e) { + // Ignore ... + } + } + } + System.out.println("- Downloading from: " + url); + + File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); + if (!outputFile.getParentFile().exists()) { + if (!outputFile.getParentFile().mkdirs()) { + System.out.println( + "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); + } + } + System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); + try { + downloadFileFromURL(url, outputFile); + System.out.println("Done"); + System.exit(0); + } catch (Throwable e) { + System.out.println("- Error downloading"); + e.printStackTrace(); + System.exit(1); + } + } + + private static void downloadFileFromURL(String urlString, File destination) throws Exception { + if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { + String username = System.getenv("MVNW_USERNAME"); + char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); + Authenticator.setDefault(new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(username, password); + } + }); + } + URL website = new URL(urlString); + ReadableByteChannel rbc; + rbc = Channels.newChannel(website.openStream()); + FileOutputStream fos = new FileOutputStream(destination); + fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); + fos.close(); + rbc.close(); + } + +} diff --git a/bookstore/.mvn/wrapper/maven-wrapper.jar b/bookstore/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..2cc7d4a55c0cd0092912bf49ae38b3a9e3fd0054 Binary files /dev/null and b/bookstore/.mvn/wrapper/maven-wrapper.jar differ diff --git a/bookstore/.mvn/wrapper/maven-wrapper.properties b/bookstore/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000000000000000000000000000000000000..abd303b6738e8492a676925355189594fe1528ac --- /dev/null +++ b/bookstore/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,2 @@ +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.2/apache-maven-3.8.2-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar diff --git a/bookstore/mvnw b/bookstore/mvnw new file mode 100644 index 0000000000000000000000000000000000000000..3c8a5537314954d53ec2fb774b34fe5d5a5f253a --- /dev/null +++ b/bookstore/mvnw @@ -0,0 +1,322 @@ +#!/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. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# 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 /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 + export JAVA_HOME="$(/usr/libexec/java_home)" + else + export JAVA_HOME="/Library/Java/Home" + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ]; then + if [ -r /etc/gentoo-release ]; then + JAVA_HOME=$(java-config --jre-home) + fi +fi + +if [ -z "$M2_HOME" ]; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ]; do + ls=$(ls -ld "$PRG") + link=$(expr "$ls" : '.*-> \(.*\)$') + if expr "$link" : '/.*' >/dev/null; then + PRG="$link" + else + PRG="$(dirname "$PRG")/$link" + fi + done + + saveddir=$(pwd) + + M2_HOME=$(dirname "$PRG")/.. + + # make it fully qualified + M2_HOME=$(cd "$M2_HOME" && pwd) + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=$(cygpath --unix "$M2_HOME") + [ -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 "$M2_HOME" ] && + M2_HOME="$( ( + cd "$M2_HOME" + pwd + ))" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="$( ( + cd "$JAVA_HOME" + 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="$(which 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 + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# 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/.." + pwd + ) + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' <"$1")" + fi +} + +BASE_DIR=$(find_maven_basedir "$(pwd)") +if [ -z "$BASE_DIR" ]; then + exit 1 +fi + +########################################################################################## +# 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. +########################################################################################## +if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found .mvn/wrapper/maven-wrapper.jar" + fi +else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." + fi + if [ -n "$MVNW_REPOURL" ]; then + jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + else + jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + fi + while IFS="=" read key value; do + case "$key" in wrapperUrl) + jarUrl="$value" + break + ;; + esac + done <"$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Downloading from: $jarUrl" + fi + wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + if $cygwin; then + wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath") + fi + + if command -v wget >/dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget "$jarUrl" -O "$wrapperJarPath" + else + wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" + fi + elif command -v curl >/dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl -o "$wrapperJarPath" "$jarUrl" -f + else + curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f + fi + + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaClass=$(cygpath --path --windows "$javaClass") + fi + if [ -e "$javaClass" ]; then + if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Compiling MavenWrapperDownloader.java ..." + fi + # Compiling the Java class + ("$JAVA_HOME/bin/javac" "$javaClass") + fi + if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + # Running the downloader + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Running MavenWrapperDownloader.java ..." + fi + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +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 "$M2_HOME" ] && + M2_HOME=$(cygpath --path --windows "$M2_HOME") + [ -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 + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/bookstore/mvnw.cmd b/bookstore/mvnw.cmd new file mode 100644 index 0000000000000000000000000000000000000000..c8d43372c986d97911cdc21bd87e0cbe3d83bdda --- /dev/null +++ b/bookstore/mvnw.cmd @@ -0,0 +1,182 @@ +@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 Maven Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@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 "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" +if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\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 DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + +FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET DOWNLOAD_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 DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_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('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@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 "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" +if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\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% + +exit /B %ERROR_CODE% diff --git a/bookstore/pom.xml b/bookstore/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..bc27d2cd3715c20c75ee4bf11d873f2d526a5d4a --- /dev/null +++ b/bookstore/pom.xml @@ -0,0 +1,75 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.5.5 + + + com + bookstore + 0.0.1-SNAPSHOT + bookstore + Demo project for Spring Boot + + 1.8 + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-devtools + runtime + true + + + mysql + mysql-connector-java + runtime + + + org.springframework.boot + spring-boot-configuration-processor + true + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.security + spring-security-test + test + + + com.auth0 + java-jwt + 3.10.3 + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/bookstore/src/main/java/com/bookstore/BookstoreApplication.java b/bookstore/src/main/java/com/bookstore/BookstoreApplication.java new file mode 100644 index 0000000000000000000000000000000000000000..532117449714cb36ae94adf629c4417dccea26e9 --- /dev/null +++ b/bookstore/src/main/java/com/bookstore/BookstoreApplication.java @@ -0,0 +1,13 @@ +package com.bookstore; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class BookstoreApplication { + + public static void main(String[] args) { + SpringApplication.run(BookstoreApplication.class, args); + } + +} diff --git a/bookstore/src/main/java/com/bookstore/config/BookstoreWebConfig.java b/bookstore/src/main/java/com/bookstore/config/BookstoreWebConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..db85087257b48b5f8957afd04524aca00bd0a327 --- /dev/null +++ b/bookstore/src/main/java/com/bookstore/config/BookstoreWebConfig.java @@ -0,0 +1,118 @@ +package com.bookstore.config; + +import com.bookstore.security.AuthFilter; +import com.bookstore.security.LoginFilter; +import com.bookstore.security.UnAuthHandle; +import com.bookstore.service.UserDetailServiceImp; +import com.bookstore.utils.JWTUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.dao.DaoAuthenticationProvider; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.builders.WebSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; + +@Configuration +@EnableWebSecurity +@EnableGlobalMethodSecurity(prePostEnabled = true) +public class BookstoreWebConfig extends WebSecurityConfigurerAdapter { + + private UserDetailServiceImp userDetailServiceImp; + private JWTUtil jwtUtil; + + @Autowired + private BCryptPasswordEncoder bCryptPasswordEncoder; + + /** + * * @param userDetailServiceImp + * + * @return + * @author ZXY + * @date 2021/10/23 22:10 + **/ + @Autowired + public BookstoreWebConfig(UserDetailServiceImp userDetailServiceImp) { + + this.userDetailServiceImp = userDetailServiceImp; + this.jwtUtil = new JWTUtil(); + } + + /** + * * @param null + * + * @return org.springframework.security.authentication.dao.DaoAuthenticationProvider + * @author ZXY + * @date 2021/10/23 22:10 + **/ + @Bean + public DaoAuthenticationProvider getDaoAuthenticationProvider() { + DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider(); + daoAuthenticationProvider.setPasswordEncoder(bCryptPasswordEncoder); + daoAuthenticationProvider.setUserDetailsService(userDetailServiceImp); + daoAuthenticationProvider.setHideUserNotFoundExceptions(false); + return daoAuthenticationProvider; + } + + /** + * * @param auth + * + * @return void + * @author ZXY + * @date 2021/10/23 22:10 + **/ + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth.authenticationProvider(getDaoAuthenticationProvider()); + + } + + /** + * * @param null + * + * @return org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder + * @author ZXY + * @date 2021/10/23 22:11 + **/ + @Bean + public BCryptPasswordEncoder getBCryptPasswordEncoder() { + return new BCryptPasswordEncoder(); + } + + /** + * * @param http + * + * @return void + * @author ZXY + * @date 2021/10/23 22:11 + **/ + @Override + protected void configure(HttpSecurity http) throws Exception { + + + http + .exceptionHandling().authenticationEntryPoint(new UnAuthHandle()) + .and() + .addFilter(new LoginFilter(jwtUtil, authenticationManager())) + .addFilterAfter(new AuthFilter(authenticationManager(), userDetailServiceImp), LoginFilter.class) + .httpBasic() + .and() + .csrf().disable(); + } + + /** + * @param web + * + * @return void + * @author ZXY + * @date 2021/10/23 22:11 + **/ + @Override + public void configure(WebSecurity web) throws Exception { + super.configure(web); + } +} diff --git a/bookstore/src/main/java/com/bookstore/controller/BookController.java b/bookstore/src/main/java/com/bookstore/controller/BookController.java new file mode 100644 index 0000000000000000000000000000000000000000..ac662419c963e3a2f0b09c45f2d1f397d1828d63 --- /dev/null +++ b/bookstore/src/main/java/com/bookstore/controller/BookController.java @@ -0,0 +1,363 @@ +package com.bookstore.controller; + +import com.bookstore.entity.Book; +import com.bookstore.entity.Record; +import com.bookstore.entity.User; +import com.bookstore.repository.RecordRepository; +import com.bookstore.service.BookService; +import com.bookstore.service.UserService; +import com.bookstore.utils.Code; +import com.bookstore.utils.Response; +import com.fasterxml.jackson.annotation.JsonProperty; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +import java.io.Serializable; +import java.util.*; + +/** + * @program: bookstore + * @description: + * @author: ZXY + * @create: 2021-10-28 14:56 + **/ +@RestController +public class BookController { + + @Autowired + BookService bookService; + @Autowired + UserService userService; + @Autowired + RecordRepository recordRepository; + + /** + * @param book_id + * @return com.bookstore.utils.Response + * @author ZXY + * @date 2021/10/28 17:30 + * @description 借书 + **/ + @RequestMapping(value = "/book/borrow", method = RequestMethod.POST) + @PreAuthorize("isAuthenticated()") + public Response borrowBook(long book_id) { + //根据我的理解,客户不应当能够修改和查看其他客户的信息,request请求中已经携带了用于身份识别的token,因此删去user_id参数 + try { + Record record = bookService.borrowBook(book_id); + if (record != null) { + HashMap hashMap = new HashMap<>(); + hashMap.put("record_id", record.getRecordID()); + hashMap.put("borrow_date", record.getBorrowDate()); + return new Response(Code.SUCCESS, hashMap, "success"); + } + return new Response(Code.Fail, null, "图书不可借"); + } catch (Exception e) { + return new Response(Code.Fail, null, e.getMessage()); + } + + } + + /** + * @param name + * @param introduction + * @param place + * @param author + * @param price + * @return com.bookstore.utils.Response + * @author ZXY + * @date 2021/10/28 17:29 + * @description 加书 + **/ + @RequestMapping(value = "/book", method = RequestMethod.POST) + @PreAuthorize("hasRole('ROLE_ADMIN')") + public Response addBook(String name, String place, String introduction, String author, Float price) { + + Book book = bookService.addBook(name, place, introduction, author, price); + + if (book != null) { + HashMap hashMap = new HashMap<>(); + hashMap.put("book_id", book.getBookID()); + return new Response(Code.SUCCESS, hashMap, "success"); + } + + return new Response(Code.Fail, null, "添加失败"); + } + + /** + * @param book_id + * @param name + * @param place + * @param introduction + * @param author + * @param price + * @return com.bookstore.utils.Response + * @author ZXY + * @date 2021/10/28 20:12 + * @description 更新书 + **/ + @RequestMapping(value = "/book", method = RequestMethod.PUT) + @PreAuthorize("hasRole('ROLE_ADMIN')") + public Response updateBookInfo(long book_id, String name, String place, String introduction, String author, Float price) { + try { + + Book book = bookService.updateBookInfo(book_id, name, place, introduction, author, price); + HashMap hashMap = new HashMap<>(); + hashMap.put("name", name); + hashMap.put("place", place); + hashMap.put("introduction", introduction); + hashMap.put("author", author); + hashMap.put("price", price); + + return new Response(Code.SUCCESS, hashMap, "success"); + } catch (Exception e) { + return new Response(Code.Fail, null, e.getMessage()); + } + } + + /** + * @param book_id + * @return com.bookstore.utils.Response + * @author ZXY + * @date 2021/10/28 20:12 + * @description 删书 + **/ + @RequestMapping(value = "/book", method = RequestMethod.DELETE) + @PreAuthorize("hasRole('ROLE_ADMIN')") + public Response deleteBook(long book_id) { + + Book book = bookService.deleteBook(book_id); + if (book != null) { + HashMap hashMap = new HashMap<>(); + hashMap.put("name", book.getBookName()); + hashMap.put("place", book.getPlace()); + hashMap.put("introduction", book.getIntroduction()); + hashMap.put("author", book.getAuthor()); + hashMap.put("price", book.getPrice()); + + return new Response(Code.SUCCESS, hashMap, "success"); + } + return new Response(Code.Fail, null, "找不到相关图书"); + } + + /** + * @param book_id + * @return com.bookstore.utils.Response + * @author ZXY + * @date 2021/10/28 20:12 + * @description 查询图书借还状态 + **/ + @RequestMapping(value = "/book/status", method = RequestMethod.GET) + @PreAuthorize("isAuthenticated()") + @Transactional + public Response getBookStatus(long book_id) { + + try { + List records = bookService.getBookRecords(book_id); + Record record = records.get(records.size() - 1); + HashMap hashMap = new HashMap<>(); + hashMap.put("record_id", record.getRecordID()); + hashMap.put("borrow_date", record.getBorrowDate()); + hashMap.put("return_date",record.getReturnDate()); + return new Response(Code.SUCCESS, hashMap, "success"); + } catch (Exception e) { + return new Response(Code.Fail, null, e.getMessage()); + } + + } + + /** + * @return com.bookstore.utils.Response + * @author ZXY + * @date 2021/10/28 20:13 + * @description 获取图书列表 + **/ + @RequestMapping(value = "/books", method = RequestMethod.GET) + @PreAuthorize("isAuthenticated()") + public Response getAllBooks() { + + List books = bookService.getAllBooks(); + ArrayList bookInfos = new ArrayList<>(); + for (Book book : books) { + bookInfos.add(new BookInfo(book.getBookID(), book.getBookName())); + } + return new Response(Code.SUCCESS, bookInfos, "success"); + } + + /** + * @param book_id + * @return com.bookstore.utils.Response + * @author ZXY + * @date 2021/10/28 20:13 + * @description 获取指定书目的记录 + **/ + @RequestMapping(value = "/book/records", method = RequestMethod.GET) + @PreAuthorize("hasRole('ROLE_ADMIN')") + public Response getBookRecords(long book_id) { + + try { + List records = bookService.getBookRecords(book_id); + System.out.println(records); + ArrayList recordInfos = new ArrayList<>(); + for (Record r : records) { + recordInfos.add(new RecordInfo(r.getRecordID(), r.getBorrowDate(), r.getReturnDate(), r.getUser().getUsername(), r.getUser().getUserID())); + } + return new Response(Code.SUCCESS, recordInfos, "success"); + } catch (Exception e) { + return new Response(Code.Fail, null, e.getMessage()); + } + } + + + /** + * @param book_id + * @return com.bookstore.utils.Response + * @author ZXY + * @date 2021/10/28 20:13 + * @description 获得图书信息 + **/ + @RequestMapping(value = "/book", method = RequestMethod.GET) + @PreAuthorize("isAuthenticated()") + public Response getBookInfo(long book_id) { + + try { + Book book = bookService.getBookInfo(book_id); + + HashMap hashMap = new HashMap<>(); + hashMap.put("name", book.getBookName()); + hashMap.put("place", book.getPlace()); + hashMap.put("introduction", book.getIntroduction()); + hashMap.put("author", book.getAuthor()); + hashMap.put("price", book.getPrice()); + + return new Response(Code.SUCCESS, hashMap, "success"); + } catch (Exception e) { + return new Response(Code.Fail, null, e.getMessage()); + } + } + + /** + * @param record_id + * @return com.bookstore.utils.Response + * @author ZXY + * @date 2021/10/28 20:13 + * @description 还书 + **/ + @RequestMapping(value = "/book/return", method = RequestMethod.POST) + @PreAuthorize("isAuthenticated()") + @Transactional + public Response returnBook(long record_id) { + //根据我的理解,客户不应当能够修改和查看其他客户的信息,request请求中已经携带了用于身份识别的token,因此删去user_id参数 + String username = (String) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); + User user = userService.getUser(username); + if (user != null) { + try { + Optional optionalRecord = recordRepository.findById(record_id); + + if (optionalRecord.isPresent()) { + + Record record = optionalRecord.get(); + + if (record.getReturnDate() == null && user.getRecords().contains(record)) { + + record.getBook().setAvailable(true); + record.setReturnDate(new Date()); + + HashMap hashMap = new HashMap<>(); + + hashMap.put("borrow_date", record.getBorrowDate()); + hashMap.put("return_date", record.getReturnDate()); + + return new Response(Code.SUCCESS, hashMap, "success"); + + } + return new Response(Code.Fail, null, "该用户从未借该图书或已归还"); + + } + + return new Response(Code.Fail, null, "记录不存在"); + + } catch (Exception e) { + + return new Response(Code.Fail, null, e.getMessage()); + + } + } + return new Response(Code.Fail, null, "用户不存在"); + } + + /** + * @param record_id + * @return com.bookstore.utils.Response + * @author ZXY + * @date 2021/10/28 20:13 + * @description 通过记录查询书目借还状态 + **/ + @RequestMapping(value = "/book/record", method = RequestMethod.GET) + @PreAuthorize("isAuthenticated()") + public Response getBookRecord(long record_id) { + + try { + Optional optionalRecord = recordRepository.findById(record_id); + if (optionalRecord.isPresent()) { + Record record = optionalRecord.get(); + HashMap hashMap = new HashMap<>(); + hashMap.put("book_id", record.getBook().getBookID()); + hashMap.put("user_id", record.getUser().getUserID()); + hashMap.put("borrow_date", record.getBorrowDate()); + hashMap.put("return_date", record.getReturnDate()); + return new Response(Code.SUCCESS, hashMap, "success"); + } + + return new Response(Code.Fail, null, "记录不存在"); + } catch (Exception e) { + return new Response(Code.Fail, null, e.getMessage()); + } + } + + class RecordInfo { + @JsonProperty("record_id") + long record_id; + @JsonProperty("borrow_date") + Date borrow_date; + @JsonProperty("return_date") + Date return_date; + @JsonProperty("name") + String name; + @JsonProperty("user_id") + long user_id; + + public RecordInfo(long record_id, Date borrow_date, Date return_date, String name, long user_id) { + this.record_id = record_id; + this.borrow_date = borrow_date; + this.return_date = return_date; + this.name = name; + this.user_id = user_id; + } + + public RecordInfo(long record_id, Date borrow_date, Date return_date) { + this.record_id = record_id; + this.borrow_date = borrow_date; + this.return_date = return_date; + } + + } + + class BookInfo implements Serializable { + @JsonProperty("book_id") + long book_id; + @JsonProperty("name") + String name; + + public BookInfo(long bookID, String bookName) { + this.book_id = bookID; + this.name = bookName; + } + + } + +} \ No newline at end of file diff --git a/bookstore/src/main/java/com/bookstore/controller/UserController.java b/bookstore/src/main/java/com/bookstore/controller/UserController.java new file mode 100644 index 0000000000000000000000000000000000000000..6a005590a213dced860808e61ed47eaa29ac599d --- /dev/null +++ b/bookstore/src/main/java/com/bookstore/controller/UserController.java @@ -0,0 +1,222 @@ +package com.bookstore.controller; + +import com.bookstore.entity.Record; +import com.bookstore.entity.User; +import com.bookstore.service.UserService; +import com.bookstore.utils.Code; +import com.bookstore.utils.Response; +import com.fasterxml.jackson.annotation.JsonProperty; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; + +@RestController +@RequestMapping() +public class UserController { + + @Autowired + BCryptPasswordEncoder bCryptPasswordEncoder; + @Autowired + private UserService userService; + + /** + * @param username + * @param password + * @param email + * @param nickname + * @return com.bookstore.utils.Response + * @author ZXY + * @date 2021/10/23 22:19 + * @description 增用户 + **/ + @PreAuthorize("permitAll") + @RequestMapping(value = "/user", method = RequestMethod.POST) + public Response addUser(String username, String password, String email, String nickname) { + User user = new User(username, bCryptPasswordEncoder.encode(password), email, nickname); + try { + User u = userService.addUser(user); + long userID = u.getUserID(); + HashMap hashMap = new HashMap<>(); + hashMap.put("user_id", userID); + return new Response(Code.SUCCESS, hashMap, "success"); + } catch (Exception e) { + return new Response(Code.Fail, null, e.getMessage()); + } + } + + /** + * @param old_password + * @param password + * @return com.bookstore.utils.Response + * @author ZXY + * @date 2021/10/23 22:30 + * @description 改密码 + **/ + @RequestMapping(value = "/user/password", method = RequestMethod.POST) + @PreAuthorize("isAuthenticated()") + public Response updatePassword(String old_password, String password) { + //根据我的理解,客户不应当能够修改和查看其他客户的信息,request请求中已经携带了用于身份识别的token,因此删去user_id参数 + String username = (String) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); + + User user = userService.getUser(username); + + if (user != null && bCryptPasswordEncoder.matches(old_password, user.getPassword())) { + + User newUser = new User(); + + newUser.setPassword(password); + + userService.updateUserInfo(username, newUser); + return new Response(Code.SUCCESS, null, "success"); + } + + return new Response(Code.Fail, null, "旧密码错误"); + + } + + /** + * @param email + * @param nickname + * @return com.bookstore.utils.Response + * @author ZXY + * @date 2021/10/27 18:02 + * @description 更新用户信息 + **/ + @RequestMapping(value = "/user", method = RequestMethod.PUT) + @PreAuthorize("isAuthenticated()") + public Response updateUserInfo(String email, String nickname) { + //根据我的理解,客户不应当能够修改和查看其他客户的信息,request请求中已经携带了用于身份识别的token,因此删去user_id参数 + String username = (String) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); + User user = userService.getUser(username); + if (user != null) { + User newUser = new User(); + newUser.setEmail(email); + newUser.setNickName(nickname); + userService.updateUserInfo(username, newUser); + return new Response(Code.SUCCESS, null, "success"); + } + + return new Response(Code.Fail, null, "fail"); + } + + /** + * @return com.bookstore.utils.Response + * @author ZXY + * @date 2021/10/27 18:02 + * @description 获取用户信息 + **/ + @RequestMapping(value = "/user", method = RequestMethod.GET) + @PreAuthorize("isAuthenticated()") + public Response getUserInfo() { + //根据我的理解,客户不应当能够修改和查看其他客户的信息,request请求中已经携带了用于身份识别的token,因此删去user_id参数 + String username = (String) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); + User user = userService.getUser(username); + if (user != null) { + HashMap hashMap = new HashMap<>(); + hashMap.put("username", user.getUsername()); + hashMap.put("nickname", user.getNickName()); + hashMap.put("email", user.getEmail()); + return new Response(Code.SUCCESS, hashMap, "success"); + } + return new Response(Code.Fail, null, "fail"); + } + + /** + * @return com.bookstore.utils.Response + * @author ZXY + * @date 2021/10/27 18:01 + * @description 获取用户列表 + **/ + @RequestMapping(value = "/users", method = RequestMethod.GET) + @PreAuthorize("hasRole('ADMIN')") + public Response getAllUsers() { + ArrayList users = (ArrayList) userService.getAllUsers(); + ArrayList userInfos = new ArrayList<>(); + if (users != null) { + for (User u : users) { + userInfos.add(new UserInfo(u.getUsername(), u.getNickName(), u.getEmail())); + } + return new Response(Code.SUCCESS, userInfos, "success"); + } + return new Response(Code.Fail, null, "fail"); + } + + /** + * @return com.bookstore.utils.Response + * @author ZXY + * @date 2021/10/27 18:25 + * @description 获取用户全部记录 + **/ + @RequestMapping(value = "/user/books", method = RequestMethod.GET) + @PreAuthorize("isAuthenticated()") + public Response getUserRecords() { + + String username = (String) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); + + try { + List records = userService.getUserRecords(username); + + ArrayList recordInfos = new ArrayList<>(); + + for (Record r : records) { + recordInfos.add(new recordInfo(r.getBook().getBookID(), r.getUser().getUserID(), r.getBorrowDate(), r.getReturnDate(), r.getBook().getBookName())); + } + + return new Response(Code.SUCCESS, recordInfos, "success"); + + } catch (NullPointerException e) { + + return new Response(Code.Fail, null, e.getMessage()); + + } + + } + + class recordInfo { + @JsonProperty("book_id") + long book_id; + @JsonProperty("user_id") + long user_id; + @JsonProperty("borrow_date") + Date borrow_date; + @JsonProperty("return_date") + Date return_date; + @JsonProperty("name") + String name; + + public recordInfo(long book_id, long user_id, Date borrow_date, Date return_date, String name) { + this.book_id = book_id; + this.user_id = user_id; + this.borrow_date = borrow_date; + this.return_date = return_date; + this.name = name; + } + + } + + + class UserInfo { + @JsonProperty("username") + String username; + @JsonProperty("nickname") + String nickname; + @JsonProperty("email") + String email; + + public UserInfo(String username, String nickname, String email) { + this.username = username; + this.nickname = nickname; + this.email = email; + } + } + +} diff --git a/bookstore/src/main/java/com/bookstore/entity/Book.java b/bookstore/src/main/java/com/bookstore/entity/Book.java new file mode 100644 index 0000000000000000000000000000000000000000..2286a3e22945b3877e52d4fc2041501cb381b406 --- /dev/null +++ b/bookstore/src/main/java/com/bookstore/entity/Book.java @@ -0,0 +1,109 @@ +package com.bookstore.entity; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; + +import javax.persistence.*; +import java.util.ArrayList; +import java.util.List; + +@Entity +public class Book { + @JsonIgnore + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private long bookID; + + private String bookName; + private String Author; + private String introduction; + private String place; + private float price; + + private boolean isAvailable; + + @JsonIgnore + @OneToMany(cascade = {CascadeType.REFRESH,CascadeType.REMOVE}) + private List records; + + + public Book() { + records = new ArrayList<>(); + isAvailable = true; + } + + public Book(String bookName, String author, String introduction, String place, float price) { + records = new ArrayList<>(); + this.bookName = bookName; + Author = author; + this.introduction = introduction; + this.place = place; + this.price = price; + isAvailable = true; + } + + public List getRecords() { + return records; + } + + public void setRecords(List records) { + this.records = records; + } + + @JsonIgnore + public boolean isAvailable() { + return isAvailable; + } + + public void setAvailable(boolean available) { + isAvailable = available; + } + @JsonIgnore + public long getBookID() { + return bookID; + } + + public void setBookID(long bookID) { + this.bookID = bookID; + } + + public String getBookName() { + return bookName; + } + + public void setBookName(String bookName) { + this.bookName = bookName; + } + + public String getAuthor() { + return Author; + } + + public void setAuthor(String author) { + Author = author; + } + + public String getIntroduction() { + return introduction; + } + + public void setIntroduction(String introduction) { + this.introduction = introduction; + } + + public String getPlace() { + return place; + } + + public void setPlace(String place) { + this.place = place; + } + + public float getPrice() { + return price; + } + + public void setPrice(float price) { + this.price = price; + } +} diff --git a/bookstore/src/main/java/com/bookstore/entity/Record.java b/bookstore/src/main/java/com/bookstore/entity/Record.java new file mode 100644 index 0000000000000000000000000000000000000000..6cc94c7d1082dffdb7f82c62fef822c806098455 --- /dev/null +++ b/bookstore/src/main/java/com/bookstore/entity/Record.java @@ -0,0 +1,84 @@ +package com.bookstore.entity; + +import javax.persistence.*; +import java.util.Date; +import java.util.Objects; + +@Entity +public class Record { + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private long recordID; + + @ManyToOne + private User user; + + @ManyToOne + private Book book; + private Date borrowDate; + private Date returnDate; + + public Record() { + } + + public Record(User user, Book book, Date borrowDate) { + this.user = user; + this.book = book; + this.borrowDate = borrowDate; + } + + + + public long getRecordID() { + return recordID; + } + + public void setRecordID(long recordID) { + this.recordID = recordID; + } + + public User getUser() { + return user; + } + + public void setUser(User user) { + this.user = user; + } + + public Book getBook() { + return book; + } + + public void setBook(Book book) { + this.book = book; + } + + public Date getBorrowDate() { + return borrowDate; + } + + public void setBorrowDate(Date borrowDate) { + this.borrowDate = borrowDate; + } + + public Date getReturnDate() { + return returnDate; + } + + public void setReturnDate(Date returnDate) { + this.returnDate = returnDate; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Record)) return false; + Record record = (Record) o; + return recordID == record.recordID ; + } + + @Override + public int hashCode() { + return Objects.hash(recordID, user, book, borrowDate, returnDate); + } +} diff --git a/bookstore/src/main/java/com/bookstore/entity/Role.java b/bookstore/src/main/java/com/bookstore/entity/Role.java new file mode 100644 index 0000000000000000000000000000000000000000..d486629bb5d0b2b81bad50995af9599500e240f3 --- /dev/null +++ b/bookstore/src/main/java/com/bookstore/entity/Role.java @@ -0,0 +1,55 @@ +package com.bookstore.entity; + +import org.springframework.security.core.GrantedAuthority; + +import javax.persistence.Entity; +import javax.persistence.Id; + +@Entity +public class Role implements GrantedAuthority { + + @Id + private String role; + + public Role() { + } + + public Role(String role) { + this.role = role; + } + + public String getRole() { + return role; + } + + public void setRole(String role) { + this.role = role; + } + + @Override + public String getAuthority() { + return this.role; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof Role) { + return this.role.equals(((Role) obj).role); + } + return false; + } + + @Override + public int hashCode() { + return this.role.hashCode(); + } + + @Override + public String toString() { + return this.role; + } + +} diff --git a/bookstore/src/main/java/com/bookstore/entity/User.java b/bookstore/src/main/java/com/bookstore/entity/User.java new file mode 100644 index 0000000000000000000000000000000000000000..4a7619d705cce1e09c5a1d20363e3d8027698c44 --- /dev/null +++ b/bookstore/src/main/java/com/bookstore/entity/User.java @@ -0,0 +1,139 @@ +package com.bookstore.entity; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import org.springframework.security.core.GrantedAuthority; + +import javax.persistence.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +@Entity +public class User { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private long userID; + private String username; + private String password; + private String email; + private String nickName; + + private boolean nonExpired = true; + private boolean nonLocked = true; + private boolean enable = true; + private boolean credentialsNonExpired = true; + + @JsonIgnore + @ManyToMany(fetch = FetchType.EAGER) + private List roles; + + @JsonIgnore + @OneToMany(cascade = {CascadeType.REFRESH,CascadeType.REMOVE}) + private List records; + + public User() { + roles = new ArrayList<>(); + } + + public User(String username, String password, String email, String nickName) { + roles = new ArrayList<>(); + this.username = username; + this.password = password; + this.email = email; + this.nickName = nickName; + } + + public List getRecords() { + return records; + } + + public void setRecords(List records) { + this.records = records; + } + + public Collection getAuthorities() { + return roles; + } + + public long getUserID() { + return userID; + } + + public void setUserID(long userID) { + this.userID = userID; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getNickName() { + return nickName; + } + + public void setNickName(String nickName) { + this.nickName = nickName; + } + + public List getRoles() { + return roles; + } + + public void setRoles(List roles) { + this.roles = roles; + } + + public boolean isAccountNonExpired() { + return nonExpired; + } + + public boolean isAccountNonLocked() { + return nonLocked; + } + + public boolean isCredentialsNonExpired() { + return credentialsNonExpired; + } + + public void setCredentialsNonExpired(boolean credentialsNonExpired) { + this.credentialsNonExpired = credentialsNonExpired; + } + + public boolean isEnabled() { + return enable; + } + + public void setNonExpired(boolean nonExpired) { + this.nonExpired = nonExpired; + } + + public void setNonLocked(boolean nonLocked) { + this.nonLocked = nonLocked; + } + + public void setEnable(boolean enable) { + this.enable = enable; + } + +} diff --git a/bookstore/src/main/java/com/bookstore/entity/UserDetailsImp.java b/bookstore/src/main/java/com/bookstore/entity/UserDetailsImp.java new file mode 100644 index 0000000000000000000000000000000000000000..7d620353a8f836a2fa4a3334d8a263ac0787f8d5 --- /dev/null +++ b/bookstore/src/main/java/com/bookstore/entity/UserDetailsImp.java @@ -0,0 +1,96 @@ +package com.bookstore.entity; + +import org.springframework.context.annotation.Bean; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import java.util.Collection; +import java.util.List; + +public class UserDetailsImp implements UserDetails { + private String username; + private String password; + + private List roles; + private boolean nonExpired; + private boolean nonLocked; + private boolean enable; + private boolean credentialsNonExpired; + + public UserDetailsImp(String username, String password, List roles, boolean nonExpired, boolean nonLocked, boolean enable, boolean credentialsNonExpired) { + this.username = username; + this.password = password; + this.roles = roles; + this.nonExpired = nonExpired; + this.nonLocked = nonLocked; + this.enable = enable; + this.credentialsNonExpired = credentialsNonExpired; + } + + public List getRoles() { + return roles; + } + + public void setRoles(List roles) { + this.roles = roles; + } + + public Collection getAuthorities() { + return roles; + } + + @Override + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + @Override + public boolean isAccountNonExpired() { + return nonExpired; + } + + @Override + public boolean isAccountNonLocked() { + return nonLocked; + } + + @Override + public boolean isCredentialsNonExpired() { + return credentialsNonExpired; + } + + + @Override + public boolean isEnabled() { + return enable; + } + + public void setNonExpired(boolean nonExpired) { + this.nonExpired = nonExpired; + } + + public void setNonLocked(boolean nonLocked) { + this.nonLocked = nonLocked; + } + + public void setEnable(boolean enable) { + this.enable = enable; + } + + public void setCredentialsNonExpired(boolean credentialsNonExpired) { + this.credentialsNonExpired = credentialsNonExpired; + } + +} diff --git a/bookstore/src/main/java/com/bookstore/repository/BookRepository.java b/bookstore/src/main/java/com/bookstore/repository/BookRepository.java new file mode 100644 index 0000000000000000000000000000000000000000..b7a0c8bd109c4efe8867c60e3d2f8a3e7f20e47c --- /dev/null +++ b/bookstore/src/main/java/com/bookstore/repository/BookRepository.java @@ -0,0 +1,12 @@ +package com.bookstore.repository; + + +import com.bookstore.entity.Book; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; +import java.util.Optional; + +public interface BookRepository extends JpaRepository { + public Optional findBookByBookID(long bookID); +} diff --git a/bookstore/src/main/java/com/bookstore/repository/RecordRepository.java b/bookstore/src/main/java/com/bookstore/repository/RecordRepository.java new file mode 100644 index 0000000000000000000000000000000000000000..bf02b6666bb4a419d82182a745e41cf57dc1f378 --- /dev/null +++ b/bookstore/src/main/java/com/bookstore/repository/RecordRepository.java @@ -0,0 +1,10 @@ +package com.bookstore.repository; + +import com.bookstore.entity.Record; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface RecordRepository extends JpaRepository { + Optional findById(Long aLong); +} diff --git a/bookstore/src/main/java/com/bookstore/repository/RoleRepository.java b/bookstore/src/main/java/com/bookstore/repository/RoleRepository.java new file mode 100644 index 0000000000000000000000000000000000000000..6fca33c62faee76b509595742dd00552e0228248 --- /dev/null +++ b/bookstore/src/main/java/com/bookstore/repository/RoleRepository.java @@ -0,0 +1,10 @@ +package com.bookstore.repository; + +import com.bookstore.entity.Role; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface RoleRepository extends JpaRepository { + Optional findRoleByRole(String role); +} diff --git a/bookstore/src/main/java/com/bookstore/repository/UserRepository.java b/bookstore/src/main/java/com/bookstore/repository/UserRepository.java new file mode 100644 index 0000000000000000000000000000000000000000..ccc0a27ad55dd135ec5692535161e45d417403cb --- /dev/null +++ b/bookstore/src/main/java/com/bookstore/repository/UserRepository.java @@ -0,0 +1,12 @@ +package com.bookstore.repository; + +import com.bookstore.entity.User; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface UserRepository extends JpaRepository { + public Optional findUserByUsername(String username); + public Optional findUserByEmail(String email); + public Optional findUserByUserID(Long id); +} diff --git a/bookstore/src/main/java/com/bookstore/security/AuthFilter.java b/bookstore/src/main/java/com/bookstore/security/AuthFilter.java new file mode 100644 index 0000000000000000000000000000000000000000..d0ca1cf79ef87fcbfaf9d45c72b8020c7ac84ff9 --- /dev/null +++ b/bookstore/src/main/java/com/bookstore/security/AuthFilter.java @@ -0,0 +1,72 @@ +package com.bookstore.security; + +import com.auth0.jwt.interfaces.DecodedJWT; +import com.bookstore.service.UserDetailServiceImp; +import com.bookstore.utils.Code; +import com.bookstore.utils.JWTUtil; +import com.bookstore.utils.ResponseUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Date; + +public class AuthFilter extends BasicAuthenticationFilter { + + @Autowired + UserDetailServiceImp userDetailServiceImp; + + public AuthFilter(AuthenticationManager authenticationManager) { + super(authenticationManager); + + } + + public AuthFilter(AuthenticationManager authenticationManager, UserDetailServiceImp userDetailServiceImp) { + super(authenticationManager); + this.userDetailServiceImp = userDetailServiceImp; + } + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { + + try { + UsernamePasswordAuthenticationToken token = getAuth(request, userDetailServiceImp); + if(token!=null){ + SecurityContextHolder.getContext().setAuthentication(token); + } + chain.doFilter(request, response); + } catch (UsernameNotFoundException e) { + ResponseUtil.response(response, Code.Fail, null, e.getMessage()); + } + } + + public UsernamePasswordAuthenticationToken getAuth(HttpServletRequest request, UserDetailServiceImp userDetailServiceImp) throws UsernameNotFoundException { + + Date now = new Date(); + + String jwtToken = request.getHeader("Token"); + + if (jwtToken != null) { + + DecodedJWT decodedJWT = JWTUtil.verifyToken(jwtToken); + + if (now.before(decodedJWT.getExpiresAt())) { + String username = decodedJWT.getSubject(); + UserDetails userDetails = userDetailServiceImp.loadUserByUsername(username); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, jwtToken, userDetails.getAuthorities()); + return token; + } + } + + return null; + } +} diff --git a/bookstore/src/main/java/com/bookstore/security/LoginFilter.java b/bookstore/src/main/java/com/bookstore/security/LoginFilter.java new file mode 100644 index 0000000000000000000000000000000000000000..16fa089c99f215201d12581938dc41581c926887 --- /dev/null +++ b/bookstore/src/main/java/com/bookstore/security/LoginFilter.java @@ -0,0 +1,78 @@ +package com.bookstore.security; + +import com.bookstore.entity.UserDetailsImp; +import com.bookstore.repository.UserRepository; +import com.bookstore.utils.Code; +import com.bookstore.utils.JWTUtil; +import com.bookstore.utils.ResponseUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.log.LogMessage; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.authentication.event.InteractiveAuthenticationSuccessEvent; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.NullRememberMeServices; +import org.springframework.security.web.authentication.RememberMeServices; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +public class LoginFilter extends UsernamePasswordAuthenticationFilter { + + @Autowired + private UserRepository userRepository; + private RememberMeServices rememberMeServices = new NullRememberMeServices(); + private JWTUtil jwtUtil; + private AuthenticationManager authenticationManager; + + public LoginFilter(JWTUtil jwtUtil, AuthenticationManager authenticationManager) { + this.jwtUtil = jwtUtil; + this.authenticationManager = authenticationManager; + this.setPostOnly(true); + this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/login", "POST")); + } + + @Override + public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { + + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(obtainUsername(request), obtainPassword(request)); + + return authenticationManager.authenticate(token); + + } + + + @Override + protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException { + +// SecurityContextHolder.getContext().setAuthentication(authResult); + + if (this.logger.isDebugEnabled()) { + this.logger.debug(LogMessage.format("Set SecurityContextHolder to %s", authResult)); + } + this.rememberMeServices.loginSuccess(request, response, authResult); + if (this.eventPublisher != null) { + this.eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(authResult, this.getClass())); + } + UserDetailsImp userDetailsImp = (UserDetailsImp) authResult.getPrincipal(); + String token = jwtUtil.encrypt(userDetailsImp.getUsername()); + ResponseUtil.response(response, Code.SUCCESS, token, "success"); + + } + + @Override + protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException { + if (failed.getMessage().equals("Bad credentials")) { + ResponseUtil.response(response, Code.Fail, null, "Wrong Password!"); + }else{ + ResponseUtil.response(response, Code.Fail, null, failed.getMessage()); + } + } + +} diff --git a/bookstore/src/main/java/com/bookstore/security/UnAuthHandle.java b/bookstore/src/main/java/com/bookstore/security/UnAuthHandle.java new file mode 100644 index 0000000000000000000000000000000000000000..867ea3497c3babf05b24a920f278fa7df4bbc323 --- /dev/null +++ b/bookstore/src/main/java/com/bookstore/security/UnAuthHandle.java @@ -0,0 +1,24 @@ +package com.bookstore.security; + +import com.bookstore.utils.Code; +import com.bookstore.utils.ResponseUtil; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.AuthenticationEntryPoint; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * @program: bookstore + * @description: + * @author: ZXY + * @create: 2021-10-27 18:05 + **/ +public class UnAuthHandle implements AuthenticationEntryPoint { + @Override + public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { + ResponseUtil.response(response, Code.Fail,null,authException.getMessage()); + } +} diff --git a/bookstore/src/main/java/com/bookstore/service/BookService.java b/bookstore/src/main/java/com/bookstore/service/BookService.java new file mode 100644 index 0000000000000000000000000000000000000000..b1ef777b462603a3028aa12e5461f732d4721771 --- /dev/null +++ b/bookstore/src/main/java/com/bookstore/service/BookService.java @@ -0,0 +1,197 @@ +package com.bookstore.service; + +import com.bookstore.entity.Book; +import com.bookstore.entity.Record; +import com.bookstore.entity.User; +import com.bookstore.repository.BookRepository; +import com.bookstore.repository.RecordRepository; +import com.bookstore.repository.UserRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Date; +import java.util.List; +import java.util.Optional; + +@Service +public class BookService { + @Autowired + BookRepository bookRepository; + @Autowired + RecordRepository recordRepository; + @Autowired + UserRepository userRepository; + + /** + * @param bookID + * @return com.bookstore.entity.Book + * @author ZXY + * @date 2021/10/28 15:06 + **/ + public Book getBookInfo(long bookID) throws NullPointerException { + + Optional optionalBook = bookRepository.findBookByBookID(bookID); + if (optionalBook.isPresent()) { + return optionalBook.get(); + } + throw new NullPointerException("找不到相关图书"); + } + + /** + * @param bookID + * @return java.util.List + * @author ZXY + * @date 2021/11/2 16:06 + **/ + @Transactional + public List getBookRecords(long bookID) throws NullPointerException { + + + Optional optionalBook = bookRepository.findBookByBookID(bookID); + if (optionalBook.isPresent()) { + List records = optionalBook.get().getRecords(); + records.isEmpty(); + return records; + } + throw new NullPointerException("找不到相关图书"); + } + + /** + * @param bookName + * @param place + * @param introduction + * @param author + * @param price + * @return com.bookstore.entity.Book + * @author ZXY + * @date 2021/11/2 16:07 + **/ + public Book addBook(String bookName, String place, String introduction, String author, Float price) { + + if (bookName != null && price != null && place != null && introduction != null && author != null) { + Book book = new Book(bookName, author, introduction, place, price); + bookRepository.save(book); + return book; + } + + return null; + } + + /** + * @param bookID + * @return com.bookstore.entity.Book + * @author ZXY + * @date 2021/11/2 16:07 + **/ + @Transactional + public Book deleteBook(Long bookID) { + + Optional optionalBook = bookRepository.findBookByBookID(bookID); + + if (optionalBook.isPresent()) { + Book book = optionalBook.get(); + + for (Record r : book.getRecords()) { + + r.getUser().getRecords().remove(r); + + } + + bookRepository.delete(book); + return book; + + } + + return null; + } + + /** + * + * @param bookID + * @param bookName + * @param place + * @param introduction + * @param author + * @param price + * @return com.bookstore.entity.Book + * @author ZXY + * @date 2021/11/2 16:07 + **/ + public Book updateBookInfo(long bookID, String bookName, String place, String introduction, String author, Float price) throws NullPointerException, IllegalArgumentException { + + Optional optionalBook = bookRepository.findBookByBookID(bookID); + if (optionalBook.isPresent()) { + + if (bookName != null && price != null && place != null && introduction != null && author != null) { + Book book = optionalBook.get(); + book.setBookName(bookName); + book.setPrice(price); + book.setPlace(place); + book.setIntroduction(introduction); + book.setAuthor(author); + bookRepository.save(book); + return book; + } + + throw new IllegalArgumentException("参数为空"); + } + + throw new NullPointerException("找不到相关书籍"); + } + + /** + * + * @param bookID + * @return com.bookstore.entity.Record + * @author ZXY + * @date 2021/11/2 16:07 + **/ + @Transactional + public Record borrowBook(Long bookID) throws NullPointerException { + + String username = (String) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); + + Optional optionalUser = userRepository.findUserByUsername(username); + + if (optionalUser.isPresent()) { + + User user = optionalUser.get(); + Book book = getBookInfo(bookID); + + if (book.isAvailable()) { + + Record record = new Record(user, book, new Date()); + user.getRecords().add(record); + book.getRecords().add(record); + + recordRepository.save(record); + userRepository.save(user); + + book.setAvailable(false); + + bookRepository.save(book); + + return record; + + } else { + return null; + } + } + + throw new NullPointerException("找不到用户"); + } + + /** + * + * @return java.util.List + * @author ZXY + * @date 2021/11/2 16:07 + **/ + public List getAllBooks() { + + return bookRepository.findAll(); + } + +} diff --git a/bookstore/src/main/java/com/bookstore/service/UserDetailServiceImp.java b/bookstore/src/main/java/com/bookstore/service/UserDetailServiceImp.java new file mode 100644 index 0000000000000000000000000000000000000000..96b91310f479066f9f275b826d81c43d0463f764 --- /dev/null +++ b/bookstore/src/main/java/com/bookstore/service/UserDetailServiceImp.java @@ -0,0 +1,34 @@ +package com.bookstore.service; + +import com.bookstore.entity.User; +import com.bookstore.entity.UserDetailsImp; +import com.bookstore.repository.UserRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.stereotype.Service; + +import java.util.Optional; + +@Service +public class UserDetailServiceImp implements UserDetailsService { + + @Autowired + UserRepository userRepository; + + + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + Optional optionalUser = userRepository.findUserByUsername(username); + if (optionalUser.isPresent()) { + User user = optionalUser.get(); + return new UserDetailsImp(user.getUsername(), user.getPassword(), user.getRoles(), user.isAccountNonExpired(), user.isAccountNonLocked(), user.isEnabled(), user.isCredentialsNonExpired()); + } else { + throw new UsernameNotFoundException("Username not Found!"); + } + } + + +} diff --git a/bookstore/src/main/java/com/bookstore/service/UserService.java b/bookstore/src/main/java/com/bookstore/service/UserService.java new file mode 100644 index 0000000000000000000000000000000000000000..98905ec5f5e12f4d7ef547063a9c04755e52ec41 --- /dev/null +++ b/bookstore/src/main/java/com/bookstore/service/UserService.java @@ -0,0 +1,168 @@ +package com.bookstore.service; + +import com.bookstore.entity.Record; +import com.bookstore.entity.Role; +import com.bookstore.entity.User; +import com.bookstore.repository.BookRepository; +import com.bookstore.repository.RecordRepository; +import com.bookstore.repository.RoleRepository; +import com.bookstore.repository.UserRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +@Service +public class UserService { + + @Autowired + UserRepository userRepository; + + @Autowired + RoleRepository roleRepository; + + @Autowired + BookRepository bookRepository; + + @Autowired + RecordRepository recordRepository; + + @Autowired + BCryptPasswordEncoder bCryptPasswordEncoder; + + /** + * @param user + * @return User + * @author ZXY + * @date 2021/10/23 22:15 + **/ + @Transactional + public User addUser(User user) throws Exception { + + + Optional optionalRole = roleRepository.findRoleByRole("ROLE_CUSTOMER"); + + if (optionalRole.isPresent()) { + + Role role = optionalRole.get(); + ArrayList roles = new ArrayList<>(); + roles.add(role); + user.setRoles(roles); + + } else { + + throw new Exception("找不到相关权限"); + + } + + if (!isUserEmailExist(user)) { + + if (!isUsernameExist(user)) { + + userRepository.save(user); + + return user; + } else { + throw new Exception("email 重复"); + } + + } else { + throw new Exception("username 重复"); + } + } + + /** + * @param username + * @return com.bookstore.entity.User + * @author ZXY + * @date 2021/10/27 16:32 + **/ + public User getUser(String username) { + return userRepository.findUserByUsername(username).get(); + } + + @Transactional + public List getUserRecords(String username) throws NullPointerException{ + Optional optionalUser = userRepository.findUserByUsername(username); + if(optionalUser.isPresent()){ + List records = optionalUser.get().getRecords(); + records.isEmpty(); + return records; + } + throw new NullPointerException("找不到用户"); + } + + + /** + * * @param userid + * + * @param newUser + * @return boolean + * @author ZXY + * @date 2021/10/27 16:32 + **/ + public boolean updateUserInfo(String username, User newUser) { + + Optional optionalUser = userRepository.findUserByUsername(username); + if (optionalUser.isPresent()) { + User user = optionalUser.get(); + + if (newUser.getEmail() != null) { + user.setEmail(newUser.getEmail()); + } + + if (newUser.getNickName() != null) { + user.setEmail(newUser.getNickName()); + } + + if (newUser.getPassword() != null) { + user.setPassword(bCryptPasswordEncoder.encode(newUser.getPassword())); + } + userRepository.save(user); + return true; + } + return false; + } + + /** + * + * @param user + * @return boolean + * @author ZXY + * @date 2021/10/27 16:33 + **/ + public boolean isUserEmailExist(User user) { + + if (userRepository.findUserByEmail(user.getEmail()).isPresent()) return true; + + return false; + } + + /** + * @param user + * @return boolean + * @author ZXY + * @date 2021/10/27 16:33 + **/ + public boolean isUsernameExist(User user) { + + if (userRepository.findUserByUsername(user.getUsername()).isPresent()) return true; + + return false; + } + + /** + * @return java.util.List + * @author ZXY + * @date 2021/10/27 16:34 + **/ + public List getAllUsers() { + return userRepository.findAll(); + } + + +} diff --git a/bookstore/src/main/java/com/bookstore/utils/Code.java b/bookstore/src/main/java/com/bookstore/utils/Code.java new file mode 100644 index 0000000000000000000000000000000000000000..a8c4a7fa20f9682663246009a144203a43de67ac --- /dev/null +++ b/bookstore/src/main/java/com/bookstore/utils/Code.java @@ -0,0 +1,19 @@ +package com.bookstore.utils; + +import com.fasterxml.jackson.annotation.JsonValue; + +public enum Code { + SUCCESS(0), Fail(1); + + private int i; + + Code(int i) { + this.i = i; + } + + @JsonValue + public int getI(){ + return i; + } + +} diff --git a/bookstore/src/main/java/com/bookstore/utils/JWTUtil.java b/bookstore/src/main/java/com/bookstore/utils/JWTUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..1f6e76719a839e08c6aaa671c28b9f1f445e1497 --- /dev/null +++ b/bookstore/src/main/java/com/bookstore/utils/JWTUtil.java @@ -0,0 +1,42 @@ +package com.bookstore.utils; + +import com.auth0.jwt.JWT; +import com.auth0.jwt.JWTVerifier; +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.interfaces.DecodedJWT; + +import java.util.Calendar; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + + +public class JWTUtil { + private static final int TOKEN_EXPIRE_TIME = 60 * 60 * 24; + private static final String SECRET = "BOOKSTORE"; + + + public static String encrypt(String username) { + + + Map map = new HashMap<>(); + map.put("alg", "HS256"); + map.put("typ", "JWT"); + + Calendar calendar = Calendar.getInstance(); + calendar.add(Calendar.SECOND, TOKEN_EXPIRE_TIME); + Date date = calendar.getTime(); + + String token = JWT.create().withHeader(map).withSubject(username) + .withExpiresAt(date).sign(Algorithm.HMAC256(SECRET)); + return token; + } + + public static DecodedJWT verifyToken(String token) { + DecodedJWT decodedJWT; + JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(SECRET)).build(); + decodedJWT = jwtVerifier.verify(token); + return decodedJWT; + } + +} diff --git a/bookstore/src/main/java/com/bookstore/utils/Response.java b/bookstore/src/main/java/com/bookstore/utils/Response.java new file mode 100644 index 0000000000000000000000000000000000000000..740174280d4d84425f1b6a929880aa75c5c751ef --- /dev/null +++ b/bookstore/src/main/java/com/bookstore/utils/Response.java @@ -0,0 +1,37 @@ +package com.bookstore.utils; + +public class Response { + private Code code; + private Object data; + private String msg; + + public Response(Code code, Object data, String msg) { + this.code = code; + this.data = data; + this.msg = msg; + } + + public Code getCode() { + return code; + } + + public void setCode(Code code) { + this.code = code; + } + + public Object getData() { + return data; + } + + public void setData(Object data) { + this.data = data; + } + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } +} diff --git a/bookstore/src/main/java/com/bookstore/utils/ResponseUtil.java b/bookstore/src/main/java/com/bookstore/utils/ResponseUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..2024099fe1e952e317f88aef2707c517a1cf8f0b --- /dev/null +++ b/bookstore/src/main/java/com/bookstore/utils/ResponseUtil.java @@ -0,0 +1,19 @@ +package com.bookstore.utils; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; + +public class ResponseUtil { + + public static void response(HttpServletResponse response,Code code, Object data, String msg) throws IOException { + PrintWriter printWriter = response.getWriter(); + ObjectMapper objectMapper = new ObjectMapper(); + Response content = new Response(code,data,msg); + objectMapper.writeValue(printWriter,content); + } + +} diff --git a/bookstore/src/main/resources/application.properties b/bookstore/src/main/resources/application.properties new file mode 100644 index 0000000000000000000000000000000000000000..9da49582fde7a6d5766f4eb3b93e8bdd1a1b9970 --- /dev/null +++ b/bookstore/src/main/resources/application.properties @@ -0,0 +1,14 @@ +server.port=80 +server.servlet.context-path=/api + +spring.datasource.url=jdbc:mysql://127.0.0.1/bookstore +spring.datasource.username=root +spring.datasource.password=123456 +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver + +spring.jpa.show-sql=true +spring.jpa.hibernate.ddl-auto=update +spring.jpa.open-in-view=false + +server.undertow.max-cookies=0 +server.servlet.session.cookie.max-age=0 \ No newline at end of file diff --git a/bookstore/src/test/java/com/bookstore/BookstoreApplicationTests.java b/bookstore/src/test/java/com/bookstore/BookstoreApplicationTests.java new file mode 100644 index 0000000000000000000000000000000000000000..95060ec7ab6360f539765d51f073fd8fd30161d3 --- /dev/null +++ b/bookstore/src/test/java/com/bookstore/BookstoreApplicationTests.java @@ -0,0 +1,39 @@ +package com.bookstore; + +import com.bookstore.entity.Role; +import com.bookstore.entity.User; +import com.bookstore.repository.RoleRepository; +import com.bookstore.repository.UserRepository; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import java.util.ArrayList; + +@SpringBootTest +class BookstoreApplicationTests { + @Autowired + UserRepository userRepository; + @Autowired + RoleRepository roleRepository; + + @Test + void contextLoads() { +// User user = new User(); +// user.setUsername("test2"); +// user.setPassword(new BCryptPasswordEncoder().encode("222")); +// user.setNonLocked(true); +// user.setNonExpired(true); +// user.setEnable(true); +// user.setCredentialsNonExpired(true); +// Role role = new Role("ROLE_ADMIN"); + + User user = userRepository.findUserByUsername("test2").get(); + Role role = roleRepository.getById("ROLE_ADMIN"); + ArrayList roles = new ArrayList<>(); + roles.add(role); + user.setRoles(roles); + userRepository.save(user); + } + +}