commit c9b686fcf33455f25389960ee9fc27a3da317478 Author: Ray Date: Tue Dec 19 09:54:32 2023 +0800 初步搭建,后面需要细化用户管理,和文件管理 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..549e00a --- /dev/null +++ b/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 0000000..cb28b0e Binary files /dev/null and b/.mvn/wrapper/maven-wrapper.jar differ diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..5f0536e --- /dev/null +++ b/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,2 @@ +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.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/README.md b/README.md new file mode 100644 index 0000000..d08221e --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# 个人网站搭建 diff --git a/mvnw b/mvnw new file mode 100755 index 0000000..66df285 --- /dev/null +++ b/mvnw @@ -0,0 +1,308 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Apache Maven Wrapper startup batch script, version 3.2.0 +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /usr/local/etc/mavenrc ] ; then + . /usr/local/etc/mavenrc + fi + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "$(uname)" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME + else + JAVA_HOME="/Library/Java/Home"; export JAVA_HOME + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=$(java-config --jre-home) + fi +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$JAVA_HOME" ] && + JAVA_HOME=$(cygpath --unix "$JAVA_HOME") + [ -n "$CLASSPATH" ] && + CLASSPATH=$(cygpath --path --unix "$CLASSPATH") +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] && + JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="$(which javac)" + if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=$(which readlink) + if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then + if $darwin ; then + javaHome="$(dirname "\"$javaExecutable\"")" + javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac" + else + javaExecutable="$(readlink -f "\"$javaExecutable\"")" + fi + javaHome="$(dirname "\"$javaExecutable\"")" + javaHome=$(expr "$javaHome" : '\(.*\)/bin') + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=$(cd "$wdir/.." || exit 1; pwd) + fi + # end of workaround + done + printf '%s' "$(cd "$basedir" || exit 1; pwd)" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + # Remove \r in case we run on Windows within Git Bash + # and check out the repository with auto CRLF management + # enabled. Otherwise, we may read lines that are delimited with + # \r\n and produce $'-Xarg\r' rather than -Xarg due to word + # splitting rules. + tr -s '\r\n' ' ' < "$1" + fi +} + +log() { + if [ "$MVNW_VERBOSE" = true ]; then + printf '%s\n' "$1" + fi +} + +BASE_DIR=$(find_maven_basedir "$(dirname "$0")") +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR +log "$MAVEN_PROJECTBASEDIR" + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" +if [ -r "$wrapperJarPath" ]; then + log "Found $wrapperJarPath" +else + log "Couldn't find $wrapperJarPath, downloading it ..." + + if [ -n "$MVNW_REPOURL" ]; then + wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" + else + wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" + fi + while IFS="=" read -r key value; do + # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' ) + safeValue=$(echo "$value" | tr -d '\r') + case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;; + esac + done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" + log "Downloading from: $wrapperUrl" + + if $cygwin; then + wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath") + fi + + if command -v wget > /dev/null; then + log "Found wget ... using wget" + [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet" + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + else + wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + fi + elif command -v curl > /dev/null; then + log "Found curl ... using curl" + [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent" + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" + else + curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" + fi + else + log "Falling back to using Java to download" + javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java" + javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaSource=$(cygpath --path --windows "$javaSource") + javaClass=$(cygpath --path --windows "$javaClass") + fi + if [ -e "$javaSource" ]; then + if [ ! -e "$javaClass" ]; then + log " - Compiling MavenWrapperDownloader.java ..." + ("$JAVA_HOME/bin/javac" "$javaSource") + fi + if [ -e "$javaClass" ]; then + log " - Running MavenWrapperDownloader.java ..." + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath" + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +# If specified, validate the SHA-256 sum of the Maven wrapper jar file +wrapperSha256Sum="" +while IFS="=" read -r key value; do + case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;; + esac +done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" +if [ -n "$wrapperSha256Sum" ]; then + wrapperSha256Result=false + if command -v sha256sum > /dev/null; then + if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then + wrapperSha256Result=true + fi + elif command -v shasum > /dev/null; then + if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then + wrapperSha256Result=true + fi + else + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." + echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties." + exit 1 + fi + if [ $wrapperSha256Result = false ]; then + echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2 + echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2 + echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2 + exit 1 + fi +fi + +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$JAVA_HOME" ] && + JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME") + [ -n "$CLASSPATH" ] && + CLASSPATH=$(cygpath --path --windows "$CLASSPATH") + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR") +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +# shellcheck disable=SC2086 # safe args +exec "$JAVACMD" \ + $MAVEN_OPTS \ + $MAVEN_DEBUG_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/mvnw.cmd b/mvnw.cmd new file mode 100644 index 0000000..95ba6f5 --- /dev/null +++ b/mvnw.cmd @@ -0,0 +1,205 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM https://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.2.0 +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* +if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" + +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %WRAPPER_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file +SET WRAPPER_SHA_256_SUM="" +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B +) +IF NOT %WRAPPER_SHA_256_SUM%=="" ( + powershell -Command "&{"^ + "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^ + "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^ + " Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^ + " Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^ + " Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^ + " exit 1;"^ + "}"^ + "}" + if ERRORLEVEL 1 goto error +) + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% ^ + %JVM_CONFIG_MAVEN_PROPS% ^ + %MAVEN_OPTS% ^ + %MAVEN_DEBUG_OPTS% ^ + -classpath %WRAPPER_JAR% ^ + "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ + %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" +if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%"=="on" pause + +if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% + +cmd /C exit /B %ERROR_CODE% diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..182ce7f --- /dev/null +++ b/pom.xml @@ -0,0 +1,56 @@ + + + + 4.0.0 + + + top.rayc + ray + 0.0.1 + pom + + ray + rayc.top 服务端程序 + + + + ray-dependencies + ray-infrastructure-utility + ray-admin + ray-user + ray-file + + + + 17 + ${java.version} + ${java.version} + UTF-8 + UTF-8 + 3.1.0 + 2.6.8 + + + + + + top.rayc + ray-dependencies + 0.0.1 + pom + import + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/ray-admin/pom.xml b/ray-admin/pom.xml new file mode 100644 index 0000000..3c9f231 --- /dev/null +++ b/ray-admin/pom.xml @@ -0,0 +1,44 @@ + + + 4.0.0 + + + top.rayc + ray + 0.0.1 + ../pom.xml + + + ray-admin + 0.0.1 + jar + ray-admin + ray-admin + + + + + org.springframework.boot + spring-boot-starter-actuator + + + + top.rayc + ray-infrastructure-utility + 0.0.1 + + + top.rayc + ray-user + 0.0.1 + + + top.rayc + ray-file + 0.0.1 + + + + \ No newline at end of file diff --git a/ray-admin/src/main/java/top/rayc/Application.java b/ray-admin/src/main/java/top/rayc/Application.java new file mode 100644 index 0000000..8c705c9 --- /dev/null +++ b/ray-admin/src/main/java/top/rayc/Application.java @@ -0,0 +1,15 @@ +package top.rayc; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + // log.info("**************************************************"); + // log.info("******************** Ray Backend *****************"); + // log.info("**************************************************"); + System.out.println("Ray Backend"); + } +} \ No newline at end of file diff --git a/ray-admin/src/main/resources/application.yml b/ray-admin/src/main/resources/application.yml new file mode 100644 index 0000000..16f308a --- /dev/null +++ b/ray-admin/src/main/resources/application.yml @@ -0,0 +1,80 @@ +server: + port: 8091 + +management: + endpoints: + web: + exposure: + include: "*" + endpoint: + health: + show-details: always + +spring: + application: + name: ray + + servlet: + multipart: + enabled: true + max-file-size: 50MB + max-request-size: 100MB + + jackson: + date-format: yyyy-MM-dd HH:mm:ss + time-zone: GMT+8 + serialization: + FAIL_ON_EMPTY_BEANS: false + + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://mysql.rayc.top:3308/ray-dev?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true + username: root + password: "#Ray970217" + type: com.alibaba.druid.pool.DruidDataSource + druid: + initial-size: 3 + min-idle: 3 + max-active: 40 + max-wait: 6000 + +mybatis-plus: + mapper-locations: classpath:mapperXml/*.xml + configuration: + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl + +jwt: + signing: + key: .ymLTU8rq83j4fmJZj60wh4OrMNuntIj4fmJ1refreywscascsa + +file: + root: + path: /home/ray/data/ray + +# springdoc-openapi +springdoc: + swagger-ui: + path: /swagger-ui.html + tags-sorter: alpha + operations-sorter: alpha + api-docs: + path: /v3/api-docs + group-configs: + - group: "default" + paths-to-match: "/**" + packages-to-scan: + - top.rayc.file.controller + - top.rayc.user.controller + +# knife4j +knife4j: + enable: true + setting: + language: zh_cn + +--- +#spring: +# boot: +# admin: +# client: +# url: http://localhost:9000 diff --git a/ray-dependencies/pom.xml b/ray-dependencies/pom.xml new file mode 100644 index 0000000..076ead2 --- /dev/null +++ b/ray-dependencies/pom.xml @@ -0,0 +1,140 @@ + + + 4.0.0 + + top.rayc + ray-dependencies + 0.0.1 + pom + ray-dependencies + ray-backend 项目依赖 + + + 17 + 3.1.2 + + 2.0.5 + + 5.8.20 + 1.4.1.Final + + 3.5.3.1 + 3.5.2 + + 2.6.0 + + + + + + + org.springframework.boot + spring-boot-dependencies + ${spring.boot.version} + pom + import + + + + org.springframework.boot + spring-boot-configuration-processor + ${spring.boot.version} + + + + io.jsonwebtoken + jjwt-impl + 0.11.1 + + + + io.jsonwebtoken + jjwt-jackson + 0.11.1 + + + + jakarta.xml.bind + jakarta.xml.bind-api + + + + org.glassfish.jaxb + jaxb-runtime + + + + + mysql + mysql-connector-java + 8.0.29 + + + + com.alibaba + druid-spring-boot-starter + 1.2.8 + + + + com.baomidou + mybatis-plus-boot-starter + ${mybatis-plus.version} + + + com.baomidou + mybatis-plus-boot-starter-test + test + 3.5.2 + + + com.baomidou + mybatis-plus-generator + ${mybatis-plus-generator.version} + + + + org.apache.commons + commons-lang3 + 3.12.0 + + + + org.apache.tika + tika-core + ${tika.version} + + + + org.mapstruct + mapstruct + ${mapstruct.version} + + + org.mapstruct + mapstruct-jdk8 + ${mapstruct.version} + + + org.mapstruct + mapstruct-processor + ${mapstruct.version} + + + + cn.hutool + hutool-all + ${hutool.version} + + + + com.alibaba + fastjson + ${fastjson.version} + + + + + \ No newline at end of file diff --git a/ray-file/pom.xml b/ray-file/pom.xml new file mode 100644 index 0000000..b383f7d --- /dev/null +++ b/ray-file/pom.xml @@ -0,0 +1,44 @@ + + + 4.0.0 + + + top.rayc + ray + 0.0.1 + ../pom.xml + + + ray-file + jar + ray-file + + + + top.rayc + ray-infrastructure-utility + 0.0.1 + + + + top.rayc + ray-user + 0.0.1 + + + + org.projectlombok + lombok + true + + + + org.springframework.boot + spring-boot-starter-test + test + + + + \ No newline at end of file diff --git a/ray-file/src/main/java/top/rayc/file/controller/FileController.java b/ray-file/src/main/java/top/rayc/file/controller/FileController.java new file mode 100644 index 0000000..4d9bf69 --- /dev/null +++ b/ray-file/src/main/java/top/rayc/file/controller/FileController.java @@ -0,0 +1,5 @@ +package top.rayc.file.controller; + +public class FileController { + +} diff --git a/ray-file/src/main/java/top/rayc/file/controller/vo/req/FileChunkDownloadReq.java b/ray-file/src/main/java/top/rayc/file/controller/vo/req/FileChunkDownloadReq.java new file mode 100644 index 0000000..2533544 --- /dev/null +++ b/ray-file/src/main/java/top/rayc/file/controller/vo/req/FileChunkDownloadReq.java @@ -0,0 +1,10 @@ +package top.rayc.file.controller.vo.req; + +import lombok.Data; + +@Data +public class FileChunkDownloadReq { + private String hash; + private Integer chunkIdx; + private Long chunkSize; +} diff --git a/ray-file/src/main/java/top/rayc/file/controller/vo/req/FileChunkMergeReq.java b/ray-file/src/main/java/top/rayc/file/controller/vo/req/FileChunkMergeReq.java new file mode 100644 index 0000000..545c5c0 --- /dev/null +++ b/ray-file/src/main/java/top/rayc/file/controller/vo/req/FileChunkMergeReq.java @@ -0,0 +1,10 @@ +package top.rayc.file.controller.vo.req; + +import lombok.Data; + +@Data +public class FileChunkMergeReq { + private String filename; + private String hash; + private String extension; +} diff --git a/ray-file/src/main/java/top/rayc/file/controller/vo/req/FileChunkUploadReq.java b/ray-file/src/main/java/top/rayc/file/controller/vo/req/FileChunkUploadReq.java new file mode 100644 index 0000000..9525298 --- /dev/null +++ b/ray-file/src/main/java/top/rayc/file/controller/vo/req/FileChunkUploadReq.java @@ -0,0 +1,17 @@ +package top.rayc.file.controller.vo.req; + +import org.springframework.web.multipart.MultipartFile; + +import io.micrometer.common.lang.NonNull; +import lombok.Data; + +@Data +public class FileChunkUploadReq { + private String filename; + private String hash; + @NonNull + private MultipartFile chunk; + private Long chunkSize; + private Integer chunkIdx; + private Integer chunkCount; +} diff --git a/ray-file/src/main/java/top/rayc/file/controller/vo/req/FileUploadReq.java b/ray-file/src/main/java/top/rayc/file/controller/vo/req/FileUploadReq.java new file mode 100644 index 0000000..8c8c95d --- /dev/null +++ b/ray-file/src/main/java/top/rayc/file/controller/vo/req/FileUploadReq.java @@ -0,0 +1,14 @@ +package top.rayc.file.controller.vo.req; + +import org.springframework.web.multipart.MultipartFile; + +import lombok.Data; + +@Data +public class FileUploadReq { + private String filename; + private MultipartFile file; + private String hash; + private Long size; + private String extension; +} diff --git a/ray-file/src/main/java/top/rayc/file/controller/vo/resp/FileResp.java b/ray-file/src/main/java/top/rayc/file/controller/vo/resp/FileResp.java new file mode 100644 index 0000000..af8c5f8 --- /dev/null +++ b/ray-file/src/main/java/top/rayc/file/controller/vo/resp/FileResp.java @@ -0,0 +1,23 @@ +package top.rayc.file.controller.vo.resp; + +import java.time.LocalDateTime; + +import lombok.Data; + +@Data +public class FileResp { + private Long id; + + private String hash; + private String filename; + private String extension; + private String realFilename; + private Long size; + private String storePath; + private Boolean staticAccess; + private String staticUri; + private String contentType; + private Boolean isDeleted; + private Long uploadBy; + private LocalDateTime uploadAt; +} diff --git a/ray-file/src/main/java/top/rayc/file/converter/FileConverter.java b/ray-file/src/main/java/top/rayc/file/converter/FileConverter.java new file mode 100644 index 0000000..e8bfdd5 --- /dev/null +++ b/ray-file/src/main/java/top/rayc/file/converter/FileConverter.java @@ -0,0 +1,21 @@ +package top.rayc.file.converter; + +import java.util.List; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import top.rayc.file.controller.vo.req.FileUploadReq; +import top.rayc.file.controller.vo.resp.FileResp; +import top.rayc.file.entity.File; + +@Mapper +public interface FileConverter { + FileConverter INSTANCE = Mappers.getMapper(FileConverter.class); + + File convertFromFileUploadReq(FileUploadReq fileUpload); + + FileResp convertToResp(File file); + + List convertToResps(List files); +} diff --git a/ray-file/src/main/java/top/rayc/file/entity/File.java b/ray-file/src/main/java/top/rayc/file/entity/File.java new file mode 100644 index 0000000..98b675e --- /dev/null +++ b/ray-file/src/main/java/top/rayc/file/entity/File.java @@ -0,0 +1,29 @@ +package top.rayc.file.entity; + +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import lombok.Data; + +@Data +@TableName("file") +public class File { + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private String hash; + private String filename; + private String extension; + private String realFilename; + private Long size; + private String storePath; + private Boolean staticAccess; + private String staticUri; + private String contentType; + private Boolean isDeleted; + private Long uploadBy; + private LocalDateTime uploadAt; +} diff --git a/ray-file/src/main/java/top/rayc/file/entity/FileChunk.java b/ray-file/src/main/java/top/rayc/file/entity/FileChunk.java new file mode 100644 index 0000000..0b5a855 --- /dev/null +++ b/ray-file/src/main/java/top/rayc/file/entity/FileChunk.java @@ -0,0 +1,26 @@ +package top.rayc.file.entity; + +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import lombok.Data; + +@Data +@TableName("file_chunk") +public class FileChunk { + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private String hash; + private String filename; + private String chunkPath; + private Integer chunkIdx; + private Integer chunkCount; + private Long chunkSize; + private Boolean isMerged; + private Long uploadBy; + private LocalDateTime uploadAt; +} diff --git a/ray-file/src/main/java/top/rayc/file/mapper/FileChunkMapper.java b/ray-file/src/main/java/top/rayc/file/mapper/FileChunkMapper.java new file mode 100644 index 0000000..f368c85 --- /dev/null +++ b/ray-file/src/main/java/top/rayc/file/mapper/FileChunkMapper.java @@ -0,0 +1,11 @@ +package top.rayc.file.mapper; + +import org.apache.ibatis.annotations.Mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +import top.rayc.file.entity.FileChunk; + +@Mapper +public interface FileChunkMapper extends BaseMapper { +} diff --git a/ray-file/src/main/java/top/rayc/file/mapper/FileMapper.java b/ray-file/src/main/java/top/rayc/file/mapper/FileMapper.java new file mode 100644 index 0000000..5f6723f --- /dev/null +++ b/ray-file/src/main/java/top/rayc/file/mapper/FileMapper.java @@ -0,0 +1,11 @@ +package top.rayc.file.mapper; + +import org.apache.ibatis.annotations.Mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +import top.rayc.file.entity.File; + +@Mapper +public interface FileMapper extends BaseMapper { +} diff --git a/ray-file/src/main/java/top/rayc/file/service/IFileService.java b/ray-file/src/main/java/top/rayc/file/service/IFileService.java new file mode 100644 index 0000000..f7ae263 --- /dev/null +++ b/ray-file/src/main/java/top/rayc/file/service/IFileService.java @@ -0,0 +1,27 @@ +package top.rayc.file.service; + +import org.springframework.http.ResponseEntity; + +import jakarta.servlet.http.HttpServletResponse; +import top.rayc.file.controller.vo.req.FileChunkMergeReq; +import top.rayc.file.controller.vo.req.FileChunkUploadReq; +import top.rayc.file.controller.vo.req.FileUploadReq; +import top.rayc.file.controller.vo.resp.FileResp; +import top.rayc.utility.page.PageObject; +import top.rayc.utility.vo.BaseResult; + +public interface IFileService { + ResponseEntity> uploadFileSingle(FileUploadReq fileUpload); + + ResponseEntity> uploadFileChunk(FileChunkUploadReq fileChunkUpload); + + ResponseEntity> mergeFileChunk(FileChunkMergeReq fileChunkMergeReq); + + ResponseEntity>> pageFileInfo(Long pageIdx, Long pageSize); + + ResponseEntity> changeFileStaticAccessStatus(Long id, Boolean newStatus); + + ResponseEntity downloadFile(String hash, HttpServletResponse response); + + ResponseEntity downloadFileChunk(String hash, Integer chunkIdx, Integer chunkSize, HttpServletResponse response); +} diff --git a/ray-file/src/main/java/top/rayc/file/service/impl/FileService.java b/ray-file/src/main/java/top/rayc/file/service/impl/FileService.java new file mode 100644 index 0000000..5f9d176 --- /dev/null +++ b/ray-file/src/main/java/top/rayc/file/service/impl/FileService.java @@ -0,0 +1,92 @@ +package top.rayc.file.service.impl; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; + +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import top.rayc.file.controller.vo.req.FileChunkMergeReq; +import top.rayc.file.controller.vo.req.FileChunkUploadReq; +import top.rayc.file.controller.vo.req.FileUploadReq; +import top.rayc.file.controller.vo.resp.FileResp; +import top.rayc.file.entity.File; +import top.rayc.file.mapper.FileChunkMapper; +import top.rayc.file.mapper.FileMapper; +import top.rayc.file.service.IFileService; +import top.rayc.user.utils.UserHelper; +import top.rayc.utility.page.PageObject; +import top.rayc.utility.utils.FileUtil; +import top.rayc.utility.vo.BaseResult; + +@Slf4j +@Service +public class FileService extends ServiceImpl implements IFileService { + + @Value("${file.root.path}") + private String rootPath; + + private final String DEFAULT_RELATIVE_PATH = "default/"; + private final String DEFAULT_CHUNK_RELATIVE_PATH = "default.chunk/"; + + + @Autowired + private FileChunkMapper fileChunkMapper; + + @Autowired + private UserHelper userHelper; + + @Override + public ResponseEntity> uploadFileSingle(FileUploadReq fileUpload) { + log.info("开始处理单文件上传"); + String storeName = fileUpload.getHash() + "." + fileUpload.getExtension(); + String contentType = ""; + try { + contentType = FileUtil.contentType(fileUpload.getFile().getInputStream()); + } catch (Exception e) { + log.error(e.getMessage(), e); + } + // String parentPath = "" + throw new UnsupportedOperationException("Unimplemented method 'uploadFileSingle'"); + } + + @Override + public ResponseEntity> uploadFileChunk(FileChunkUploadReq fileChunkUpload) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'uploadFileChunk'"); + } + + @Override + public ResponseEntity> mergeFileChunk(FileChunkMergeReq fileChunkMergeReq) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'mergeFileChunk'"); + } + + @Override + public ResponseEntity>> pageFileInfo(Long pageIdx, Long pageSize) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'pageFileInfo'"); + } + + @Override + public ResponseEntity> changeFileStaticAccessStatus(Long id, Boolean newStatus) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'changeFileStaticAccessStatus'"); + } + + @Override + public ResponseEntity downloadFile(String hash, HttpServletResponse response) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'downloadFile'"); + } + + @Override + public ResponseEntity downloadFileChunk(String hash, Integer chunkIdx, Integer chunkSize, + HttpServletResponse response) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'downloadFileChunk'"); + } +} diff --git a/ray-infrastructure-utility/pom.xml b/ray-infrastructure-utility/pom.xml new file mode 100644 index 0000000..f267354 --- /dev/null +++ b/ray-infrastructure-utility/pom.xml @@ -0,0 +1,154 @@ + + + 4.0.0 + + + top.rayc + ray + 0.0.1 + ../pom.xml + + + ray-infrastructure-utility + jar + ${project.artifactId} + + + + org.springframework.boot + spring-boot-starter-web + + + + mysql + mysql-connector-java + 8.0.29 + + + + com.alibaba + druid-spring-boot-starter + + + + com.baomidou + mybatis-plus-boot-starter + + + + com.baomidou + mybatis-plus-boot-starter-test + test + + + + + com.baomidou + mybatis-plus-generator + 3.5.2 + test + + + + org.mapstruct + mapstruct + + + org.mapstruct + mapstruct-jdk8 + + + org.mapstruct + mapstruct-processor + + + + org.springframework.boot + spring-boot-starter-aop + + + + org.apache.commons + commons-lang3 + + + + org.springframework.boot + spring-boot-starter-validation + + + + org.springframework.boot + spring-boot-test + + + + + org.junit.jupiter + junit-jupiter-api + + + + + org.springframework.boot + spring-boot-devtools + runtime + true + + + + org.projectlombok + lombok + true + + + + cn.hutool + hutool-all + + + + com.alibaba + fastjson + + + + org.springframework.data + spring-data-redis + + + + org.springframework.boot + spring-boot-starter-security + + + + io.jsonwebtoken + jjwt-api + 0.11.1 + + + + io.jsonwebtoken + jjwt-impl + 0.11.1 + runtime + + + + io.jsonwebtoken + jjwt-jackson + 0.11.1 + runtime + + + + org.apache.tika + tika-core + + + + + \ No newline at end of file diff --git a/ray-infrastructure-utility/src/main/java/top/rayc/utility/aop/GlobalExceptionHandler.java b/ray-infrastructure-utility/src/main/java/top/rayc/utility/aop/GlobalExceptionHandler.java new file mode 100644 index 0000000..252d783 --- /dev/null +++ b/ray-infrastructure-utility/src/main/java/top/rayc/utility/aop/GlobalExceptionHandler.java @@ -0,0 +1,81 @@ +package top.rayc.utility.aop; + +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.web.HttpRequestMethodNotSupportedException; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import jakarta.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +import top.rayc.utility.exception.BizException; +import top.rayc.utility.vo.BaseResult; + +@Slf4j +@RestControllerAdvice +public class GlobalExceptionHandler { + /** + * 请求体为空处理 + * + * @param req + * @param e + * @return + */ + @ExceptionHandler(value = HttpMessageNotReadableException.class) + public BaseResult exceptionHandler(HttpServletRequest req, HttpMessageNotReadableException e) { +// log.error("请求体request body不能为空:", e); + return BaseResult.error("请求体request body不能为空!"); + } + + /** + * 参数校验异常处理 + * + * @param req + * @param e + * @return + */ + @ExceptionHandler(value = MethodArgumentNotValidException.class) + public BaseResult exceptionHandler(HttpServletRequest req, MethodArgumentNotValidException e) { +// log.error("参数校验异常:", e); + return BaseResult.error(e.getBindingResult().getFieldError().getDefaultMessage()); + } + + /** + * 请求方法不支持异常处理 + * + * @param req + * @param e + * @return + */ + @ExceptionHandler(value = HttpRequestMethodNotSupportedException.class) + public BaseResult exceptionHandler(HttpServletRequest req, HttpRequestMethodNotSupportedException e) { +// log.error("参数校验异常:", e); + return BaseResult.error(e.getMessage()); + } + + /** + * 业务异常处理 + * + * @param req + * @param e + * @return + */ + @ExceptionHandler(value = BizException.class) + public BaseResult exceptionHandler(HttpServletRequest req, BizException e) { + log.error("业务异常:", e); + return BaseResult.error(e.findMessageCode().getStatus(), e.getMessage()); + } + + /** + * 未知异常处理 + * + * @param req + * @param e + * @return + */ + @ExceptionHandler(value = Exception.class) + public BaseResult exceptionHandler(HttpServletRequest req, Exception e) { + log.error("系统异常:", e); + return BaseResult.error("系统内部异常!"); + } +} diff --git a/ray-infrastructure-utility/src/main/java/top/rayc/utility/aop/LogAspect.java b/ray-infrastructure-utility/src/main/java/top/rayc/utility/aop/LogAspect.java new file mode 100644 index 0000000..4b89c4e --- /dev/null +++ b/ray-infrastructure-utility/src/main/java/top/rayc/utility/aop/LogAspect.java @@ -0,0 +1,48 @@ +package top.rayc.utility.aop; + +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.slf4j.MDC; +import org.springframework.stereotype.Component; + +import com.alibaba.fastjson.JSON; + +import cn.hutool.core.lang.UUID; +import io.micrometer.common.util.StringUtils; +import lombok.extern.slf4j.Slf4j; +import top.rayc.utility.vo.BaseReq; + +@Aspect +@Component +@Slf4j +public class LogAspect { + private static final String TRACE_LOG_ID = "traceId"; + + @Pointcut("execution(* top.rayc.*.impl.*.*(..))") + public void logPointCut() {} + + public Object doAround(ProceedingJoinPoint pjp) throws Throwable { + String traceId = MDC.get(TRACE_LOG_ID); + if (StringUtils.isBlank(traceId)) { + if (pjp.getArgs().length > 0 && pjp.getArgs()[0] instanceof BaseReq) { + BaseReq req = (BaseReq) pjp.getArgs()[0]; + if (StringUtils.isNotBlank(req.getTraceId())) { + traceId = req.getTraceId(); + } + } + if (StringUtils.isNotBlank(traceId)) { + MDC.put(TRACE_LOG_ID, traceId); + } else { + MDC.put(TRACE_LOG_ID, UUID.randomUUID().toString()); + } + } + + Long startTime = System.currentTimeMillis(); + log.info("入参: {}", JSON.toJSONString(pjp.getArgs())); + + Object result = pjp.proceed(); + log.info("耗时: {}ms; 出参: {}", System.currentTimeMillis() - startTime, JSON.toJSONString(result)); + return result; + } +} diff --git a/ray-infrastructure-utility/src/main/java/top/rayc/utility/event/DomainEvent.java b/ray-infrastructure-utility/src/main/java/top/rayc/utility/event/DomainEvent.java new file mode 100644 index 0000000..a03427f --- /dev/null +++ b/ray-infrastructure-utility/src/main/java/top/rayc/utility/event/DomainEvent.java @@ -0,0 +1,23 @@ +package top.rayc.utility.event; + +import java.util.Date; +import java.util.UUID; + +public abstract class DomainEvent { + private String eventId; + private Date eventTime; + + public DomainEvent() { + this.eventId = "Event" + UUID.randomUUID().toString().toUpperCase(); + this.eventTime = new Date(); + } + + public String getEventId() { + return eventId; + } + + public Date getEventTime() { + return eventTime; + } + +} diff --git a/ray-infrastructure-utility/src/main/java/top/rayc/utility/event/HealthEvent.java b/ray-infrastructure-utility/src/main/java/top/rayc/utility/event/HealthEvent.java new file mode 100644 index 0000000..544a30c --- /dev/null +++ b/ray-infrastructure-utility/src/main/java/top/rayc/utility/event/HealthEvent.java @@ -0,0 +1,4 @@ +package top.rayc.utility.event; + +public class HealthEvent extends DomainEvent { +} diff --git a/ray-infrastructure-utility/src/main/java/top/rayc/utility/exception/BizException.java b/ray-infrastructure-utility/src/main/java/top/rayc/utility/exception/BizException.java new file mode 100644 index 0000000..ba921d9 --- /dev/null +++ b/ray-infrastructure-utility/src/main/java/top/rayc/utility/exception/BizException.java @@ -0,0 +1,34 @@ +package top.rayc.utility.exception; + +public class BizException extends RuntimeException implements ExceptionMessage { + /** + * 错误信息 + */ + private final MessageCode messageCode; + + public BizException(MessageCode messageCode) { + super(messageCode.getMessage()); + this.messageCode = messageCode; + + } + + public BizException(MessageCode messageCode, Throwable cause) { + super(messageCode.getMessage(), cause); + this.messageCode = messageCode; + } + + public BizException(MessageCode messageCode, String... sub) { + super(messageCode.getSubMsg(sub)); + this.messageCode = messageCode; + } + + public BizException(MessageCode messageCode, Throwable cause, String... sub) { + super(messageCode.getSubMsg(sub), cause); + this.messageCode = messageCode; + } + + @Override + public MessageCode findMessageCode() { + return this.messageCode; + } +} diff --git a/ray-infrastructure-utility/src/main/java/top/rayc/utility/exception/ExceptionMessage.java b/ray-infrastructure-utility/src/main/java/top/rayc/utility/exception/ExceptionMessage.java new file mode 100644 index 0000000..90b65db --- /dev/null +++ b/ray-infrastructure-utility/src/main/java/top/rayc/utility/exception/ExceptionMessage.java @@ -0,0 +1,5 @@ +package top.rayc.utility.exception; + +public interface ExceptionMessage { + public MessageCode findMessageCode(); +} diff --git a/ray-infrastructure-utility/src/main/java/top/rayc/utility/exception/GlobalExceptionCode.java b/ray-infrastructure-utility/src/main/java/top/rayc/utility/exception/GlobalExceptionCode.java new file mode 100644 index 0000000..119bc03 --- /dev/null +++ b/ray-infrastructure-utility/src/main/java/top/rayc/utility/exception/GlobalExceptionCode.java @@ -0,0 +1,5 @@ +package top.rayc.utility.exception; + +public interface GlobalExceptionCode { + int NOT_FOUND = 10001; +} diff --git a/ray-infrastructure-utility/src/main/java/top/rayc/utility/exception/MessageCode.java b/ray-infrastructure-utility/src/main/java/top/rayc/utility/exception/MessageCode.java new file mode 100644 index 0000000..eb06f91 --- /dev/null +++ b/ray-infrastructure-utility/src/main/java/top/rayc/utility/exception/MessageCode.java @@ -0,0 +1,74 @@ +package top.rayc.utility.exception; + +import java.text.MessageFormat; +import java.util.Arrays; + +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Data +public class MessageCode { + + private Integer status; + private String message; + + public Integer getStatus() { return this.status; } + + public void setStatus(Integer status) { this.status = status; } + + public String getMessage() { return this.message; } + + public void setMessage(String message) { this.message = message; } + + private MessageCode(Integer code, String msg) { + this.status = code; + this.message = msg; + } + + public static MessageCode build(Integer code, String msg) { + return new MessageCode(code, msg); + } + + + + public static MessageCode SUCCESS = MessageCode.build(200, "ok"); + public static MessageCode UN_KNOWN = MessageCode.build(200, ""); + public static MessageCode SYSTEM_ERROR = MessageCode.build(200, "systemError"); + public static MessageCode COMPONENT_ERROR = MessageCode.build(200, "componentError"); + public static MessageCode RUNTIME_ERROR = MessageCode.build(200, "runtimeError"); + public static MessageCode REMOTE_ERROR = MessageCode.build(200, "callRemoteError"); + public static MessageCode CHECK_ERROR = MessageCode.build(200, "校验失败:{0}"); + + public String getSubMsg(String[] sub) { + if (this.message == null) { + return ""; + } + if (sub == null || sub.length == 0) { + return this.message; + } + String[] subArr = Arrays.stream(sub) + .map(item -> { + if (item.isEmpty()) { + return ""; + } else { + return item; + } + }) + .toArray(String[]::new); + + try { + return MessageFormat.format(this.message, subArr); + } catch (Exception e) { + log.error(e.getMessage(), e); + return this.getMessage(); + } + } + + public static org.slf4j.Logger getLog() { + return log; + } + + + +} diff --git a/ray-infrastructure-utility/src/main/java/top/rayc/utility/id/DistributedId.java b/ray-infrastructure-utility/src/main/java/top/rayc/utility/id/DistributedId.java new file mode 100644 index 0000000..259888d --- /dev/null +++ b/ray-infrastructure-utility/src/main/java/top/rayc/utility/id/DistributedId.java @@ -0,0 +1,21 @@ +package top.rayc.utility.id; + +import cn.hutool.core.util.IdUtil; + +public class DistributedId { + + private static DistributedId instance = new DistributedId(); + + public String getFastSimpleUUID(){ + return IdUtil.fastSimpleUUID(); + } + + public Long getSnowflake(long workerId, long datacenterId){ + return IdUtil.createSnowflake(workerId, datacenterId).nextId(); + } + + public static DistributedId getInstance(){ + return instance; + } + +} diff --git a/ray-infrastructure-utility/src/main/java/top/rayc/utility/page/PageObject.java b/ray-infrastructure-utility/src/main/java/top/rayc/utility/page/PageObject.java new file mode 100644 index 0000000..ba280d5 --- /dev/null +++ b/ray-infrastructure-utility/src/main/java/top/rayc/utility/page/PageObject.java @@ -0,0 +1,29 @@ +package top.rayc.utility.page; + +import java.util.List; + +import lombok.Data; +import lombok.ToString; +import lombok.experimental.Accessors; + +@Data +@ToString +@Accessors(chain = true) +public class PageObject { + + private Long total; + + private Long pageIdx; + + private Long pageSize; + + private List list; + + public void buildPage(List list, Long total, Long pageIdx, Long pageSize) { + this.list = list; + this.total = total; + this.pageIdx = pageIdx; + this.pageSize = pageSize; + } + +} diff --git a/ray-infrastructure-utility/src/main/java/top/rayc/utility/security/authentication/UsernamePasswordAuthentication.java b/ray-infrastructure-utility/src/main/java/top/rayc/utility/security/authentication/UsernamePasswordAuthentication.java new file mode 100644 index 0000000..5a284d6 --- /dev/null +++ b/ray-infrastructure-utility/src/main/java/top/rayc/utility/security/authentication/UsernamePasswordAuthentication.java @@ -0,0 +1,18 @@ +package top.rayc.utility.security.authentication; + +import java.util.Collection; + +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.GrantedAuthority; + +public class UsernamePasswordAuthentication extends UsernamePasswordAuthenticationToken { + + public UsernamePasswordAuthentication( + Object principal, + Object credentials, + Collection authorities + ) { + super(principal, credentials, authorities); + } + +} diff --git a/ray-infrastructure-utility/src/main/java/top/rayc/utility/security/authentication/filter/JwtAuthenticationFilter.java b/ray-infrastructure-utility/src/main/java/top/rayc/utility/security/authentication/filter/JwtAuthenticationFilter.java new file mode 100644 index 0000000..2bfefd7 --- /dev/null +++ b/ray-infrastructure-utility/src/main/java/top/rayc/utility/security/authentication/filter/JwtAuthenticationFilter.java @@ -0,0 +1,64 @@ +package top.rayc.utility.security.authentication.filter; + +import java.io.IOException; +import java.util.List; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; + +import ch.qos.logback.core.subst.Token; +import io.jsonwebtoken.Claims; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import top.rayc.utility.security.authentication.UsernamePasswordAuthentication; +import top.rayc.utility.utils.JwtTokenUtils; + +// @Component +@Slf4j +public class JwtAuthenticationFilter extends OncePerRequestFilter { + + private static final String TOKEN_HEADER_KEY = "Authorization"; + private static final String LOGIN_PATH = "/login"; + private static final String AUTHORIZATION_PREFIX = "Bearer "; + + @Value("${jwt.signing.key:ymLTU8rq83j4fmJZj60wh4OrMNuntIj4fmJ}") + private String jwtSigningKey; + + @Override + protected void doFilterInternal( + HttpServletRequest request, + HttpServletResponse response, + FilterChain filterChain + ) throws ServletException, IOException { + Claims claims = JwtTokenUtils.getClaimsFromToken(request.getHeader(TOKEN_HEADER_KEY).substring(7), jwtSigningKey); + if (claims != null) { + String username = claims.getSubject(); + @SuppressWarnings("unchecked") + List authorities = ((List)claims.get("role", List.class)) + .stream() + .map(SimpleGrantedAuthority::new) + .toList(); + UsernamePasswordAuthentication auth = new UsernamePasswordAuthentication(username, null, authorities); + SecurityContextHolder.getContext().setAuthentication(auth); + } + filterChain.doFilter(request, response); + } + + @Override + protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException { + String bearerToken = request.getHeader(TOKEN_HEADER_KEY); + if (LOGIN_PATH.equals(request.getServletPath())) { + return true; + } + if (bearerToken.isBlank() || bearerToken.isEmpty() || !bearerToken.startsWith(AUTHORIZATION_PREFIX)) { + return true; + } + return !JwtTokenUtils.validateToken(bearerToken.substring(7), jwtSigningKey); + } +} diff --git a/ray-infrastructure-utility/src/main/java/top/rayc/utility/security/config/CommonSecurityConfig.java b/ray-infrastructure-utility/src/main/java/top/rayc/utility/security/config/CommonSecurityConfig.java new file mode 100644 index 0000000..541da32 --- /dev/null +++ b/ray-infrastructure-utility/src/main/java/top/rayc/utility/security/config/CommonSecurityConfig.java @@ -0,0 +1,16 @@ +package top.rayc.utility.security.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; + +@Configuration +public class CommonSecurityConfig { + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } + +} diff --git a/ray-infrastructure-utility/src/main/java/top/rayc/utility/utils/FileUtil.java b/ray-infrastructure-utility/src/main/java/top/rayc/utility/utils/FileUtil.java new file mode 100644 index 0000000..45c1d08 --- /dev/null +++ b/ray-infrastructure-utility/src/main/java/top/rayc/utility/utils/FileUtil.java @@ -0,0 +1,25 @@ +package top.rayc.utility.utils; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; + +import org.apache.tika.Tika; + +public class FileUtil { + + public static String contentType(File file) throws IOException { + return new Tika().detect(file); + } + + public static String contentType(InputStream stream) throws IOException { + return new Tika().detect(stream); + } + + public static void delete(Path path) throws IOException { + Files.delete(path); + } + +} diff --git a/ray-infrastructure-utility/src/main/java/top/rayc/utility/utils/JwtTokenUtils.java b/ray-infrastructure-utility/src/main/java/top/rayc/utility/utils/JwtTokenUtils.java new file mode 100644 index 0000000..22e2927 --- /dev/null +++ b/ray-infrastructure-utility/src/main/java/top/rayc/utility/utils/JwtTokenUtils.java @@ -0,0 +1,72 @@ +package top.rayc.utility.utils; + +import java.nio.charset.StandardCharsets; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.util.Date; + +import javax.crypto.SecretKey; + +import org.springframework.security.core.Authentication; + +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import io.jsonwebtoken.security.Keys; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class JwtTokenUtils { + + public static String generateJwtToken( + String jwtSigningKey, + Authentication authentication, + Long jwtDuration + ) { + Long signAt = System.currentTimeMillis(); + Long expireAt = signAt + jwtDuration; + + log.error("jwtDuration: {} signAt: {} expireAt: {}", + jwtDuration, + LocalDateTime.ofInstant(Instant.ofEpochMilli(signAt), ZoneId.systemDefault()), + LocalDateTime.ofInstant(Instant.ofEpochMilli(expireAt), ZoneId.systemDefault()) + ); + + Claims claims = Jwts.claims(); + claims.put("role", authentication.getAuthorities().stream().map(item -> item.getAuthority()).toList()); + claims.setSubject((String) authentication.getPrincipal()); + claims.setIssuedAt(new Date(signAt)); + claims.setExpiration(new Date(expireAt)); + + SecretKey key = Keys.hmacShaKeyFor(jwtSigningKey.getBytes()); + + return Jwts.builder() + .signWith(key, SignatureAlgorithm.HS256) + .setClaims(claims) + .compact(); + } + + public static Claims getClaimsFromToken(String token, String jwtSigningKey) { + try { + SecretKey key = Keys.hmacShaKeyFor(jwtSigningKey.getBytes()); + return Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token).getBody(); + } catch (Exception e) { + log.error(e.getMessage(), e); + return null; + } + } + + public static Boolean validateToken(String token, String jwtSigningKey) { + Claims claims = getClaimsFromToken(token, jwtSigningKey); + log.info("claims: {} ; expire: {} ; now: {}", + claims, + claims.getExpiration().getTime(), + System.currentTimeMillis()); + if (claims == null || claims.getExpiration() == null) { + return false; + } + return claims.getExpiration().after(new Date()); + } + +} diff --git a/ray-infrastructure-utility/src/main/java/top/rayc/utility/utils/StringUtils.java b/ray-infrastructure-utility/src/main/java/top/rayc/utility/utils/StringUtils.java new file mode 100644 index 0000000..59f51ca --- /dev/null +++ b/ray-infrastructure-utility/src/main/java/top/rayc/utility/utils/StringUtils.java @@ -0,0 +1,149 @@ +package top.rayc.utility.utils; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; + +public class StringUtils extends org.springframework.util.StringUtils { + + private static Charset encoding = StandardCharsets.UTF_8; + + public static final String EMPTY = ""; + + /** + * 项目 字符串 处理编码 + * + * @param charset default UTF-8 + * @see StandardCharsets + */ + public static void setGlobalCharset(Charset charset) { + encoding = charset; + } + + public static Charset charset() { + return encoding; + } + + /** + * 异常 转字符串 + * + * @param throwable error + * @return error string + */ + public static String getTraceString(Throwable throwable) { + if (throwable == null) { + return EMPTY; + } + StringWriter stackTrace = new StringWriter(); + throwable.printStackTrace(new PrintWriter(stackTrace)); + stackTrace.flush(); + return stackTrace.toString(); + } + + /** + * @param str string + * @return not null + */ + public static boolean isNotEmpty(String str) { + return hasLength(str); + } + + /** + * 没有长度 + * + * @param str string value + * @return hasNotLength + */ + public static boolean hasNotLength(String str) { + return str == null || !str.isEmpty(); + } + + /** + * 没有长度 + * + * @param str string value + * @return hasNotLength + */ + public static boolean hasNotLength(CharSequence str) { + return str == null || str.length() <= 0; + } + + /** + * 默认字符串替换 + * + * @param nullAbleString 为空字符串 + * @param defaultString 默认字符串 + * @return 转换后字符串 + */ + public static String defaultString(String nullAbleString, String defaultString) { + return StringUtils.hasLength(nullAbleString) ? defaultString : nullAbleString; + } + + /** + * 首字母变小写 + * + * @param str 字符串 + * @return {String} + */ + public static String firstCharToLower(String str) { + char firstChar = str.charAt(0); + if (firstChar >= 'A' && firstChar <= 'Z') { + char[] arr = str.toCharArray(); + arr[0] += ('a' - 'A'); + return new String(arr); + } + return str; + } + + /** + * 是否是空白字符串 + * + * @param cs + * @return + */ + public static boolean isBlank(final CharSequence cs) { + return !hasText(cs); + } + + /** + * 下划线 分隔转驼峰 + */ + public static String underScoreToLowerCamelCase(String userScoreStr) { + if (userScoreStr == null) { + return EMPTY; + } + char[] chars = userScoreStr.toCharArray(); + boolean meetUnderScore = false; + int scoreCount = 0; + for (int i = 0, j = chars.length; i < j; i++) { + if (chars[i] == '_') { + meetUnderScore = true; + ++scoreCount; + continue; + } + if (meetUnderScore) { + meetUnderScore = false; + int a = chars[i]; + if (a >= 'a' && a <= 'z') { + chars[i] = (char) (a - 32); + } + } + } + char[] newChars = new char[chars.length - scoreCount]; + int scoreIndex = 0; + for (int i = 0, j = newChars.length; i < j; ) { + if (chars[scoreIndex] != '_') { + newChars[i] = chars[scoreIndex]; + ++scoreIndex; + ++i; + } else { + do { + ++scoreIndex; + } while (chars[scoreIndex] == '_'); + } + } + + return new String(newChars); + } +} diff --git a/ray-infrastructure-utility/src/main/java/top/rayc/utility/vo/BaseReq.java b/ray-infrastructure-utility/src/main/java/top/rayc/utility/vo/BaseReq.java new file mode 100644 index 0000000..fa63cbe --- /dev/null +++ b/ray-infrastructure-utility/src/main/java/top/rayc/utility/vo/BaseReq.java @@ -0,0 +1,28 @@ +package top.rayc.utility.vo; + +public class BaseReq { + private String traceId; + private Integer pageSize; + private Integer pageNumber; + + public String getTraceId() { + return traceId; + } + public void setTraceId(String traceId) { + this.traceId = traceId; + } + public Integer getPageSize() { + return pageSize; + } + public void setPageSize(Integer pageSize) { + this.pageSize = pageSize; + } + public Integer getPageNumber() { + return pageNumber; + } + public void setPageNumber(Integer pageNumber) { + this.pageNumber = pageNumber; + } + + +} diff --git a/ray-infrastructure-utility/src/main/java/top/rayc/utility/vo/BaseResult.java b/ray-infrastructure-utility/src/main/java/top/rayc/utility/vo/BaseResult.java new file mode 100644 index 0000000..874c91a --- /dev/null +++ b/ray-infrastructure-utility/src/main/java/top/rayc/utility/vo/BaseResult.java @@ -0,0 +1,128 @@ +package top.rayc.utility.vo; + +import java.io.Serializable; + +import org.jboss.logging.MDC; + +import top.rayc.utility.exception.MessageCode; + +public class BaseResult implements Serializable { + + private Integer status; + private String msg; + private T data; + private String traceId; + private String errMsg; + + private static final String TRACE_LOG_ID = "traceId"; + + private BaseResult (Integer status, String msg, String traceId) { + this.status = status; + this.msg = msg; + this.traceId = traceId; + } + + private BaseResult (Integer status, String msg, T data, String traceId) { + this.status = status; + this.msg = msg; + this.data = data; + this.traceId = traceId; + } + + private BaseResult (Integer status, String msg, T data, String traceId, String errMsg) { + this.status = status; + this.msg = msg; + this.data = data; + this.traceId = traceId; + this.errMsg = errMsg; + } + + public static BaseResult success(MessageCode messageCode) { + return new BaseResult( + messageCode.getStatus(), + messageCode.getMessage(), + MDC.get(TRACE_LOG_ID).toString()); + } + + public static BaseResult success(Integer code, String msg, T data) { + return new BaseResult( + MessageCode.SUCCESS.getStatus(), + MessageCode.SUCCESS.getMessage(), + data, + MDC.get(TRACE_LOG_ID).toString()); + } + + public static BaseResult error(Integer code, String msg, T data) { + return new BaseResult( + code, + msg, + data, + MDC.get(TRACE_LOG_ID).toString()); + } + + public static BaseResult error(String msg) { + return new BaseResult( + MessageCode.SYSTEM_ERROR.getStatus(), + msg, + MDC.get(TRACE_LOG_ID).toString()); + } + + public static BaseResult error(Integer code, String msg) { + return new BaseResult( + code, + msg, + MDC.get(TRACE_LOG_ID).toString()); + } + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } + + public T getData() { + return data; + } + + public void setData(T data) { + this.data = data; + } + + public String getTraceId() { + return traceId; + } + + public void setTraceId(String traceId) { + this.traceId = traceId; + } + + public String getErrMsg() { + return errMsg; + } + + public void setErrMsg(String errMsg) { + this.errMsg = errMsg; + } + + @Override + public String toString() { + return "Result {" + + "status=" + status + + ", msg='" + msg + "'" + + ", data=" + data + + ", traceId='" + traceId + "'" + + ", errMsg='" + errMsg + "'" + + "}"; + } + +} diff --git a/ray-user/pom.xml b/ray-user/pom.xml new file mode 100644 index 0000000..a8a8f18 --- /dev/null +++ b/ray-user/pom.xml @@ -0,0 +1,37 @@ + + + 4.0.0 + + + top.rayc + ray + 0.0.1 + ../pom.xml + + + ray-user + jar + ${project.artifactId} + + + + top.rayc + ray-infrastructure-utility + 0.0.1 + + + + org.springframework.boot + spring-boot-test + test + + + + org.projectlombok + lombok + true + + + \ No newline at end of file diff --git a/ray-user/src/main/java/top/rayc/user/controller/UserController.java b/ray-user/src/main/java/top/rayc/user/controller/UserController.java new file mode 100644 index 0000000..8346952 --- /dev/null +++ b/ray-user/src/main/java/top/rayc/user/controller/UserController.java @@ -0,0 +1,8 @@ +package top.rayc.user.controller; + +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class UserController { + +} diff --git a/ray-user/src/main/java/top/rayc/user/controller/vo/req/UserCreateReq.java b/ray-user/src/main/java/top/rayc/user/controller/vo/req/UserCreateReq.java new file mode 100644 index 0000000..9b1f32d --- /dev/null +++ b/ray-user/src/main/java/top/rayc/user/controller/vo/req/UserCreateReq.java @@ -0,0 +1,17 @@ +package top.rayc.user.controller.vo.req; + +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotEmpty; +import lombok.Data; + +@Data +public class UserCreateReq { + @Email + private String email; + @NotEmpty + private String password; + @NotEmpty + private String code; + + private String verifyCode; +} diff --git a/ray-user/src/main/java/top/rayc/user/controller/vo/req/UserLoginReq.java b/ray-user/src/main/java/top/rayc/user/controller/vo/req/UserLoginReq.java new file mode 100644 index 0000000..f3d81e8 --- /dev/null +++ b/ray-user/src/main/java/top/rayc/user/controller/vo/req/UserLoginReq.java @@ -0,0 +1,10 @@ +package top.rayc.user.controller.vo.req; + +import lombok.Data; + +@Data +public class UserLoginReq { + private String username; + private String password; + private String optCode; +} diff --git a/ray-user/src/main/java/top/rayc/user/controller/vo/resp/UserResp.java b/ray-user/src/main/java/top/rayc/user/controller/vo/resp/UserResp.java new file mode 100644 index 0000000..77a3c62 --- /dev/null +++ b/ray-user/src/main/java/top/rayc/user/controller/vo/resp/UserResp.java @@ -0,0 +1,21 @@ +package top.rayc.user.controller.vo.resp; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +import lombok.Data; + +@Data +public class UserResp { + private Long id; + private Long accountId; + private String username; + private String nickname; + private String phone; + private String email; + private String gender; + private String shortBio; + private String avatar; + private LocalDate birthday; + private LocalDateTime createAt; +} diff --git a/ray-user/src/main/java/top/rayc/user/converter/UserConverter.java b/ray-user/src/main/java/top/rayc/user/converter/UserConverter.java new file mode 100644 index 0000000..a6b5577 --- /dev/null +++ b/ray-user/src/main/java/top/rayc/user/converter/UserConverter.java @@ -0,0 +1,19 @@ +package top.rayc.user.converter; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import top.rayc.user.controller.vo.req.UserCreateReq; +import top.rayc.user.controller.vo.resp.UserResp; +import top.rayc.user.entity.User; + +@Mapper +public interface UserConverter { + + UserConverter INSTANCE = Mappers.getMapper(UserConverter.class); + + User converterFromUserCreateReq(UserCreateReq userReq); + + UserResp converterToUserResp(User user); + +} diff --git a/ray-user/src/main/java/top/rayc/user/entity/Role.java b/ray-user/src/main/java/top/rayc/user/entity/Role.java new file mode 100644 index 0000000..87d962e --- /dev/null +++ b/ray-user/src/main/java/top/rayc/user/entity/Role.java @@ -0,0 +1,20 @@ +package top.rayc.user.entity; + +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import lombok.Data; + +@Data +@TableName("role") +public class Role { + @TableId(value="id", type = IdType.AUTO) + private Long id; + private String roleName; + private String description; + private LocalDateTime createAt; + private LocalDateTime updateAt; +} diff --git a/ray-user/src/main/java/top/rayc/user/entity/User.java b/ray-user/src/main/java/top/rayc/user/entity/User.java new file mode 100644 index 0000000..683a8e1 --- /dev/null +++ b/ray-user/src/main/java/top/rayc/user/entity/User.java @@ -0,0 +1,30 @@ +package top.rayc.user.entity; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import lombok.Data; + +@Data +@TableName("user") +public class User { + @TableId(value = "id", type = IdType.AUTO) + private Long id; + private Long accountId; + private String username; + private String nickname; + private String phone; + private String email; + private String password; + private String gender; + private String shortBio; + private String avatar; + private LocalDate birthday; + private Boolean isDeleted; + private LocalDateTime createAt; + private LocalDateTime updateAt; +} diff --git a/ray-user/src/main/java/top/rayc/user/entity/UserRole.java b/ray-user/src/main/java/top/rayc/user/entity/UserRole.java new file mode 100644 index 0000000..ab8c7d3 --- /dev/null +++ b/ray-user/src/main/java/top/rayc/user/entity/UserRole.java @@ -0,0 +1,16 @@ +package top.rayc.user.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import lombok.Data; + +@Data +@TableName("user_role") +public class UserRole { + @TableId(value = "id", type = IdType.AUTO) + private Long id; + private Long userId; + private Long roleId; +} diff --git a/ray-user/src/main/java/top/rayc/user/mapper/RoleMapper.java b/ray-user/src/main/java/top/rayc/user/mapper/RoleMapper.java new file mode 100644 index 0000000..573ce0a --- /dev/null +++ b/ray-user/src/main/java/top/rayc/user/mapper/RoleMapper.java @@ -0,0 +1,12 @@ +package top.rayc.user.mapper; + +import org.apache.ibatis.annotations.Mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +import top.rayc.user.entity.Role; + +@Mapper +public interface RoleMapper extends BaseMapper { + +} diff --git a/ray-user/src/main/java/top/rayc/user/mapper/UserMapper.java b/ray-user/src/main/java/top/rayc/user/mapper/UserMapper.java new file mode 100644 index 0000000..4c9534b --- /dev/null +++ b/ray-user/src/main/java/top/rayc/user/mapper/UserMapper.java @@ -0,0 +1,11 @@ +package top.rayc.user.mapper; + +import org.apache.ibatis.annotations.Mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +import top.rayc.user.entity.User; + +@Mapper +public interface UserMapper extends BaseMapper { +} diff --git a/ray-user/src/main/java/top/rayc/user/mapper/UserRoleMapper.java b/ray-user/src/main/java/top/rayc/user/mapper/UserRoleMapper.java new file mode 100644 index 0000000..61f5802 --- /dev/null +++ b/ray-user/src/main/java/top/rayc/user/mapper/UserRoleMapper.java @@ -0,0 +1,11 @@ +package top.rayc.user.mapper; + +import org.apache.ibatis.annotations.Mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +import top.rayc.user.entity.UserRole; + +@Mapper +public interface UserRoleMapper extends BaseMapper { +} diff --git a/ray-user/src/main/java/top/rayc/user/security/SecurityConfig.java b/ray-user/src/main/java/top/rayc/user/security/SecurityConfig.java new file mode 100644 index 0000000..af027f4 --- /dev/null +++ b/ray-user/src/main/java/top/rayc/user/security/SecurityConfig.java @@ -0,0 +1,47 @@ +package top.rayc.user.security; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.ProviderManager; +import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; + +import top.rayc.user.security.dsl.SecurityConfigDsl; +import top.rayc.user.security.provider.UsernamePasswordAuthenticationProvider; +import top.rayc.utility.security.authentication.filter.JwtAuthenticationFilter; + +@Configuration +@EnableWebSecurity +@EnableMethodSecurity(prePostEnabled = true) +public class SecurityConfig { + + @Autowired + private UsernamePasswordAuthenticationProvider usernamePasswordAuthenticationProvider; + + + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + http + .csrf(csrf -> csrf.disable()) + .authorizeHttpRequests(auth -> { + auth.anyRequest().permitAll(); + }) + .sessionManagement(management -> management.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) + .addFilterBefore(new JwtAuthenticationFilter(), BasicAuthenticationFilter.class) + .apply( new SecurityConfigDsl() ); + + return http.build(); + } + + @Bean + public AuthenticationManager authenticationManager() { + return new ProviderManager(usernamePasswordAuthenticationProvider); + } + +} diff --git a/ray-user/src/main/java/top/rayc/user/security/authentication/InitialJsonAuthenticationFilter.java b/ray-user/src/main/java/top/rayc/user/security/authentication/InitialJsonAuthenticationFilter.java new file mode 100644 index 0000000..50999e1 --- /dev/null +++ b/ray-user/src/main/java/top/rayc/user/security/authentication/InitialJsonAuthenticationFilter.java @@ -0,0 +1,79 @@ +package top.rayc.user.security.authentication; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; + +import org.springframework.web.filter.OncePerRequestFilter; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; + +import lombok.val; +import lombok.extern.slf4j.Slf4j; +import top.rayc.user.controller.vo.req.UserLoginReq; +import top.rayc.utility.security.authentication.UsernamePasswordAuthentication; +import top.rayc.utility.utils.JwtTokenUtils; + +@Slf4j +public class InitialJsonAuthenticationFilter extends OncePerRequestFilter { + + private AuthenticationManager manager; + + public InitialJsonAuthenticationFilter(AuthenticationManager manager) { + this.manager = manager; + } + + private final String signingKey = ".ymLTU8rq83j4fmJZj60wh4OrMNuntIj4fmJ1refreywscascsa"; + private final Long jwtDuration = 1000L * 60 * 60 * 10; + + @Override + protected void doFilterInternal( + HttpServletRequest request, + HttpServletResponse response, + FilterChain filterChain + ) throws ServletException, IOException { + UserLoginReq loginReq = new UserLoginReq(); + + try { + ObjectMapper objectMapper = new ObjectMapper(); + loginReq = objectMapper.readValue(request.getInputStream(), UserLoginReq.class); + if ("null".equals(loginReq.getUsername())) { + loginReq.setUsername(null); + } + if ("null".equals(loginReq.getPassword())) { + loginReq.setPassword(null); + } + if ("null".equals(loginReq.getOptCode())) { + loginReq.setOptCode(null); + } + } catch (Exception e) { + log.error(e.getMessage(), e); + } + + UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthentication(loginReq.getUsername(), loginReq.getPassword(), null); + this.manager.authenticate(authentication); + + String jwt = JwtTokenUtils.generateJwtToken(signingKey, authentication, jwtDuration); + + response.setCharacterEncoding(StandardCharsets.UTF_8.name()); + response.setContentType(MediaType.APPLICATION_JSON_VALUE); + response.setStatus(HttpStatus.OK.value()); + response.setHeader("Authorization", jwt); + } + + @Override + protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException { + return !request.getServletPath().equals("/login") || + !request.getContentType().equals(MediaType.APPLICATION_JSON_VALUE) || + !request.getMethod().equals("POST"); + } + +} diff --git a/ray-user/src/main/java/top/rayc/user/security/dsl/SecurityConfigDsl.java b/ray-user/src/main/java/top/rayc/user/security/dsl/SecurityConfigDsl.java new file mode 100644 index 0000000..886c5ba --- /dev/null +++ b/ray-user/src/main/java/top/rayc/user/security/dsl/SecurityConfigDsl.java @@ -0,0 +1,23 @@ +package top.rayc.user.security.dsl; + +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; + +import top.rayc.user.security.authentication.InitialJsonAuthenticationFilter; + +public class SecurityConfigDsl extends AbstractHttpConfigurer { + + @Override + public void configure(HttpSecurity builder) throws Exception { + super.configure(builder); + AuthenticationManager manager = builder.getSharedObject(AuthenticationManager.class); + builder.addFilterAfter(new InitialJsonAuthenticationFilter(manager), BasicAuthenticationFilter.class); + } + + public static SecurityConfigDsl newInstance() { + return new SecurityConfigDsl(); + } + +} diff --git a/ray-user/src/main/java/top/rayc/user/security/handler/JwtAuthenticationFailedHandler.java b/ray-user/src/main/java/top/rayc/user/security/handler/JwtAuthenticationFailedHandler.java new file mode 100644 index 0000000..39f2425 --- /dev/null +++ b/ray-user/src/main/java/top/rayc/user/security/handler/JwtAuthenticationFailedHandler.java @@ -0,0 +1,24 @@ +package top.rayc.user.security.handler; + +import java.io.IOException; + +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.AuthenticationFailureHandler; +import org.springframework.stereotype.Component; + +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +@Component +public class JwtAuthenticationFailedHandler implements AuthenticationFailureHandler { + + @Override + public void onAuthenticationFailure( + HttpServletRequest request, + HttpServletResponse response, + AuthenticationException exception + ) throws IOException, ServletException { + } + +} diff --git a/ray-user/src/main/java/top/rayc/user/security/handler/JwtAuthenticationSuccessHandler.java b/ray-user/src/main/java/top/rayc/user/security/handler/JwtAuthenticationSuccessHandler.java new file mode 100644 index 0000000..5359564 --- /dev/null +++ b/ray-user/src/main/java/top/rayc/user/security/handler/JwtAuthenticationSuccessHandler.java @@ -0,0 +1,21 @@ +package top.rayc.user.security.handler; + +import java.io.IOException; + +import org.springframework.security.core.Authentication; +import org.springframework.security.web.authentication.AuthenticationSuccessHandler; +import org.springframework.stereotype.Component; + +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +@Component +public class JwtAuthenticationSuccessHandler implements AuthenticationSuccessHandler { + + @Override + public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, + Authentication authentication) throws IOException, ServletException { + } + +} diff --git a/ray-user/src/main/java/top/rayc/user/security/provider/UsernamePasswordAuthenticationProvider.java b/ray-user/src/main/java/top/rayc/user/security/provider/UsernamePasswordAuthenticationProvider.java new file mode 100644 index 0000000..fdb5e41 --- /dev/null +++ b/ray-user/src/main/java/top/rayc/user/security/provider/UsernamePasswordAuthenticationProvider.java @@ -0,0 +1,32 @@ +package top.rayc.user.security.provider; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.stereotype.Component; + +import top.rayc.user.service.impl.AuthService; +import top.rayc.utility.security.authentication.UsernamePasswordAuthentication; + +@Component +public class UsernamePasswordAuthenticationProvider implements AuthenticationProvider { + + @Autowired + private AuthService authService; + + @Override + public Authentication authenticate(Authentication authentication) throws AuthenticationException { + String username = (String) authentication.getPrincipal(); + String password = (String) authentication.getCredentials(); + + return authService.auth(username, password); + } + + @Override + public boolean supports(Class authentication) { + if (authentication == null) return false; + return UsernamePasswordAuthentication.class.isAssignableFrom(authentication); + } + +} diff --git a/ray-user/src/main/java/top/rayc/user/service/IAuthService.java b/ray-user/src/main/java/top/rayc/user/service/IAuthService.java new file mode 100644 index 0000000..a95bd5e --- /dev/null +++ b/ray-user/src/main/java/top/rayc/user/service/IAuthService.java @@ -0,0 +1,7 @@ +package top.rayc.user.service; + +import top.rayc.utility.security.authentication.UsernamePasswordAuthentication; + +public interface IAuthService { + UsernamePasswordAuthentication auth(String username, String password); +} diff --git a/ray-user/src/main/java/top/rayc/user/service/IUserService.java b/ray-user/src/main/java/top/rayc/user/service/IUserService.java new file mode 100644 index 0000000..2a1d9ea --- /dev/null +++ b/ray-user/src/main/java/top/rayc/user/service/IUserService.java @@ -0,0 +1,13 @@ +package top.rayc.user.service; + +import org.springframework.http.ResponseEntity; + +import top.rayc.user.controller.vo.req.UserCreateReq; +import top.rayc.user.controller.vo.resp.UserResp; +import top.rayc.utility.vo.BaseResult; + +public interface IUserService { + + ResponseEntity> createUser(UserCreateReq userReq); + +} diff --git a/ray-user/src/main/java/top/rayc/user/service/impl/AuthService.java b/ray-user/src/main/java/top/rayc/user/service/impl/AuthService.java new file mode 100644 index 0000000..68ff406 --- /dev/null +++ b/ray-user/src/main/java/top/rayc/user/service/impl/AuthService.java @@ -0,0 +1,80 @@ +package top.rayc.user.service.impl; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; + +import lombok.extern.slf4j.Slf4j; +import top.rayc.user.entity.Role; +import top.rayc.user.entity.User; +import top.rayc.user.entity.UserRole; +import top.rayc.user.mapper.RoleMapper; +import top.rayc.user.mapper.UserMapper; +import top.rayc.user.mapper.UserRoleMapper; +import top.rayc.user.service.IAuthService; +import top.rayc.utility.security.authentication.UsernamePasswordAuthentication; +@Slf4j +@Service +public class AuthService implements IAuthService { + + @Autowired + private UserMapper userMapper; + @Autowired + private RoleMapper roleMapper; + @Autowired + private UserRoleMapper userRoleMapper; + + @Autowired + private PasswordEncoder passwordEncoder; + + @Override + public UsernamePasswordAuthentication auth(String username, String password) { + User storedUser = findUser(username); + + log.info("username: {}; password: {}; storedUser: {}", username, password, storedUser); + + if (storedUser == null || !verifyPassrword(password, storedUser.getPassword())) { + throw new BadCredentialsException("密码错误"); + } + List roles = findRoles(storedUser); + + return new UsernamePasswordAuthentication( + storedUser.getUsername(), + password, + roles.stream().map(role -> new SimpleGrantedAuthority(role.getRoleName())).toList() + ); + } + + private List findRoles(User user) { + LambdaQueryWrapper userRoleWrapper = new LambdaQueryWrapper<>(); + userRoleWrapper.eq(UserRole::getUserId, user.getId()); + + List userRoles = userRoleMapper.selectList(userRoleWrapper); + if (userRoles.isEmpty()) { + return new ArrayList(); + } + LambdaQueryWrapper roleWrapper = new LambdaQueryWrapper<>(); + roleWrapper.in(Role::getId, + userRoles.stream() + .map(UserRole::getRoleId) + .toList()); + return roleMapper.selectList(roleWrapper); + } + + private Boolean verifyPassrword(String password, String storedPassword) { + return passwordEncoder.matches(password, storedPassword); + } + + private User findUser(String username) { + LambdaQueryWrapper userWrapper = new LambdaQueryWrapper<>(); + userWrapper.eq(User::getEmail, username); + return userMapper.selectOne(userWrapper); + } +} diff --git a/ray-user/src/main/java/top/rayc/user/service/impl/UserService.java b/ray-user/src/main/java/top/rayc/user/service/impl/UserService.java new file mode 100644 index 0000000..0bf5bb9 --- /dev/null +++ b/ray-user/src/main/java/top/rayc/user/service/impl/UserService.java @@ -0,0 +1,63 @@ +package top.rayc.user.service.impl; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; + +import top.rayc.user.controller.vo.req.UserCreateReq; +import top.rayc.user.controller.vo.resp.UserResp; +import top.rayc.user.converter.UserConverter; +import top.rayc.user.entity.Role; +import top.rayc.user.entity.User; +import top.rayc.user.entity.UserRole; +import top.rayc.user.mapper.RoleMapper; +import top.rayc.user.mapper.UserMapper; +import top.rayc.user.mapper.UserRoleMapper; +import top.rayc.user.service.IUserService; +import top.rayc.utility.id.DistributedId; +import top.rayc.utility.vo.BaseResult; + +@Service +public class UserService extends ServiceImpl implements IUserService { + + @Autowired + private RoleMapper roleMapper; + @Autowired + private UserRoleMapper userRoleMapper; + + @Override + public ResponseEntity> createUser(UserCreateReq userReq) { + if (userReq.getCode() == "1234") throw new RuntimeException("验证码错误"); + User newUser = UserConverter.INSTANCE.converterFromUserCreateReq(userReq); + newUser.setAccountId(DistributedId.getInstance().getSnowflake(1, 1)); + + Boolean result = this.save(newUser); + initializeUserRole(newUser, "Normal"); + + if (result) { + return ResponseEntity.ok(BaseResult.success(200, "Register Successful!!!", UserConverter.INSTANCE.converterToUserResp(newUser))); + } else { + ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR.value()) + .body(BaseResult.error(500,"failed!!!")); + } + + throw new UnsupportedOperationException("Unimplemented method 'createUser'"); + } + + private void initializeUserRole(User user, String roleName) { + LambdaQueryWrapper query = new LambdaQueryWrapper<>(); + query.eq(Role::getRoleName, roleName); + + Role role = roleMapper.selectOne(query); + if (role != null) { + UserRole userRole = new UserRole(); + userRole.setUserId(user.getId()); + userRole.setRoleId(role.getId()); + userRoleMapper.insert(userRole); + } + } +} diff --git a/ray-user/src/main/java/top/rayc/user/utils/UserHelper.java b/ray-user/src/main/java/top/rayc/user/utils/UserHelper.java new file mode 100644 index 0000000..f93faef --- /dev/null +++ b/ray-user/src/main/java/top/rayc/user/utils/UserHelper.java @@ -0,0 +1,31 @@ +package top.rayc.user.utils; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.AnonymousAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Component; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; + +import top.rayc.user.entity.User; +import top.rayc.user.service.impl.UserService; + +@Component +public class UserHelper { + @Autowired + private UserService userService; + + public User currentUser() { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + + if (authentication instanceof AnonymousAuthenticationToken) { + String email = authentication.getName(); + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(User::getEmail, email); + + return userService.getOne(wrapper); + } + return null; + } +}