Compare commits
102 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
90101c173c | ||
|
|
c590953197 | ||
|
|
23772223bd | ||
|
|
b88f413906 | ||
|
|
6d8bdf1df3 | ||
|
|
0173357ec9 | ||
|
|
b4ae4bcc90 | ||
|
|
f7679217ec | ||
|
|
901d539332 | ||
|
|
1b3c284f4e | ||
|
|
f5b6f8da4e | ||
|
|
6da72845e4 | ||
|
|
81b9ac5923 | ||
|
|
8f8dc86365 | ||
|
|
f9d46edbcc | ||
|
|
e3991be3b7 | ||
|
|
d42853abe2 | ||
|
|
e5c6a1aca4 | ||
|
|
b5d46912d2 | ||
|
|
dfcbaf7158 | ||
|
|
17257dccda | ||
|
|
1c1248306c | ||
|
|
d5873a7f97 | ||
|
|
7437dc8936 | ||
|
|
549a599a5b | ||
|
|
38effb0bb7 | ||
|
|
1e25c23b0b | ||
|
|
c870d32777 | ||
|
|
b86e487a47 | ||
|
|
330713509e | ||
|
|
ecf85dfe9e | ||
|
|
ac3b4283a3 | ||
|
|
141f9dee5e | ||
|
|
ce9f809ab5 | ||
|
|
b83af8dc5e | ||
|
|
ce0a7bd6ef | ||
|
|
008425734c | ||
|
|
e078366395 | ||
|
|
69ec12ab99 | ||
|
|
8e93874c69 | ||
|
|
2a6f0f94cc | ||
|
|
d501d96ad6 | ||
|
|
73569a63f8 | ||
|
|
71e6ba4d8b | ||
|
|
72a627be74 | ||
|
|
0344f687b6 | ||
|
|
1b0789cdd0 | ||
|
|
7cf16754f8 | ||
|
|
6aefc107e7 | ||
|
|
e082043f99 | ||
|
|
a55e8ae2ad | ||
|
|
188431b64d | ||
|
|
7f23dcb7c4 | ||
|
|
8dcb64a60d | ||
|
|
d9c64ff369 | ||
|
|
6963b1d593 | ||
|
|
0a61e1047d | ||
|
|
3f02cd9832 | ||
|
|
3aa42c00fa | ||
|
|
77b2253ff6 | ||
|
|
71a4fdfbaf | ||
|
|
2ecd69dc51 | ||
|
|
ebae9ba5c8 | ||
|
|
b2fd722443 | ||
|
|
e2ce404e87 | ||
|
|
6cfbe7689e | ||
|
|
b95c1d890b | ||
|
|
461c77012a | ||
|
|
9328e0ea9d | ||
|
|
aefa928a19 | ||
|
|
89c6c515f1 | ||
|
|
dcadffa265 | ||
|
|
300e58e92c | ||
|
|
96b71e4f8d | ||
|
|
456aabb893 | ||
|
|
b4d2ca238f | ||
|
|
2afb841fd9 | ||
|
|
2b09812153 | ||
|
|
972099a598 | ||
|
|
9335d78d60 | ||
|
|
f332cb929b | ||
|
|
a190a2ec6e | ||
|
|
5bfa7037cb | ||
|
|
4a94c879b8 | ||
|
|
38161f96e1 | ||
|
|
33c751ab33 | ||
|
|
d12cbd2383 | ||
|
|
5f84becf08 | ||
|
|
432fd89c0f | ||
|
|
84c8adc9d2 | ||
|
|
ba2523ac8a | ||
|
|
dcdd25c01f | ||
|
|
278e320550 | ||
|
|
1bfa66cc49 | ||
|
|
20fb2b3baa | ||
|
|
e9a85a4e88 | ||
|
|
63edbc11d3 | ||
|
|
c98c6af0f9 | ||
|
|
47f6066733 | ||
|
|
f4fb471da3 | ||
|
|
301b6bdf70 | ||
|
|
a98c4f4c48 |
24
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,24 +0,0 @@
|
||||
---
|
||||
name: BUG 反馈
|
||||
about: 事情不像预期的那样工作吗?
|
||||
title: ''
|
||||
labels: 'bug'
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
为了帮助我们更好的解决您的问题,请填写以下选项(不填写完整可能会被直接关闭 issue):
|
||||
|
||||
|
||||
- 是否已搜索其他 issue,没有人提过这个问题?:
|
||||
- 当前 ZFile 版本:
|
||||
- 是否尝试最新版是否已解决此问题:
|
||||
- 是否尝试重启 ZFile,且问题依旧存在?:
|
||||
- 是否已尝试清空浏览器缓存,且问题依旧存在?:
|
||||
- 操作系统(如 Windows、Mac、iOS、安卓):
|
||||
- 浏览器(如 Chrome、Firefox、Safari,X 浏览器):
|
||||
- 做什么操作提示的错误?:
|
||||
- 期望行为(应该是什么样的结果):
|
||||
- 当前行为(当前是什么样的结果):
|
||||
- 错误日志(可选):
|
||||
- 复现步骤(可选):
|
||||
- 您的额外信息(可选):
|
||||
13
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
name: 'Blank Issue'
|
||||
description: 请使用 https://issue.zfile.vip 创建新的问题.
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
**注意:**
|
||||
不要通过此页面创建问题, 请使用 https://issue.zfile.vip 创建新的问题.
|
||||
如果不是通过此链接创建的问题, 将会被直接关闭.
|
||||
- type: textarea
|
||||
id: add-a-description
|
||||
attributes:
|
||||
label: Add a description
|
||||
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
blank_issues_enabled: true
|
||||
contact_links:
|
||||
- name: 创建 Issue
|
||||
url: https://issue.zfile.vip/
|
||||
about: 未通过 https://issue.zfile.vip/ 创建的问题可能会被立即关闭。
|
||||
17
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -1,17 +0,0 @@
|
||||
---
|
||||
name: 功能建议
|
||||
about: 想让我们为 ZFile 增加什么功能吗?
|
||||
title: 'feat: '
|
||||
labels: 'Feature Request'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
|
||||
为了帮助我们更好的解决您的问题,请填写以下选项(不填写完整可能会被直接关闭 issue):
|
||||
|
||||
- 是否已搜索其他 issue,没有人提过这个功能?:
|
||||
- 是否已尝试使用最新版本,且仍然没有此功能?:
|
||||
- 功能概述:
|
||||
- 功能动机:
|
||||
- 详细解释(可选):
|
||||
4
.gitignore
vendored
@@ -18,6 +18,8 @@ target/
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
.fastRequest
|
||||
.murphy.yml
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
@@ -34,4 +36,4 @@ build/
|
||||
/.mvn/wrapper/
|
||||
/mvnw
|
||||
/mvnw.cmd
|
||||
/.script/
|
||||
/result/
|
||||
2
.package/script/log.sh
Normal file
@@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
tail -fn100 ~/.zfile-v4/logs/zfile.log
|
||||
6
.package/script/restart.sh
Normal file
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
|
||||
$DIR/stop.sh
|
||||
$DIR/start.sh
|
||||
22
.package/script/start.sh
Normal file
@@ -0,0 +1,22 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 检测是否已启动
|
||||
pid=`ps -ef | grep -n zfile | grep -v grep | grep -v launch | grep -v .sh | awk '{print $2}'`
|
||||
if [ -n "${pid}" ]
|
||||
then
|
||||
echo "已运行在 pid:${pid},无需重复启动!"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# 获取当前脚本所在路径
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
ZFILE_DIR=$(dirname "$DIR")
|
||||
|
||||
# 启动 zfile
|
||||
nohup $ZFILE_DIR/zfile/zfile --spring.config.location=$ZFILE_DIR/application.properties --spring.web.resources.static-locations=file:$ZFILE_DIR/static/ >/dev/null 2>&1 &
|
||||
echo '启动中...'
|
||||
sleep 3s
|
||||
|
||||
# 输出 pid
|
||||
pid=`ps -ef | grep -n zfile | grep -v grep | grep -v .sh | awk '{print $2}'`
|
||||
echo "目前 PID 为: ${pid}"
|
||||
12
.package/script/status.sh
Normal file
@@ -0,0 +1,12 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "------------------ 检测状态 START --------------"
|
||||
pid=`ps -ef | grep -n zfile | grep -v grep | grep -v launch | grep -v .sh | awk '{print $2}'`
|
||||
if [ -z "${pid}" ]
|
||||
then
|
||||
echo "未运行, 无需停止!"
|
||||
else
|
||||
echo "运行pid:${pid}"
|
||||
fi
|
||||
|
||||
echo "------------------ 检测状态 END --------------"
|
||||
14
.package/script/stop.sh
Normal file
@@ -0,0 +1,14 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "------------------ 检测状态 START --------------"
|
||||
pid=`ps -ef | grep -n zfile | grep -v grep | grep -v .sh | awk '{print $2}'`
|
||||
if [ -z "${pid}" ]
|
||||
then
|
||||
echo "未运行, 无需停止!"
|
||||
else
|
||||
echo "运行pid:${pid}"
|
||||
kill -9 ${pid}
|
||||
echo "已停止进程: ${pid}"
|
||||
fi
|
||||
|
||||
echo "------------------ 检测状态 END --------------"
|
||||
BIN
.package/script/vcruntime140_1.dll
Normal file
7
.package/script/双击我启动.bat
Normal file
@@ -0,0 +1,7 @@
|
||||
@echo off
|
||||
if not exist %windir%\system32\cmd.exe (
|
||||
"%CD%\zfile\zfile.exe"
|
||||
) else (
|
||||
cmd /k "%CD%\zfile\zfile.exe"
|
||||
exit
|
||||
)
|
||||
21
Dockerfile
Normal file
@@ -0,0 +1,21 @@
|
||||
FROM debian:10-slim
|
||||
|
||||
ARG TARGETARCH
|
||||
|
||||
WORKDIR /root
|
||||
EXPOSE 8080
|
||||
|
||||
RUN apt update -y && apt install --no-install-recommends fontconfig zstd -y && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
||||
COPY zfile-artifacts/zfile-linux-${TARGETARCH}/zfile/* /root/
|
||||
COPY zfile-artifacts/zfile-linux-${TARGETARCH}/static/ /root/static/
|
||||
COPY zfile-artifacts/zfile-linux-${TARGETARCH}/application.properties /root/
|
||||
|
||||
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
|
||||
RUN echo 'Asia/Shanghai' >/etc/timezone
|
||||
|
||||
# 设置编码为 UTF-8
|
||||
ENV LANG=C.UTF-8
|
||||
ENV LC_ALL=C.UTF-8
|
||||
|
||||
CMD if [ -f /root/zfile.zst ]; then zstd --no-progress -d /root/zfile.zst && rm -rf /root/zfile.zst && chmod +x /root/zfile && /root/zfile --spring.config.location=file:/root/application.properties; else chmod +x /root/zfile && /root/zfile --spring.config.location=file:/root/application.properties; fi
|
||||
106
README.md
@@ -1,65 +1,83 @@
|
||||
<p align="center">
|
||||
<a href="https://zfile.vip" target="_blank" rel="noopener noreferrer">
|
||||
<img alt="ZFile" src="https://cdn.jun6.net/2021/04/21/69a89344e2a84.png" height="150px">
|
||||
</a>
|
||||
<br><br>
|
||||
基于 Java 的在线网盘程序,支持对接 S3、OneDrive、SharePoint、又拍云、本地存储、FTP、SFTP 等存储源,支持在线浏览图片、播放音视频,文本文件、Office、obj(3d)等文件类型。
|
||||
<br><br>
|
||||
<img src="https://img.shields.io/badge/license-MIT-blue.svg?longCache=true&style=flat-square" alt="license">
|
||||
<img src="https://api.codacy.com/project/badge/Grade/70b793267f7941d58cbd93f50c9a8e0a" alt="codady">
|
||||
<img src="https://img.shields.io/github/last-commit/zhaojun1998/zfile.svg?style=flat-square" alt="last commit">
|
||||
<img src="https://img.shields.io/github/downloads/zhaojun1998/zfile/total?style=flat-square" alt="downloads">
|
||||
<img src="https://img.shields.io/github/v/release/zhaojun1998/zfile?style=flat-square" alt="release">
|
||||
<img src="https://img.shields.io/github/commit-activity/y/zhaojun1998/zfile?style=flat-square" alt="commit activity">
|
||||
<br>
|
||||
<img src="https://img.shields.io/github/issues/zhaojun1998/zfile?style=flat-square" alt="issues">
|
||||
<img src="https://img.shields.io/github/issues-closed-raw/zhaojun1998/zfile?style=flat-square" alt="closed issues">
|
||||
<img src="https://img.shields.io/github/forks/zhaojun1998/zfile?style=flat-square" alt="forks">
|
||||
<img src="https://img.shields.io/github/stars/zhaojun1998/zfile?style=flat-square" alt="stars">
|
||||
<img src="https://img.shields.io/github/watchers/zhaojun1998/zfile?style=flat-square" alt="watchers">
|
||||
</p>
|
||||
<div align="center">
|
||||
<a href="https://zfile.vip" target="_blank" rel="noopener noreferrer">
|
||||
<img style="margin: auto; width: 100px; display: block" src="/img/logo-zfile.png" alt="ZFile" />
|
||||
</a>
|
||||
<p>ZFile 是一个适用于个人或小团队的在线网盘程序,可以将多种存储类型统一管理,再也不用登录各种网站管理文件,现在你只需要在 ZFile 中畅快使用!</p>
|
||||
<div>
|
||||
<img alt="last commit" src="https://shields.io/github/last-commit/zhaojun1998/zfile.svg?style=flat-square"/>
|
||||
<img alt="downloads" src="https://shields.io/github/downloads/zhaojun1998/zfile/total?style=flat-square"/>
|
||||
<img alt="release version" src="https://shields.io/github/v/release/zhaojun1998/zfile?style=flat-square"/>
|
||||
<img alt="commit activity" src="https://shields.io/github/commit-activity/y/zhaojun1998/zfile?style=flat-square"/>
|
||||
<img alt="open issues" src="https://shields.io/github/issues/zhaojun1998/zfile?style=flat-square"/>
|
||||
<img alt="closed issues" src="https://shields.io/github/issues-closed-raw/zhaojun1998/zfile?style=flat-square"/>
|
||||
<img alt="forks" src="https://shields.io/github/forks/zhaojun1998/zfile?style=flat-square"/>
|
||||
<img alt="stars" src="https://shields.io/github/stars/zhaojun1998/zfile?style=flat-square"/>
|
||||
<img alt="watchers" src="https://shields.io/github/watchers/zhaojun1998/zfile?style=flat-square"/>
|
||||
</div>
|
||||
<span>
|
||||
<a href="https://zfile.vip">官网</a>
|
||||
<span> | </span>
|
||||
<a href="https://docs.zfile.vip">文档</a>
|
||||
<span> | </span>
|
||||
<a href="https://demo.zfile.vip">预览地址</a>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
## 系统特色
|
||||
|
||||
- Docker、Docker Compose 支持(amd64, arm64)。
|
||||
- 支持对文件生成直链、短链(可设过期时间)。
|
||||
- 响应式设计,支持手机、平板、电脑等多种设备访问。
|
||||
- 支持多用户功能,可分配给指定用户指定存储源或目录。
|
||||
- 支持在线浏览图片、播放音视频,文本文件、Office、Obj(3d)等文件类型。
|
||||
- 支持对接 S3、OneDrive、SharePoint、Google Drive、多吉云、又拍云、本地存储、FTP、SFTP 等存储源。
|
||||
- 支持常用快捷键,`Ctrl + A` 全选,`Ctrl + 左键` 多选,`Shift + 左键` 范围选择,`Esc` 取消全选等。
|
||||
- 支持限速下载(捐赠版)
|
||||
- 支持限制指定用户可查看、上传的文件类型(捐赠版)
|
||||
|
||||
## 快速开始
|
||||
|
||||
请参考部署文档: [https://docs.zfile.vip](https://docs.zfile.vip)
|
||||
一键脚本安装:
|
||||
|
||||
## 在线体验
|
||||
```bash
|
||||
curl -sSL https://docs.zfile.vip/install.sh -o install.sh && chmod +x install.sh && ./install.sh
|
||||
```
|
||||
|
||||
更多安装方式请参考 [安装文档](https://docs.zfile.vip/install/)
|
||||
|
||||
[https://demo.zfile.vip](https://demo.zfile.vip)
|
||||
|
||||
## 功能预览
|
||||
|
||||
### 文件列表
|
||||

|
||||

|
||||
### 画廊模式
|
||||

|
||||

|
||||
### 视频预览
|
||||

|
||||

|
||||
### 文本预览
|
||||

|
||||

|
||||
### 音频预览
|
||||

|
||||

|
||||
### PDF 预览
|
||||

|
||||

|
||||
### Office 预览
|
||||

|
||||

|
||||
### 3d 文件预览
|
||||

|
||||
### 生成直链
|
||||

|
||||

|
||||
### 页面设置
|
||||

|
||||

|
||||
### 后台设置-登录
|
||||

|
||||

|
||||
### 后台设置-存储源列表
|
||||

|
||||
### 后台设置-存储源权限控制
|
||||

|
||||

|
||||
### 后台设置-添加存储源(本地存储)
|
||||

|
||||
### 后台设置-添加存储源(世纪互联)
|
||||

|
||||

|
||||
### 后台设置-用户管理
|
||||

|
||||
### 后台设置-显示设置
|
||||

|
||||
|
||||

|
||||
|
||||
## 支持作者
|
||||
|
||||
@@ -67,10 +85,6 @@
|
||||
|
||||
<img src="https://cdn.jun6.net/2021/03/27/152704e91f13d.png" width="400" alt="赞助我">
|
||||
|
||||
## Status
|
||||
|
||||

|
||||
|
||||
## Star History
|
||||
|
||||
[](https://star-history.com/#zfile-dev/zfile&Date)
|
||||
[](https://star-history.com/#zfile-dev/zfile&Date)
|
||||
|
||||
BIN
img/file-list.png
Normal file
|
After Width: | Height: | Size: 79 KiB |
BIN
img/gallery.png
Normal file
|
After Width: | Height: | Size: 563 KiB |
BIN
img/generate-link.jpeg
Normal file
|
After Width: | Height: | Size: 362 KiB |
BIN
img/login.png
Normal file
|
After Width: | Height: | Size: 59 KiB |
BIN
img/logo-zfile.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
img/page-setting.png
Normal file
|
After Width: | Height: | Size: 166 KiB |
BIN
img/preview-3d.png
Normal file
|
After Width: | Height: | Size: 213 KiB |
BIN
img/preview-audio.png
Normal file
|
After Width: | Height: | Size: 106 KiB |
BIN
img/preview-office.png
Normal file
|
After Width: | Height: | Size: 156 KiB |
BIN
img/preview-pdf.png
Normal file
|
After Width: | Height: | Size: 220 KiB |
BIN
img/preview-text.png
Normal file
|
After Width: | Height: | Size: 150 KiB |
BIN
img/preview-video.png
Normal file
|
After Width: | Height: | Size: 790 KiB |
BIN
img/storage-edit-local.png
Normal file
|
After Width: | Height: | Size: 483 KiB |
BIN
img/storage-list.png
Normal file
|
After Width: | Height: | Size: 104 KiB |
BIN
img/user-edit.png
Normal file
|
After Width: | Height: | Size: 164 KiB |
BIN
img/view-setting.png
Normal file
|
After Width: | Height: | Size: 181 KiB |
277
pom.xml
@@ -2,27 +2,60 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>im.zhaojun</groupId>
|
||||
<artifactId>zfile</artifactId>
|
||||
<version>4.2.0</version>
|
||||
<name>zfile</name>
|
||||
<packaging>jar</packaging>
|
||||
<description>一个在线的文件浏览系统</description>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.6.8</version>
|
||||
<version>3.3.2</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
|
||||
<groupId>im.zhaojun</groupId>
|
||||
<artifactId>zfile</artifactId>
|
||||
<version>4.1.1</version>
|
||||
<name>zfile</name>
|
||||
<packaging>war</packaging>
|
||||
<description>一个在线的文件浏览系统</description>
|
||||
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
<org.mapstruct.version>1.5.1.Final</org.mapstruct.version>
|
||||
<skipTests>true</skipTests>
|
||||
|
||||
<java.version>21</java.version>
|
||||
<maven.compiler.source>21</maven.compiler.source>
|
||||
<maven.compiler.target>21</maven.compiler.target>
|
||||
|
||||
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
|
||||
<org.mapstruct.version>1.5.3.Final</org.mapstruct.version>
|
||||
<snakeyaml.version>2.0</snakeyaml.version>
|
||||
<jackson-bom.version>2.14.1</jackson-bom.version>
|
||||
<sqlite-jdbc.version>3.46.0.1</sqlite-jdbc.version>
|
||||
<flyway.version>10.12.0</flyway.version>
|
||||
|
||||
<lombok.version>1.18.32</lombok.version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>software.amazon.awssdk</groupId>
|
||||
<artifactId>bom</artifactId>
|
||||
<version>2.24.3</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
<!-- spring boot 官方相关 -->
|
||||
<!-- spring boot 官方相关-->
|
||||
<dependency>
|
||||
<groupId>org.graalvm.sdk</groupId>
|
||||
<artifactId>graal-sdk</artifactId>
|
||||
<version>24.1.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
@@ -31,11 +64,16 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-aop</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-cache</artifactId>
|
||||
@@ -49,12 +87,10 @@
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- 数据库相关 -->
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<version>8.0.29</version>
|
||||
<groupId>com.mysql</groupId>
|
||||
<artifactId>mysql-connector-j</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -64,93 +100,132 @@
|
||||
<dependency>
|
||||
<groupId>org.flywaydb</groupId>
|
||||
<artifactId>flyway-core</artifactId>
|
||||
<version>7.15.0</version>
|
||||
<version>${flyway.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.flywaydb</groupId>
|
||||
<artifactId>flyway-mysql</artifactId>
|
||||
<version>${flyway.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||
<version>3.5.2</version>
|
||||
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
|
||||
<version>3.5.6</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- 存储策略相关 SDK、 工具类-->
|
||||
<!-- 存储策略相关 API, 对象存储、FTP、 Rest API-->
|
||||
<dependency>
|
||||
<groupId>com.upyun</groupId>
|
||||
<artifactId>java-sdk</artifactId>
|
||||
<version>4.1.3</version>
|
||||
<version>4.2.3</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/software.amazon.awssdk/s3 -->
|
||||
<dependency>
|
||||
<groupId>com.amazonaws</groupId>
|
||||
<artifactId>aws-java-sdk-s3</artifactId>
|
||||
<version>1.12.261</version>
|
||||
<groupId>software.amazon.awssdk</groupId>
|
||||
<artifactId>s3</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.qiniu</groupId>
|
||||
<artifactId>qiniu-java-sdk</artifactId>
|
||||
<version>7.11.0</version>
|
||||
<version>7.12.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.jcraft</groupId>
|
||||
<groupId>com.github.mwiede</groupId>
|
||||
<artifactId>jsch</artifactId>
|
||||
<version>0.1.55</version>
|
||||
<version>0.2.20</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.lookfirst</groupId>
|
||||
<artifactId>sardine</artifactId>
|
||||
<version>5.10</version>
|
||||
<version>5.12</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-simple</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.api-client</groupId>
|
||||
<artifactId>google-api-client</artifactId>
|
||||
<version>1.35.2</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- 登陆/权限相关 -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-spring-boot-starter</artifactId>
|
||||
<version>1.30.0</version>
|
||||
<artifactId>sa-token-spring-boot3-starter</artifactId>
|
||||
<version>1.38.0</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- 文档相关 -->
|
||||
<dependency>
|
||||
<groupId>com.github.xiaoymin</groupId>
|
||||
<artifactId>knife4j-spring-boot-starter</artifactId>
|
||||
<version>3.0.3</version>
|
||||
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
|
||||
<version>4.5.0</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- 工具类 -->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>com.hierynomus</groupId>-->
|
||||
<!-- <artifactId>sshj</artifactId>-->
|
||||
<!-- <version>0.38.0</version>-->
|
||||
<!-- </dependency>-->
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>5.8.3</version>
|
||||
<version>5.8.28</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi-ooxml</artifactId>
|
||||
<version>5.2.5</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-compress</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-compress</artifactId>
|
||||
<version>1.26.2</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.24</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-net</groupId>
|
||||
<artifactId>commons-net</artifactId>
|
||||
<version>3.8.0</version>
|
||||
<version>3.11.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-pool2</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>1.2.83</version>
|
||||
<groupId>com.alibaba.fastjson2</groupId>
|
||||
<artifactId>fastjson2</artifactId>
|
||||
<version>2.0.29</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>30.1.1-jre</version>
|
||||
<version>33.2.0-jre</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mapstruct</groupId>
|
||||
@@ -164,7 +239,7 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>dev.samstevens.totp</groupId>
|
||||
<artifactId>totp-spring-boot-starter</artifactId>
|
||||
<artifactId>totp</artifactId>
|
||||
<version>1.7.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -175,18 +250,45 @@
|
||||
<dependency>
|
||||
<groupId>org.json</groupId>
|
||||
<artifactId>json</artifactId>
|
||||
<version>20200518</version>
|
||||
<version>20231013</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpmime</artifactId>
|
||||
<version>4.5.13</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents.client5</groupId>
|
||||
<artifactId>httpclient5</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk15on</artifactId>
|
||||
<version>1.70</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.retry</groupId>
|
||||
<artifactId>spring-retry</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
|
||||
<dependency>
|
||||
<groupId>commons-fileupload</groupId>
|
||||
<artifactId>commons-fileupload</artifactId>
|
||||
<version>1.5</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>dns-cache-manipulator</artifactId>
|
||||
<version>1.8.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.github.oshi</groupId>
|
||||
<artifactId>oshi-core</artifactId>
|
||||
<version>6.6.3</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -195,21 +297,13 @@
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<source>21</source>
|
||||
<target>21</target>
|
||||
<encoding>UTF-8</encoding>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
@@ -220,7 +314,7 @@
|
||||
<path>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.16</version>
|
||||
<version>1.18.32</version>
|
||||
</path>
|
||||
<path>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
@@ -234,29 +328,52 @@
|
||||
<groupId>org.flywaydb</groupId>
|
||||
<artifactId>flyway-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.uyoqu.framework</groupId>
|
||||
<artifactId>maven-plugin-starter</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>bin</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<jvms>
|
||||
<jvm>-Djava.security.egd=file:/dev/./urandom</jvm>
|
||||
<jvm>-Dfile.encoding=utf-8</jvm>
|
||||
<jvm>-Djava.net.preferIPv4Stack=false</jvm>
|
||||
<jvm>-Djava.net.preferIPv4Addresses=true</jvm>
|
||||
</jvms>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
||||
|
||||
</build>
|
||||
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>native</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.graalvm.buildtools</groupId>
|
||||
<artifactId>native-maven-plugin</artifactId>
|
||||
<extensions>true</extensions>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>build-native</id>
|
||||
<goals>
|
||||
<goal>compile-no-fork</goal>
|
||||
</goals>
|
||||
<phase>package</phase>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<fallback>false</fallback>
|
||||
<imageName>${project.name}</imageName>
|
||||
<metadataRepository>
|
||||
<enabled>true</enabled>
|
||||
</metadataRepository>
|
||||
<jvmArgs>
|
||||
<jvmArg>--add-opens=java.base/java.net=ALL-UNNAMED</jvmArg>
|
||||
<jvmArg>--add-opens=java.base/sun.net=ALL-UNNAMED</jvmArg>
|
||||
</jvmArgs>
|
||||
<buildArgs>
|
||||
<arg>
|
||||
-march=compatibility
|
||||
-H:+AddAllCharsets
|
||||
--features=im.zhaojun.zfile.aot.LambdaRegistrationFeature
|
||||
--features=im.zhaojun.zfile.aot.BouncyCastleFeature
|
||||
--features=im.zhaojun.zfile.aot.SQLiteNativeConfiguration
|
||||
</arg>
|
||||
</buildArgs>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
</project>
|
||||
@@ -1,173 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011-2022, baomidou (jobob@qq.com).
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.baomidou.mybatisplus.core.handlers;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.EnumValue;
|
||||
import com.baomidou.mybatisplus.annotation.IEnum;
|
||||
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
||||
import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
|
||||
import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||
import org.apache.ibatis.reflection.DefaultReflectorFactory;
|
||||
import org.apache.ibatis.reflection.MetaClass;
|
||||
import org.apache.ibatis.reflection.ReflectorFactory;
|
||||
import org.apache.ibatis.reflection.invoker.Invoker;
|
||||
import org.apache.ibatis.type.BaseTypeHandler;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* 自定义枚举属性转换器
|
||||
*
|
||||
* @author hubin
|
||||
* @since 2017-10-11
|
||||
*/
|
||||
public class MybatisEnumTypeHandler<E extends Enum<E>> extends BaseTypeHandler<E> {
|
||||
|
||||
private static final Map<String, String> TABLE_METHOD_OF_ENUM_TYPES = new ConcurrentHashMap<>();
|
||||
private static final ReflectorFactory REFLECTOR_FACTORY = new DefaultReflectorFactory();
|
||||
private final Class<E> enumClassType;
|
||||
private final Class<?> propertyType;
|
||||
private final Invoker getInvoker;
|
||||
|
||||
public MybatisEnumTypeHandler(Class<E> enumClassType) {
|
||||
if (enumClassType == null) {
|
||||
throw new IllegalArgumentException("Type argument cannot be null");
|
||||
}
|
||||
this.enumClassType = enumClassType;
|
||||
MetaClass metaClass = MetaClass.forClass(enumClassType, REFLECTOR_FACTORY);
|
||||
String name = "value";
|
||||
if (!IEnum.class.isAssignableFrom(enumClassType)) {
|
||||
name = findEnumValueFieldName(this.enumClassType).orElseThrow(() -> new IllegalArgumentException(String.format("Could not find @EnumValue in Class: %s.", this.enumClassType.getName())));
|
||||
}
|
||||
this.propertyType = ReflectionKit.resolvePrimitiveIfNecessary(metaClass.getGetterType(name));
|
||||
this.getInvoker = metaClass.getGetInvoker(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找标记标记EnumValue字段
|
||||
*
|
||||
* @param clazz class
|
||||
* @return EnumValue字段
|
||||
* @since 3.3.1
|
||||
*/
|
||||
public static Optional<String> findEnumValueFieldName(Class<?> clazz) {
|
||||
if (clazz != null && clazz.isEnum()) {
|
||||
String className = clazz.getName();
|
||||
return Optional.ofNullable(CollectionUtils.computeIfAbsent(TABLE_METHOD_OF_ENUM_TYPES, className, key -> {
|
||||
Optional<Field> fieldOptional = findEnumValueAnnotationField(clazz);
|
||||
return fieldOptional.map(Field::getName).orElse(null);
|
||||
}));
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
private static Optional<Field> findEnumValueAnnotationField(Class<?> clazz) {
|
||||
return Arrays.stream(clazz.getDeclaredFields()).filter(field -> field.isAnnotationPresent(EnumValue.class)).findFirst();
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为MP枚举处理
|
||||
*
|
||||
* @param clazz class
|
||||
* @return 是否为MP枚举处理
|
||||
* @since 3.3.1
|
||||
*/
|
||||
public static boolean isMpEnums(Class<?> clazz) {
|
||||
return clazz != null && clazz.isEnum() && (IEnum.class.isAssignableFrom(clazz) || findEnumValueFieldName(clazz).isPresent());
|
||||
}
|
||||
|
||||
@SuppressWarnings("Duplicates")
|
||||
@Override
|
||||
public void setNonNullParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType)
|
||||
throws SQLException {
|
||||
if (jdbcType == null) {
|
||||
ps.setObject(i, this.getValue(parameter));
|
||||
} else {
|
||||
// see r3589
|
||||
ps.setObject(i, this.getValue(parameter), jdbcType.TYPE_CODE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
|
||||
Object value = rs.getObject(columnName);
|
||||
if (null == value && rs.wasNull()) {
|
||||
return null;
|
||||
}
|
||||
return this.valueOf(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
|
||||
Object value = rs.getObject(columnIndex, this.propertyType);
|
||||
if (null == value && rs.wasNull()) {
|
||||
return null;
|
||||
}
|
||||
return this.valueOf(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
|
||||
Object value = cs.getObject(columnIndex, this.propertyType);
|
||||
if (null == value && cs.wasNull()) {
|
||||
return null;
|
||||
}
|
||||
return this.valueOf(value);
|
||||
}
|
||||
|
||||
private E valueOf(Object value) {
|
||||
E[] es = this.enumClassType.getEnumConstants();
|
||||
return Arrays.stream(es).filter((e) -> equalsValue(value, getValue(e))).findAny().orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 值比较
|
||||
*
|
||||
* @param sourceValue 数据库字段值
|
||||
* @param targetValue 当前枚举属性值
|
||||
* @return 是否匹配
|
||||
* @since 3.3.0
|
||||
*/
|
||||
protected boolean equalsValue(Object sourceValue, Object targetValue) {
|
||||
String sValue = StringUtils.toStringTrim(sourceValue);
|
||||
String tValue = StringUtils.toStringTrim(targetValue);
|
||||
if (sourceValue instanceof Number && targetValue instanceof Number
|
||||
&& new BigDecimal(sValue).compareTo(new BigDecimal(tValue)) == 0) {
|
||||
return true;
|
||||
}
|
||||
return Objects.equals(sValue, tValue);
|
||||
}
|
||||
|
||||
private Object getValue(Object object) {
|
||||
try {
|
||||
return this.getInvoker.invoke(object, new Object[0]);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw ExceptionUtils.mpe(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,16 +6,18 @@ import org.springframework.boot.web.servlet.ServletComponentScan;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||
|
||||
|
||||
/**
|
||||
* @author zhaojun
|
||||
*/
|
||||
@SpringBootApplication
|
||||
@EnableAspectJAutoProxy(exposeProxy = true, proxyTargetClass = true)
|
||||
@ServletComponentScan(basePackages = "im.zhaojun.zfile.*.filter")
|
||||
@ServletComponentScan(basePackages = {"im.zhaojun.zfile.core.filter", "im.zhaojun.zfile.module.storage.filter"})
|
||||
@ComponentScan(basePackages = "im.zhaojun.zfile.*")
|
||||
public class ZfileApplication {
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(ZfileApplication.class, args);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.controller;
|
||||
|
||||
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
|
||||
import com.github.xiaoymin.knife4j.annotations.ApiSort;
|
||||
import im.zhaojun.zfile.home.model.dto.CacheInfoDTO;
|
||||
import im.zhaojun.zfile.admin.service.StorageSourceService;
|
||||
import im.zhaojun.zfile.common.util.AjaxJson;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* 存储源缓存维护接口
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@RestController
|
||||
@Api(tags = "存储源模块-缓存")
|
||||
@ApiSort(5)
|
||||
@RequestMapping("/admin/cache")
|
||||
public class CacheController {
|
||||
|
||||
@Resource
|
||||
private StorageSourceService storageSourceService;
|
||||
|
||||
@ApiOperationSupport(order = 1)
|
||||
@ApiOperation(value = "启用存储源缓存", notes = "开启缓存后,N 秒内重复请求相同文件夹,不会重复调用 API。" +
|
||||
"参数 N 在配置文件中设置 {zfile.cache.timeout},默认为 1800 秒。")
|
||||
@ApiImplicitParam(paramType = "path", name = "storageId", value = "存储源 id", required = true)
|
||||
@PostMapping("/{storageId}/enable")
|
||||
public AjaxJson<Void> enableCache(@PathVariable("storageId") Integer storageId) {
|
||||
storageSourceService.updateCacheStatus(storageId, true);
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
|
||||
|
||||
@ApiOperationSupport(order = 2)
|
||||
@ApiOperation(value = "禁用存储源缓存")
|
||||
@ApiImplicitParam(paramType = "path", name = "storageId", value = "存储源 id", required = true)
|
||||
@PostMapping("/{storageId}/disable")
|
||||
public AjaxJson<Void> disableCache(@PathVariable("storageId") Integer storageId) {
|
||||
storageSourceService.updateCacheStatus(storageId, false);
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
|
||||
|
||||
@ApiOperationSupport(order = 3)
|
||||
@ApiOperation(value = "查看存储源缓存", notes = "可查看存储源缓存的所有目录路径")
|
||||
@ApiImplicitParam(paramType = "path", name = "storageId", value = "存储源 id", required = true)
|
||||
@GetMapping("/{storageId}/info")
|
||||
public AjaxJson<CacheInfoDTO> cacheInfo(@PathVariable("storageId") Integer storageId) {
|
||||
CacheInfoDTO cacheInfo = storageSourceService.findCacheInfo(storageId);
|
||||
return AjaxJson.getSuccessData(cacheInfo);
|
||||
}
|
||||
|
||||
|
||||
@ApiOperationSupport(order = 4)
|
||||
@ApiOperation(value = "刷新存储源缓存", notes = "刷新存储源缓存路径,系统会重新预热此路径的内容")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(paramType = "path", name = "storageId", value = "存储源 id", required = true),
|
||||
@ApiImplicitParam(paramType = "body", name = "key", value = "缓存 key", required = true)
|
||||
})
|
||||
@PostMapping("/{storageId}/refresh")
|
||||
public AjaxJson<Void> refreshCache(@PathVariable("storageId") Integer storageId, String key) throws Exception {
|
||||
storageSourceService.refreshCache(storageId, key);
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
|
||||
|
||||
@ApiOperationSupport(order = 5)
|
||||
@ApiOperation(value = "开启缓存自动刷新", notes = "开启后每隔 N 秒检测到期的缓存, 对于过期缓存尝试调用 API, 重新写入缓存." +
|
||||
"参数 N 在配置文件中设置 {zfile.cache.auto-refresh-interval},默认为 5 秒。")
|
||||
@ApiImplicitParam(paramType = "path", name = "storageId", value = "存储源 id", required = true)
|
||||
@PostMapping("/{storageId}/auto-refresh/start")
|
||||
public AjaxJson<Void> enableAutoRefresh(@PathVariable("storageId") Integer storageId) {
|
||||
storageSourceService.startAutoCacheRefresh(storageId);
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
|
||||
|
||||
@ApiOperationSupport(order = 5)
|
||||
@ApiOperation(value = "关闭缓存自动刷新")
|
||||
@ApiImplicitParam(paramType = "path", name = "storageId", value = "存储源 id", required = true)
|
||||
@PostMapping("/{storageId}/auto-refresh/stop")
|
||||
public AjaxJson<Void> disableAutoRefresh(@PathVariable("storageId") Integer storageId) {
|
||||
storageSourceService.stopAutoCacheRefresh(storageId);
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
|
||||
|
||||
@ApiOperationSupport(order = 6)
|
||||
@ApiOperation(value = "清空缓存")
|
||||
@ApiImplicitParam(paramType = "path", name = "storageId", value = "存储源 id", required = true)
|
||||
@PostMapping("/{storageId}/clear")
|
||||
public AjaxJson<Void> clearCache(@PathVariable("storageId") Integer storageId) {
|
||||
storageSourceService.clearCache(storageId);
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,150 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.controller.link;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.OrderItem;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
|
||||
import com.github.xiaoymin.knife4j.annotations.ApiSort;
|
||||
import im.zhaojun.zfile.admin.convert.DownloadLogConvert;
|
||||
import im.zhaojun.zfile.admin.model.entity.DownloadLog;
|
||||
import im.zhaojun.zfile.admin.model.entity.StorageSource;
|
||||
import im.zhaojun.zfile.admin.model.request.link.BatchDeleteRequest;
|
||||
import im.zhaojun.zfile.admin.model.request.link.QueryDownloadLogRequest;
|
||||
import im.zhaojun.zfile.admin.model.result.link.DownloadLogResult;
|
||||
import im.zhaojun.zfile.admin.service.DownloadLogService;
|
||||
import im.zhaojun.zfile.admin.service.StorageSourceService;
|
||||
import im.zhaojun.zfile.common.util.AjaxJson;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* 直链下载日志接口
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Api(tags = "直链日志管理")
|
||||
@ApiSort(7)
|
||||
@Controller
|
||||
@RequestMapping("/admin/download/log")
|
||||
public class DownloadLogManagerController {
|
||||
|
||||
@Resource
|
||||
private StorageSourceService storageSourceService;
|
||||
|
||||
@Resource
|
||||
private DownloadLogConvert downloadLogConvert;
|
||||
|
||||
@Resource
|
||||
private DownloadLogService downloadLogService;
|
||||
|
||||
@ApiOperationSupport(order = 1)
|
||||
@GetMapping("/list")
|
||||
@ApiOperation(value = "直链下载日志")
|
||||
@ResponseBody
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(paramType = "query", name = "key", value = "直链 key"),
|
||||
@ApiImplicitParam(paramType = "query", name = "page", value = "分页页数"),
|
||||
@ApiImplicitParam(paramType = "query", name = "limit", value = "每页条数"),
|
||||
@ApiImplicitParam(paramType = "query", name = "orderBy", defaultValue = "createDate", value = "排序字段"),
|
||||
@ApiImplicitParam(paramType = "query", name = "orderDirection", defaultValue = "desc", value = "排序顺序")
|
||||
})
|
||||
public AjaxJson<?> list(QueryDownloadLogRequest queryDownloadLogRequest,
|
||||
@RequestParam(required = false, defaultValue = "create_time") String orderBy,
|
||||
@RequestParam(required = false, defaultValue = "desc") String orderDirection) {
|
||||
Page<DownloadLog> pages = Page.of(queryDownloadLogRequest.getPage(), queryDownloadLogRequest.getLimit());
|
||||
boolean asc = Objects.equals(orderDirection, "asc");
|
||||
pages.addOrder(new OrderItem(orderBy, asc));
|
||||
|
||||
DownloadLog downloadLog = new DownloadLog();
|
||||
QueryWrapper<DownloadLog> queryWrapper = new QueryWrapper<>(downloadLog);
|
||||
|
||||
if (StrUtil.isNotEmpty(queryDownloadLogRequest.getStorageKey())) {
|
||||
queryWrapper.eq("storage_key", queryDownloadLogRequest.getStorageKey());
|
||||
}
|
||||
if (StrUtil.isNotEmpty(queryDownloadLogRequest.getPath())) {
|
||||
queryWrapper.like("path", queryDownloadLogRequest.getPath());
|
||||
}
|
||||
if (StrUtil.isNotEmpty(queryDownloadLogRequest.getShortKey())) {
|
||||
queryWrapper.like("short_key", queryDownloadLogRequest.getShortKey());
|
||||
}
|
||||
if (StrUtil.isNotEmpty(queryDownloadLogRequest.getIp())) {
|
||||
queryWrapper.like("ip", queryDownloadLogRequest.getIp());
|
||||
}
|
||||
if (StrUtil.isNotEmpty(queryDownloadLogRequest.getReferer())) {
|
||||
queryWrapper.like("referer", queryDownloadLogRequest.getReferer());
|
||||
}
|
||||
if (StrUtil.isNotEmpty(queryDownloadLogRequest.getUserAgent())) {
|
||||
queryWrapper.like("user_agent", queryDownloadLogRequest.getUserAgent());
|
||||
}
|
||||
if (ObjectUtil.isNotEmpty(queryDownloadLogRequest.getDateFrom())) {
|
||||
queryWrapper.ge("create_time", queryDownloadLogRequest.getDateFrom());
|
||||
}
|
||||
if (ObjectUtil.isNotEmpty(queryDownloadLogRequest.getDateTo())) {
|
||||
queryWrapper.le("create_time", queryDownloadLogRequest.getDateFrom());
|
||||
}
|
||||
Page<DownloadLog> selectResult = downloadLogService.page(pages, queryWrapper);
|
||||
|
||||
long total = selectResult.getTotal();
|
||||
List<DownloadLog> records = selectResult.getRecords();
|
||||
|
||||
Map<String, StorageSource> cache = new HashMap<>();
|
||||
|
||||
Stream<DownloadLogResult> shortLinkResultList = records.stream().map(model -> {
|
||||
String storageKey = model.getStorageKey();
|
||||
StorageSource storageSource;
|
||||
if (cache.containsKey(storageKey)) {
|
||||
storageSource = cache.get(storageKey);
|
||||
} else {
|
||||
storageSource = storageSourceService.findByStorageKey(storageKey);
|
||||
cache.put(storageKey, storageSource);
|
||||
}
|
||||
return downloadLogConvert.entityToResultList(model, storageSource);
|
||||
});
|
||||
return AjaxJson.getPageData(total, shortLinkResultList);
|
||||
}
|
||||
|
||||
|
||||
@ApiOperationSupport(order = 2)
|
||||
@DeleteMapping("/delete/{id}")
|
||||
@ApiOperation(value = "删除直链")
|
||||
@ApiImplicitParam(paramType = "path", name = "id", value = "直链 id", required = true)
|
||||
@ResponseBody
|
||||
public AjaxJson<Void> deleteById(@PathVariable Integer id) {
|
||||
downloadLogService.removeById(id);
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
|
||||
|
||||
@ApiOperationSupport(order = 3)
|
||||
@PostMapping("/delete/batch")
|
||||
@ResponseBody
|
||||
@ApiImplicitParam(paramType = "query", name = "ids", value = "直链 id", required = true)
|
||||
@ApiOperation(value = "批量删除直链")
|
||||
public AjaxJson<Void> batchDelete(@RequestBody BatchDeleteRequest batchDeleteRequest) {
|
||||
List<Integer> ids = batchDeleteRequest.getIds();
|
||||
downloadLogService.removeBatchByIds(ids);
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,143 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.controller.link;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.OrderItem;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
|
||||
import com.github.xiaoymin.knife4j.annotations.ApiSort;
|
||||
import im.zhaojun.zfile.admin.convert.ShortLinkConvert;
|
||||
import im.zhaojun.zfile.admin.model.entity.ShortLink;
|
||||
import im.zhaojun.zfile.admin.model.entity.StorageSource;
|
||||
import im.zhaojun.zfile.admin.model.request.link.BatchDeleteRequest;
|
||||
import im.zhaojun.zfile.admin.model.result.link.ShortLinkResult;
|
||||
import im.zhaojun.zfile.admin.service.ShortLinkService;
|
||||
import im.zhaojun.zfile.admin.service.StorageSourceService;
|
||||
import im.zhaojun.zfile.common.util.AjaxJson;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* 直链管理接口
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Api(tags = "直链管理")
|
||||
@ApiSort(7)
|
||||
@Controller
|
||||
@RequestMapping("/admin")
|
||||
public class ShortLinkManagerController {
|
||||
|
||||
@Resource
|
||||
private ShortLinkService shortLinkService;
|
||||
|
||||
@Resource
|
||||
private StorageSourceService storageSourceService;
|
||||
|
||||
@Resource
|
||||
private ShortLinkConvert shortLinkConvert;
|
||||
|
||||
@ApiOperationSupport(order = 1)
|
||||
@GetMapping("/link/list")
|
||||
@ApiOperation(value = "搜索短链")
|
||||
@ResponseBody
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(paramType = "query", name = "key", value = "短链 key"),
|
||||
@ApiImplicitParam(paramType = "query", name = "storageId", value = "存储源 ID"),
|
||||
@ApiImplicitParam(paramType = "query", name = "url", value = "短链 url"),
|
||||
@ApiImplicitParam(paramType = "query", name = "dateFrom", value = "短链创建时间从"),
|
||||
@ApiImplicitParam(paramType = "query", name = "dateTo", value = "短链创建时间至"),
|
||||
@ApiImplicitParam(paramType = "query", name = "page", value = "分页页数"),
|
||||
@ApiImplicitParam(paramType = "query", name = "limit", value = "每页条数"),
|
||||
@ApiImplicitParam(paramType = "query", name = "orderBy", defaultValue = "createDate", value = "排序字段"),
|
||||
@ApiImplicitParam(paramType = "query", name = "orderDirection", defaultValue = "desc", value = "排序顺序")
|
||||
})
|
||||
public AjaxJson<?> list(String key, String storageId,
|
||||
String url,
|
||||
String dateFrom,
|
||||
String dateTo,
|
||||
Integer page,
|
||||
Integer limit,
|
||||
@RequestParam(required = false, defaultValue = "create_date") String orderBy,
|
||||
@RequestParam(required = false, defaultValue = "desc") String orderDirection) {
|
||||
Page<ShortLink> pages = Page.of(page, limit);
|
||||
boolean asc = Objects.equals(orderDirection, "asc");
|
||||
pages.addOrder(new OrderItem(orderBy, asc));
|
||||
QueryWrapper<ShortLink> queryWrapper = new QueryWrapper<>(new ShortLink());
|
||||
if (StrUtil.isNotEmpty(storageId)) {
|
||||
queryWrapper.eq("storage_id", storageId);
|
||||
}
|
||||
if (StrUtil.isNotEmpty(key)) {
|
||||
queryWrapper.like("short_key", key);
|
||||
}
|
||||
if (StrUtil.isNotEmpty(url)) {
|
||||
queryWrapper.like("url", url);
|
||||
}
|
||||
if (StrUtil.isNotEmpty(dateFrom)) {
|
||||
queryWrapper.ge("create_date", dateFrom);
|
||||
}
|
||||
if (StrUtil.isNotEmpty(dateTo)) {
|
||||
queryWrapper.le("create_date", dateTo);
|
||||
}
|
||||
Page<ShortLink> selectResult = shortLinkService.page(pages, queryWrapper);
|
||||
|
||||
long total = selectResult.getTotal();
|
||||
List<ShortLink> records = selectResult.getRecords();
|
||||
|
||||
Map<Integer, StorageSource> cache = new HashMap<>();
|
||||
|
||||
Stream<ShortLinkResult> shortLinkResultList = records.stream().map(shortLink -> {
|
||||
Integer shortLinkStorageId = shortLink.getStorageId();
|
||||
StorageSource storageSource;
|
||||
if (cache.containsKey(shortLinkStorageId)) {
|
||||
storageSource = cache.get(shortLinkStorageId);
|
||||
} else {
|
||||
storageSource = storageSourceService.findById(shortLinkStorageId);
|
||||
cache.put(shortLinkStorageId, storageSource);
|
||||
}
|
||||
return shortLinkConvert.entityToResultList(shortLink, storageSource);
|
||||
});
|
||||
return AjaxJson.getPageData(total, shortLinkResultList);
|
||||
}
|
||||
|
||||
|
||||
@ApiOperationSupport(order = 2)
|
||||
@DeleteMapping("/link/delete/{id}")
|
||||
@ApiOperation(value = "删除短链")
|
||||
@ApiImplicitParam(paramType = "path", name = "id", value = "短链 id", required = true)
|
||||
@ResponseBody
|
||||
public AjaxJson<Void> deleteById(@PathVariable Integer id) {
|
||||
shortLinkService.removeById(id);
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
|
||||
|
||||
@ApiOperationSupport(order = 3)
|
||||
@PostMapping("/link/delete/batch")
|
||||
@ResponseBody
|
||||
@ApiImplicitParam(paramType = "query", name = "ids", value = "短链 id", required = true)
|
||||
@ApiOperation(value = "批量删除短链")
|
||||
public AjaxJson<Void> batchDelete(@RequestBody BatchDeleteRequest batchDeleteRequest) {
|
||||
shortLinkService.removeBatchByIds(batchDeleteRequest.getIds());
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.controller.setting;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.crypto.SecureUtil;
|
||||
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
|
||||
import com.github.xiaoymin.knife4j.annotations.ApiSort;
|
||||
import im.zhaojun.zfile.admin.model.request.setting.UpdateLinkSettingRequest;
|
||||
import im.zhaojun.zfile.admin.model.request.setting.UpdateSecuritySettingRequest;
|
||||
import im.zhaojun.zfile.admin.model.request.setting.UpdateSiteSettingRequest;
|
||||
import im.zhaojun.zfile.admin.model.request.setting.UpdateUserNameAndPasswordRequest;
|
||||
import im.zhaojun.zfile.admin.model.request.setting.UpdateViewSettingRequest;
|
||||
import im.zhaojun.zfile.admin.service.SystemConfigService;
|
||||
import im.zhaojun.zfile.common.util.AjaxJson;
|
||||
import im.zhaojun.zfile.home.model.dto.SystemConfigDTO;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
|
||||
/**
|
||||
* 站点设定值接口
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Api(tags = "站点设置模块")
|
||||
@ApiSort(2)
|
||||
@RestController
|
||||
@RequestMapping("/admin")
|
||||
public class SettingController {
|
||||
|
||||
@Resource
|
||||
private SystemConfigService systemConfigService;
|
||||
|
||||
@ApiOperationSupport(order = 1)
|
||||
@ApiOperation(value = "获取站点信息",
|
||||
notes = "获取站点相关信息,如站点名称,风格样式,是否显示公告,是否显示文档区,自定义 CSS,JS 等参数")
|
||||
@GetMapping("/config")
|
||||
public AjaxJson<SystemConfigDTO> getConfig() {
|
||||
SystemConfigDTO systemConfigDTO = systemConfigService.getSystemConfig();
|
||||
return AjaxJson.getSuccessData(systemConfigDTO);
|
||||
}
|
||||
|
||||
|
||||
@ApiOperationSupport(order = 2)
|
||||
@ApiOperation(value = "修改管理员账号密码")
|
||||
@PutMapping("/config/password")
|
||||
public AjaxJson<?> updatePwd(@Valid @RequestBody UpdateUserNameAndPasswordRequest settingRequest) {
|
||||
SystemConfigDTO systemConfigDTO = new SystemConfigDTO();
|
||||
BeanUtils.copyProperties(settingRequest, systemConfigDTO);
|
||||
String password = systemConfigDTO.getPassword();
|
||||
if (StrUtil.isNotEmpty(password)) {
|
||||
systemConfigDTO.setPassword(SecureUtil.md5(password));
|
||||
}
|
||||
systemConfigService.updateSystemConfig(systemConfigDTO);
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
|
||||
|
||||
@ApiOperationSupport(order = 3)
|
||||
@ApiOperation(value = "修改站点设置")
|
||||
@PutMapping("/config/site")
|
||||
public AjaxJson<?> updateSiteSetting(@Valid @RequestBody UpdateSiteSettingRequest settingRequest) {
|
||||
SystemConfigDTO systemConfigDTO = new SystemConfigDTO();
|
||||
BeanUtils.copyProperties(settingRequest, systemConfigDTO);
|
||||
systemConfigService.updateSystemConfig(systemConfigDTO);
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
|
||||
|
||||
@ApiOperationSupport(order = 4)
|
||||
@ApiOperation(value = "修改显示设置")
|
||||
@PutMapping("/config/view")
|
||||
public AjaxJson<?> updateViewSetting(@Valid @RequestBody UpdateViewSettingRequest settingRequest) {
|
||||
SystemConfigDTO systemConfigDTO = new SystemConfigDTO();
|
||||
BeanUtils.copyProperties(settingRequest, systemConfigDTO);
|
||||
systemConfigService.updateSystemConfig(systemConfigDTO);
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
|
||||
|
||||
@ApiOperationSupport(order = 5)
|
||||
@ApiOperation(value = "修改登陆安全设置")
|
||||
@PutMapping("/config/security")
|
||||
public AjaxJson<?> updateSecuritySetting(@Valid @RequestBody UpdateSecuritySettingRequest settingRequest) {
|
||||
SystemConfigDTO systemConfigDTO = new SystemConfigDTO();
|
||||
BeanUtils.copyProperties(settingRequest, systemConfigDTO);
|
||||
systemConfigService.updateSystemConfig(systemConfigDTO);
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
|
||||
|
||||
@ApiOperationSupport(order = 6)
|
||||
@ApiOperation(value = "修改直链设置")
|
||||
@PutMapping("/config/link")
|
||||
public AjaxJson<?> updateLinkSetting(@Valid @RequestBody UpdateLinkSettingRequest settingRequest) {
|
||||
SystemConfigDTO systemConfigDTO = new SystemConfigDTO();
|
||||
BeanUtils.copyProperties(settingRequest, systemConfigDTO);
|
||||
systemConfigService.updateSystemConfig(systemConfigDTO);
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,148 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.controller.stroage;
|
||||
|
||||
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
|
||||
import com.github.xiaoymin.knife4j.annotations.ApiSort;
|
||||
import im.zhaojun.zfile.admin.model.entity.StorageSource;
|
||||
import im.zhaojun.zfile.admin.model.request.SaveStorageSourceRequest;
|
||||
import im.zhaojun.zfile.admin.model.result.storage.StorageSourceAdminResult;
|
||||
import im.zhaojun.zfile.admin.service.StorageSourceService;
|
||||
import im.zhaojun.zfile.common.cache.RefreshTokenCache;
|
||||
import im.zhaojun.zfile.common.util.AjaxJson;
|
||||
import im.zhaojun.zfile.home.convert.StorageSourceConvert;
|
||||
import im.zhaojun.zfile.home.model.dto.StorageSourceDTO;
|
||||
import im.zhaojun.zfile.home.model.request.UpdateStorageSortRequest;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 存储源基础设置模块接口
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Api(tags = "存储源模块-基础")
|
||||
@ApiSort(3)
|
||||
@RestController
|
||||
@RequestMapping("/admin")
|
||||
public class StorageSourceController {
|
||||
|
||||
@Resource
|
||||
private StorageSourceService storageSourceService;
|
||||
|
||||
@Resource
|
||||
private StorageSourceConvert storageSourceConvert;
|
||||
|
||||
|
||||
@ApiOperationSupport(order = 1)
|
||||
@ApiOperation(value = "获取所有存储源列表", notes = "获取所有添加的存储源列表,按照排序值由小到大排序")
|
||||
@GetMapping("/storages")
|
||||
public AjaxJson<List<StorageSourceAdminResult>> storageList() {
|
||||
List<StorageSource> list = storageSourceService.findAllOrderByOrderNum();
|
||||
|
||||
List<StorageSourceAdminResult> storageSourceAdminResults = storageSourceConvert.entityToAdminResultList(list);
|
||||
|
||||
storageSourceAdminResults.forEach(storageSourceAdminResult -> {
|
||||
RefreshTokenCache.RefreshTokenInfo refreshTokenInfo = RefreshTokenCache.getRefreshTokenInfo(storageSourceAdminResult.getId());
|
||||
storageSourceAdminResult.setRefreshTokenInfo(refreshTokenInfo);
|
||||
});
|
||||
|
||||
return AjaxJson.getSuccessData(storageSourceAdminResults);
|
||||
}
|
||||
|
||||
|
||||
@ApiOperationSupport(order = 2)
|
||||
@ApiOperation(value = "获取指定存储源参数", notes = "获取指定存储源基本信息及其参数")
|
||||
@ApiImplicitParam(paramType = "path", name = "storageId", value = "存储源 id", required = true)
|
||||
@GetMapping("/storage/{storageId}")
|
||||
public AjaxJson<StorageSourceDTO> storageItem(@PathVariable Integer storageId) {
|
||||
StorageSourceDTO storageSourceDTO = storageSourceService.findStorageSourceDTOById(storageId);
|
||||
return AjaxJson.getSuccessData(storageSourceDTO);
|
||||
}
|
||||
|
||||
|
||||
@ApiOperationSupport(order = 3)
|
||||
@ApiOperation(value = "保存存储源参数", notes = "保存存储源的所有参数")
|
||||
@PostMapping("/storage")
|
||||
public AjaxJson<Void> saveStorageItem(@RequestBody SaveStorageSourceRequest saveStorageSourceRequest) {
|
||||
storageSourceService.saveStorageSource(saveStorageSourceRequest);
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
|
||||
|
||||
@ApiOperationSupport(order = 4)
|
||||
@ApiOperation(value = "删除存储源", notes = "删除存储源基本设置和拓展设置")
|
||||
@ApiImplicitParam(paramType = "path", name = "storageId", value = "存储源 id", required = true)
|
||||
@DeleteMapping("/storage/{storageId}")
|
||||
public AjaxJson<Void> deleteStorageItem(@PathVariable Integer storageId) {
|
||||
storageSourceService.deleteById(storageId);
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
|
||||
|
||||
@ApiOperationSupport(order = 5)
|
||||
@ApiOperation(value = "启用存储源", notes = "开启存储源后可在前台显示")
|
||||
@ApiImplicitParam(paramType = "path", name = "storageId", value = "存储源 id", required = true)
|
||||
@PostMapping("/storage/{storageId}/enable")
|
||||
public AjaxJson<Void> enable(@PathVariable Integer storageId) {
|
||||
StorageSource storageSource = storageSourceService.findById(storageId);
|
||||
storageSource.setEnable(true);
|
||||
storageSourceService.updateById(storageSource);
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
|
||||
|
||||
@ApiOperationSupport(order = 6)
|
||||
@ApiOperation(value = "停止存储源", notes = "停用存储源后不在前台显示")
|
||||
@ApiImplicitParam(paramType = "path", name = "storageId", value = "存储源 id", required = true)
|
||||
@PostMapping("/storage/{storageId}/disable")
|
||||
public AjaxJson<Void> disable(@PathVariable Integer storageId) {
|
||||
StorageSource storageSource = storageSourceService.findById(storageId);
|
||||
storageSource.setEnable(false);
|
||||
storageSourceService.updateById(storageSource);
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
|
||||
|
||||
@ApiOperationSupport(order = 7)
|
||||
@ApiOperation(value = "更新存储源顺序")
|
||||
@PostMapping("/storage/sort")
|
||||
public AjaxJson<Void> updateStorageSort(@RequestBody List<UpdateStorageSortRequest> updateStorageSortRequestList) {
|
||||
storageSourceService.updateStorageSort(updateStorageSortRequestList);
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
|
||||
|
||||
@ApiOperationSupport(order = 8)
|
||||
@ApiOperation(value = "校验存储源 key 是否重复")
|
||||
@ApiImplicitParam(paramType = "query", name = "storageKey", value = "存储源 key", required = true)
|
||||
@GetMapping("/storage/exist/key")
|
||||
public AjaxJson<Boolean> existKey(String storageKey) {
|
||||
boolean exist = storageSourceService.existByStorageKey(storageKey);
|
||||
return AjaxJson.getSuccessData(exist);
|
||||
}
|
||||
|
||||
@ApiOperationSupport(order = 9)
|
||||
@ApiOperation(value = "修改 readme 兼容模式", notes = "修改 readme 兼容模式是否启用")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(paramType = "path", name = "storageId", value = "存储源 id", required = true),
|
||||
@ApiImplicitParam(paramType = "path", name = "status", value = "存储源兼容模式状态", required = true)
|
||||
})
|
||||
@PostMapping("/storage/{storageId}/compatibility_readme/{status}")
|
||||
public AjaxJson<Void> changeCompatibilityReadme(@PathVariable Integer storageId, @PathVariable Boolean status) {
|
||||
StorageSource storageSource = storageSourceService.findById(storageId);
|
||||
storageSource.setCompatibilityReadme(status);
|
||||
storageSourceService.updateById(storageSource);
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.controller.stroage;
|
||||
|
||||
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
|
||||
import com.github.xiaoymin.knife4j.annotations.ApiSort;
|
||||
import im.zhaojun.zfile.admin.model.entity.FilterConfig;
|
||||
import im.zhaojun.zfile.admin.service.FilterConfigService;
|
||||
import im.zhaojun.zfile.common.util.AjaxJson;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 存储源过滤器维护接口
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Api(tags = "存储源模块-过滤文件")
|
||||
@ApiSort(6)
|
||||
@RestController
|
||||
@RequestMapping("/admin")
|
||||
public class StorageSourceFilterController {
|
||||
|
||||
@Resource
|
||||
private FilterConfigService filterConfigService;
|
||||
|
||||
@ApiOperationSupport(order = 1)
|
||||
@ApiOperation(value = "获取存储源过滤文件列表", notes = "根据存储源 ID 获取存储源设置的过滤文件列表")
|
||||
@ApiImplicitParam(paramType = "path", name = "storageId", value = "存储源 id", required = true)
|
||||
@GetMapping("/storage/{storageId}/filters")
|
||||
public AjaxJson<List<FilterConfig>> getFilters(@PathVariable Integer storageId) {
|
||||
return AjaxJson.getSuccessData(filterConfigService.findByStorageId(storageId));
|
||||
}
|
||||
|
||||
|
||||
@ApiOperationSupport(order = 2)
|
||||
@ApiOperation(value = "保存存储源过滤文件列表", notes = "保存指定存储源 ID 设置的过滤文件列表")
|
||||
@ApiImplicitParam(paramType = "path", name = "storageId", value = "存储源 id", required = true)
|
||||
@PostMapping("/storage/{storageId}/filters")
|
||||
public AjaxJson<Void> saveFilters(@PathVariable Integer storageId, @RequestBody List<FilterConfig> filter) {
|
||||
filterConfigService.batchSave(storageId, filter);
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.controller.stroage;
|
||||
|
||||
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
|
||||
import com.github.xiaoymin.knife4j.annotations.ApiSort;
|
||||
import im.zhaojun.zfile.admin.model.entity.PasswordConfig;
|
||||
import im.zhaojun.zfile.admin.service.PasswordConfigService;
|
||||
import im.zhaojun.zfile.common.util.AjaxJson;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 存储源密码维护接口
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Api(tags = "存储源模块-密码文件夹")
|
||||
@ApiSort(6)
|
||||
@RestController
|
||||
@RequestMapping("/admin")
|
||||
public class StorageSourcePasswordController {
|
||||
|
||||
@Resource
|
||||
private PasswordConfigService passwordConfigService;
|
||||
|
||||
@ApiOperationSupport(order = 1)
|
||||
@ApiOperation(value = "获取存储源密码文件夹列表", notes = "根据存储源 ID 获取存储源设置的密码文件夹列表")
|
||||
@ApiImplicitParam(paramType = "path", name = "storageId", value = "存储源 id", required = true)
|
||||
@GetMapping("/storage/{storageId}/password")
|
||||
public AjaxJson<List<PasswordConfig>> getPasswordList(@PathVariable Integer storageId) {
|
||||
return AjaxJson.getSuccessData(passwordConfigService.findByStorageId(storageId));
|
||||
}
|
||||
|
||||
|
||||
@ApiOperationSupport(order = 2)
|
||||
@ApiOperation(value = "保存存储源密码文件夹列表", notes = "保存指定存储源 ID 设置的密码文件夹列表")
|
||||
@ApiImplicitParam(paramType = "path", name = "storageId", value = "存储源 id", required = true)
|
||||
@PostMapping("/storage/{storageId}/password")
|
||||
public AjaxJson<Void> savePasswordList(@PathVariable Integer storageId, @RequestBody List<PasswordConfig> password) {
|
||||
passwordConfigService.batchSave(storageId, password);
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.controller.stroage;
|
||||
|
||||
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
|
||||
import com.github.xiaoymin.knife4j.annotations.ApiSort;
|
||||
import im.zhaojun.zfile.admin.model.entity.ReadmeConfig;
|
||||
import im.zhaojun.zfile.admin.service.ReadmeConfigService;
|
||||
import im.zhaojun.zfile.common.util.AjaxJson;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 存储源文档模块维护接口
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Api(tags = "存储源模块-README")
|
||||
@ApiSort(7)
|
||||
@RestController
|
||||
@RequestMapping("/admin")
|
||||
public class StorageSourceReadmeController {
|
||||
|
||||
@Resource
|
||||
private ReadmeConfigService readmeConfigService;
|
||||
|
||||
@ApiOperationSupport(order = 1)
|
||||
@ApiOperation(value = "获取存储源文档文件夹列表", notes = "根据存储源 ID 获取存储源设置的文档文件夹列表")
|
||||
@ApiImplicitParam(paramType = "path", name = "storageId", value = "存储源 id", required = true)
|
||||
@GetMapping("/storage/{storageId}/readme")
|
||||
public AjaxJson<List<ReadmeConfig>> getReadmeList(@PathVariable Integer storageId) {
|
||||
return AjaxJson.getSuccessData(readmeConfigService.findByStorageId(storageId));
|
||||
}
|
||||
|
||||
|
||||
@ApiOperationSupport(order = 2)
|
||||
@ApiOperation(value = "保存存储源文档文件夹列表", notes = "保存指定存储源 ID 设置的文档文件夹列表")
|
||||
@ApiImplicitParam(paramType = "path", name = "storageId", value = "存储源 id", required = true)
|
||||
@PostMapping("/storage/{storageId}/readme")
|
||||
public AjaxJson<Void> saveReadmeList(@PathVariable Integer storageId, @RequestBody List<ReadmeConfig> readme) {
|
||||
readmeConfigService.batchSave(storageId, readme);
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.exception;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 禁止的文件操作异常
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Getter
|
||||
public class ForbidFileOperationException extends RuntimeException {
|
||||
|
||||
private final Integer storageId;
|
||||
|
||||
private final String action;
|
||||
|
||||
public ForbidFileOperationException(Integer storageId, String action) {
|
||||
this.storageId = storageId;
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.exception;
|
||||
|
||||
import im.zhaojun.zfile.admin.model.param.IStorageParam;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 存储源自动设置 cors 异常
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Getter
|
||||
public class StorageSourceAutoConfigCorsException extends RuntimeException {
|
||||
|
||||
private final IStorageParam iStorageParam;
|
||||
|
||||
public StorageSourceAutoConfigCorsException(String message, Throwable cause, IStorageParam iStorageParam) {
|
||||
super(message, cause);
|
||||
this.iStorageParam = iStorageParam;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import im.zhaojun.zfile.admin.model.entity.DownloadLog;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 下载日志 Mapper 接口
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Mapper
|
||||
public interface DownloadLogMapper extends BaseMapper<DownloadLog> {
|
||||
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import im.zhaojun.zfile.admin.model.entity.ShortLink;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
/**
|
||||
* 短链接配置表 Mapper 接口
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Mapper
|
||||
public interface ShortLinkMapper extends BaseMapper<ShortLink> {
|
||||
|
||||
/**
|
||||
* 根据短链接 key 查询短链接
|
||||
*
|
||||
* @param key
|
||||
* 短链接 key
|
||||
*
|
||||
* @return 短链接信息
|
||||
*/
|
||||
ShortLink findByKey(@Param("key")String key);
|
||||
|
||||
|
||||
/**
|
||||
* 根据存储源 ID 和文件路径查询短链接
|
||||
*
|
||||
* @param storageId
|
||||
* 存储源 ID
|
||||
*
|
||||
* @param url
|
||||
* 短链接 url
|
||||
*
|
||||
* @return 短链接信息
|
||||
*/
|
||||
ShortLink findByStorageIdAndUrl(@Param("storageId") Integer storageId, @Param("url") String url);
|
||||
|
||||
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.model.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 缓存对象,用户表示那个存储源的那个文件夹.
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class StorageSourceCacheKey {
|
||||
|
||||
private Integer storageId;
|
||||
|
||||
private String key;
|
||||
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.model.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 短链信息 entity
|
||||
*/
|
||||
@Data
|
||||
@ApiModel(description = "短链信息")
|
||||
@TableName(value = "short_link")
|
||||
public class ShortLink implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
@ApiModelProperty(value = "ID, 新增无需填写", example = "1")
|
||||
private Integer id;
|
||||
|
||||
|
||||
@TableField(value = "storage_id")
|
||||
@ApiModelProperty(value = "存储源 ID", example = "1")
|
||||
private Integer storageId;
|
||||
|
||||
|
||||
@TableField(value = "short_key")
|
||||
@ApiModelProperty(value = "短链 key", example = "voldd3")
|
||||
private String shortKey;
|
||||
|
||||
|
||||
@TableField(value = "url")
|
||||
@ApiModelProperty(value = "短链 url", example = "/directlink/1/test02.png")
|
||||
private String url;
|
||||
|
||||
|
||||
@TableField(value = "create_date")
|
||||
@ApiModelProperty(value = "创建时间", example = "2021-11-22 10:05")
|
||||
private Date createDate;
|
||||
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.model.entity;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.hutool.core.util.BooleanUtil;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import im.zhaojun.zfile.admin.model.enums.SearchModeEnum;
|
||||
import im.zhaojun.zfile.home.model.enums.StorageTypeEnum;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 存储源基本属性 entity
|
||||
*/
|
||||
@Data
|
||||
@ApiModel(description = "存储源基本属性")
|
||||
@TableName(value = "storage_source")
|
||||
public class StorageSource implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
@ApiModelProperty(value = "ID, 新增无需填写", example = "1")
|
||||
private Integer id;
|
||||
|
||||
|
||||
@TableField(value = "`enable`")
|
||||
@ApiModelProperty(value = "是否启用", example = "true")
|
||||
private Boolean enable;
|
||||
|
||||
|
||||
@TableField(value = "`enable_file_operator`")
|
||||
@ApiModelProperty(value = "是否启用文件操作功能", example = "true", notes = "是否启用文件上传,编辑,删除等操作.")
|
||||
private Boolean enableFileOperator;
|
||||
|
||||
|
||||
@TableField(value = "`enable_file_anno_operator`")
|
||||
@ApiModelProperty(value = "是否允许匿名进行文件操作", example = "true", notes = "是否允许匿名进行文件上传,编辑,删除等操作.")
|
||||
private Boolean enableFileAnnoOperator;
|
||||
|
||||
|
||||
@TableField(value = "`enable_cache`")
|
||||
@ApiModelProperty(value = "是否开启缓存", example = "true")
|
||||
private Boolean enableCache;
|
||||
|
||||
|
||||
@TableField(value = "`name`")
|
||||
@ApiModelProperty(value = "存储源名称", example = "阿里云 OSS 存储")
|
||||
private String name;
|
||||
|
||||
|
||||
@TableField(value = "`key`")
|
||||
@ApiModelProperty(value = "存储源别名", example = "存储源别名,用于 URL 中展示, 如 http://ip:port/{存储源别名}")
|
||||
private String key;
|
||||
|
||||
|
||||
@TableField(value = "`remark`")
|
||||
@ApiModelProperty(value = "存储源备注", example = "这是一个备注信息, 用于管理员区分不同的存储源, 此字段仅管理员可见")
|
||||
private String remark;
|
||||
|
||||
|
||||
@TableField(value = "auto_refresh_cache")
|
||||
@ApiModelProperty(value = "是否开启缓存自动刷新", example = "true")
|
||||
private Boolean autoRefreshCache;
|
||||
|
||||
|
||||
@TableField(value = "`type`")
|
||||
@ApiModelProperty(value = "存储源类型")
|
||||
private StorageTypeEnum type;
|
||||
|
||||
|
||||
@TableField(value = "search_enable")
|
||||
@ApiModelProperty(value = "是否开启搜索", example = "true")
|
||||
private Boolean searchEnable;
|
||||
|
||||
|
||||
@TableField(value = "search_ignore_case")
|
||||
@ApiModelProperty(value = "搜索是否忽略大小写", example = "true")
|
||||
private Boolean searchIgnoreCase;
|
||||
|
||||
|
||||
@TableField(value = "`search_mode`")
|
||||
@ApiModelProperty(value = "搜索模式", example = "SEARCH_CACHE", notes = "仅从缓存中搜索或直接全量搜索")
|
||||
private SearchModeEnum searchMode;
|
||||
|
||||
|
||||
@TableField(value = "order_num")
|
||||
@ApiModelProperty(value = "排序值", example = "1")
|
||||
private Integer orderNum;
|
||||
|
||||
|
||||
@TableField(value = "default_switch_to_img_mode")
|
||||
@ApiModelProperty(value = "是否默认开启图片模式", example = "true")
|
||||
private Boolean defaultSwitchToImgMode;
|
||||
|
||||
@TableField(value = "compatibility_readme")
|
||||
@ApiModelProperty(value = "兼容 readme 模式", example = "true", notes = "兼容模式, 目录文档读取 readme.md 文件")
|
||||
private Boolean compatibilityReadme;
|
||||
|
||||
public boolean allowOperator() {
|
||||
// 允许文件操作,且允许匿名操作或者当前登录用户是管理员
|
||||
return BooleanUtil.isTrue(enableFileOperator) && (BooleanUtil.isTrue(enableFileAnnoOperator) || StpUtil.isLogin());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.model.enums;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.EnumValue;
|
||||
import com.fasterxml.jackson.annotation.JsonValue;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 文件操作类型枚举
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum FileOperatorTypeEnum {
|
||||
|
||||
/**
|
||||
* 获取文件上传链接操作
|
||||
*/
|
||||
UPLOAD("上传", "upload"),
|
||||
|
||||
/**
|
||||
* 新建文件夹操作
|
||||
*/
|
||||
NEW_FOLDER("新建文件夹", "new_folder"),
|
||||
|
||||
/**
|
||||
* 删除文件&文件夹操作
|
||||
*/
|
||||
DELETE("删除", "delete"),
|
||||
|
||||
/**
|
||||
* 重命名文件&文件夹操作
|
||||
*/
|
||||
RENAME("重命名", "rename"),
|
||||
|
||||
/**
|
||||
* 复制文件&文件夹操作
|
||||
*/
|
||||
COPY("复制", "copy"),
|
||||
|
||||
/**
|
||||
* 移动文件&文件夹操作
|
||||
*/
|
||||
MOVE("移动", "move");
|
||||
|
||||
private final String name;
|
||||
|
||||
@EnumValue
|
||||
@JsonValue
|
||||
private final String value;
|
||||
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.model.param;
|
||||
|
||||
import im.zhaojun.zfile.admin.annotation.StorageParamItem;
|
||||
import im.zhaojun.zfile.admin.annotation.select.impl.EncodingStorageParamSelect;
|
||||
import im.zhaojun.zfile.admin.model.enums.StorageParamTypeEnum;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 本地存储初始化参数
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Getter
|
||||
public class FtpParam extends ProxyDownloadParam {
|
||||
|
||||
@StorageParamItem(name = "域名或 IP")
|
||||
private String host;
|
||||
|
||||
@StorageParamItem(name = "端口")
|
||||
private int port;
|
||||
|
||||
@StorageParamItem(name = "编码格式",
|
||||
defaultValue = "UTF-8",
|
||||
type = StorageParamTypeEnum.SELECT,
|
||||
optionsClass = EncodingStorageParamSelect.class,
|
||||
description = "表示文件夹及文件名称的编码格式,不表示文本内容的编码格式.")
|
||||
private String encoding;
|
||||
|
||||
@StorageParamItem(name = "用户名", required = false)
|
||||
private String username;
|
||||
|
||||
@StorageParamItem(name = "密码", required = false)
|
||||
private String password;
|
||||
|
||||
@StorageParamItem(name = "加速域名", required = false, description = "如不配置加速域名,则使用服务器中转下载, 反之则使用加速域名下载.")
|
||||
private String domain;
|
||||
|
||||
@StorageParamItem(name = "基路径", defaultValue = "/", description = "基路径表示读取的根文件夹,不填写表示允许读取所有。如: '/','/文件夹1'")
|
||||
private String basePath;
|
||||
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.model.param;
|
||||
|
||||
|
||||
public interface IStorageParam {
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.model.param;
|
||||
|
||||
import im.zhaojun.zfile.admin.annotation.StorageParamItem;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 本地存储初始化参数
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Getter
|
||||
public class LocalParam extends ProxyDownloadParam {
|
||||
|
||||
@StorageParamItem(name = "文件路径", description = "只支持绝对路径<br>Docker 方式部署的话需提前映射宿主机路径! " +
|
||||
"(<a class='link' target='_blank' href='https://docs.docker.com/engine/reference/run/#volume-shared-filesystems'>配置文档</a>)")
|
||||
private String filePath;
|
||||
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.model.param;
|
||||
|
||||
import im.zhaojun.zfile.admin.annotation.StorageParamItem;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 微软云初始化参数
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Getter
|
||||
public class MicrosoftDriveParam implements IStorageParam {
|
||||
|
||||
@StorageParamItem(name = "clientId", defaultValue = "${zfile.onedrive.clientId}", order = 1)
|
||||
private String clientId;
|
||||
|
||||
@StorageParamItem(name = "SecretKey", defaultValue = "${zfile.onedrive.clientSecret}", order = 2)
|
||||
private String clientSecret;
|
||||
|
||||
@StorageParamItem(name = "回调地址", description = "如使用自定义 api, 需将此处默认的域名修改为您的域名, 且需在 api 中配置为回调域名.", defaultValue = "${zfile.onedrive.redirectUri}", order = 3)
|
||||
private String redirectUri;
|
||||
|
||||
@StorageParamItem(name = "访问令牌", link = "/onedrive/authorize", linkName = "前往获取令牌", order = 3)
|
||||
private String accessToken;
|
||||
|
||||
@StorageParamItem(name = "刷新令牌", order = 4)
|
||||
private String refreshToken;
|
||||
|
||||
@StorageParamItem(name = "反代域名", required = false, order = 7, description = "世纪互联版不建议启用,国际版启用后不一定比启用前快,这个要根据仔细网络情况决定.",
|
||||
link = "https://docs.zfile.vip/#/advanced?id=onedrive-cf", linkName = "配置文档")
|
||||
private String proxyDomain;
|
||||
|
||||
@StorageParamItem(name = "基路径", defaultValue = "/", order = 8, description = "基路径表示读取的根文件夹,不填写表示允许读取所有。如: '/','/文件夹1'")
|
||||
private String basePath;
|
||||
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.model.param;
|
||||
|
||||
import im.zhaojun.zfile.admin.annotation.StorageParamItem;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* MinIO 初始化参数
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Getter
|
||||
public class MinIOParam extends S3BaseParam {
|
||||
|
||||
@StorageParamItem(name = "Bucket 域名 / CDN 加速域名", required = false, order = 5, description = "为 minio 的服务地址,非 web 访问地址,一般为 http://ip:9000")
|
||||
private String domain;
|
||||
|
||||
@StorageParamItem(name = "地域", defaultValue = "auto")
|
||||
private String region;
|
||||
|
||||
@StorageParamItem(name = "服务地址", order = 5, description = "为 minio 的服务地址,非 web 访问地址,一般为 http://ip:9000")
|
||||
private String endPoint;
|
||||
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.model.param;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 代理下载参数
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Getter
|
||||
public class ProxyDownloadParam extends ProxyTransferParam {
|
||||
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.model.param;
|
||||
|
||||
import im.zhaojun.zfile.admin.annotation.StorageParamItem;
|
||||
import im.zhaojun.zfile.admin.model.enums.StorageParamTypeEnum;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 代理上传下载参数
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Getter
|
||||
public class ProxyTransferParam implements IStorageParam {
|
||||
|
||||
@StorageParamItem(name = "加速域名", required = false, description = "如不配置加速域名,则使用服务器中转下载, 反之则使用加速域名下载.")
|
||||
private String domain;
|
||||
|
||||
@StorageParamItem(name = "生成签名链接", type = StorageParamTypeEnum.SWITCH, defaultValue = "true", description = "下载会生成带签名的下载链接, 如不想对外开放直链, 可以防止被当做直链使用.")
|
||||
private boolean isPrivate;
|
||||
|
||||
@StorageParamItem(name = "下载签名有效期", required = false, defaultValue = "1800", description = "用于下载签名的有效期, 单位为秒, 如不配置则默认为 1800 秒.")
|
||||
private Integer tokenTime;
|
||||
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.model.param;
|
||||
|
||||
/**
|
||||
* 代理上传参数
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
public class ProxyUploadParam extends ProxyTransferParam {
|
||||
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.model.param;
|
||||
|
||||
import im.zhaojun.zfile.admin.annotation.StorageParamItem;
|
||||
import im.zhaojun.zfile.admin.model.enums.StorageParamTypeEnum;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* S3 通用参数
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Getter
|
||||
public class S3BaseParam implements IStorageParam {
|
||||
|
||||
@StorageParamItem(name = "AccessKey", order = 1)
|
||||
private String accessKey;
|
||||
|
||||
@StorageParamItem(name = "SecretKey", order = 2)
|
||||
private String secretKey;
|
||||
|
||||
@StorageParamItem(name = "区域", order = 3, description = "如下拉列表中没有的区域,或想使用内网地址,可直接输入后回车,如: xxx-cn-beijing.example.com")
|
||||
private String endPoint;
|
||||
|
||||
@StorageParamItem(name = "存储空间名称", order = 4)
|
||||
private String bucketName;
|
||||
|
||||
@StorageParamItem(name = "Bucket 域名 / CDN 加速域名", required = false, order = 5)
|
||||
private String domain;
|
||||
|
||||
@StorageParamItem(name = "基路径", order = 6, required = false, defaultValue = "/", description = "基路径表示读取的根文件夹,不填写表示允许读取所有。如: '/','/文件夹1'")
|
||||
private String basePath;
|
||||
|
||||
@StorageParamItem(name = "是否是私有空间", order = 7, type = StorageParamTypeEnum.SWITCH, defaultValue = "true", description = "私有空间会生成带签名的下载链接")
|
||||
private boolean isPrivate;
|
||||
|
||||
@StorageParamItem(name = "下载签名有效期", required = false, defaultValue = "1800", description = "当为私有空间时, 用于下载签名的有效期, 单位为秒, 如不配置则默认为 1800 秒.")
|
||||
private Integer tokenTime;
|
||||
|
||||
@StorageParamItem(name = "是否自动配置 CORS 跨域设置", order = 100, type = StorageParamTypeEnum.SWITCH, defaultValue = "true", description = "如不配置跨域设置,可能会无法导致无法上传,或上传后看不到文件")
|
||||
private boolean autoConfigCors;
|
||||
|
||||
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.model.param;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* SFTP 初始化参数
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Getter
|
||||
public class SftpParam extends FtpParam {
|
||||
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.model.param;
|
||||
|
||||
import im.zhaojun.zfile.admin.annotation.StorageParamItem;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 腾讯云初始化参数
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Getter
|
||||
public class TencentParam extends S3BaseParam {
|
||||
|
||||
@StorageParamItem(key = "secretId", name = "SecretId", order = 1)
|
||||
private String accessKey;
|
||||
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.model.param;
|
||||
|
||||
import im.zhaojun.zfile.admin.annotation.StorageParamItem;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 又拍云初始化参数
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Getter
|
||||
public class UpYunParam implements IStorageParam {
|
||||
|
||||
@StorageParamItem(name = "存储空间名称")
|
||||
private String bucketName;
|
||||
|
||||
@StorageParamItem(name = "用户名")
|
||||
private String username;
|
||||
|
||||
@StorageParamItem(name = "密码")
|
||||
private String password;
|
||||
|
||||
@StorageParamItem(name = "下载域名", description = "填写您在又拍云绑定的域名.")
|
||||
private String domain;
|
||||
|
||||
@StorageParamItem(name = "基路径", defaultValue = "/", description = "基路径表示读取的根文件夹,不填写表示允许读取所有。如: '/','/文件夹1'")
|
||||
private String basePath;
|
||||
|
||||
@StorageParamItem(name = "Token", required = false, link = "https://help.upyun.com/knowledge-base/cdn-token-limite/", linkName = "官方配置文档",description = "可在又拍云后台开启 \"访问控制\" -> \"Token 防盗链\",控制资源内容的访问时限,即时间戳防盗链。")
|
||||
private String token;
|
||||
|
||||
@StorageParamItem(name = "Token 有效期", required = false, defaultValue = "1800", description = "Token (防盗链)有效期,单位为秒。")
|
||||
private int tokenTime;
|
||||
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.model.param;
|
||||
|
||||
import im.zhaojun.zfile.admin.annotation.StorageParamItem;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* WebDav 初始化参数
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Getter
|
||||
public class WebdavParam extends ProxyDownloadParam {
|
||||
|
||||
@StorageParamItem(key = "url", name = "WebDAV 链接")
|
||||
private String url;
|
||||
|
||||
@StorageParamItem(key = "username", name = "用户名", required = false)
|
||||
private String username;
|
||||
|
||||
@StorageParamItem(key = "password", name = "密码", required = false)
|
||||
private String password;
|
||||
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.model.request;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 下载排行请求类
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Data
|
||||
public class DownloadTopInfoRequest {
|
||||
|
||||
@ApiModelProperty(value = "排行数量", required = true)
|
||||
private Integer top;
|
||||
|
||||
@ApiModelProperty(value = "开始时间")
|
||||
private String startTime;
|
||||
|
||||
@ApiModelProperty(value = "结束时间")
|
||||
private String endTime;
|
||||
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.model.request;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import im.zhaojun.zfile.admin.model.enums.SearchModeEnum;
|
||||
import im.zhaojun.zfile.home.model.dto.StorageSourceAllParam;
|
||||
import im.zhaojun.zfile.home.model.enums.StorageTypeEnum;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 保存存储源信息请求类
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Data
|
||||
@ApiModel(description = "存储源基本参数")
|
||||
public class SaveStorageSourceRequest {
|
||||
|
||||
@ApiModelProperty(value = "ID, 新增无需填写", example = "1")
|
||||
private Integer id;
|
||||
|
||||
@ApiModelProperty(value = "存储源名称", example = "阿里云 OSS 存储")
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty(value = "存储源别名", example = "存储源别名,用于 URL 中展示, 如 http://ip:port/{存储源别名}")
|
||||
private String key;
|
||||
|
||||
@ApiModelProperty(value = "存储源备注", example = "这是一个备注信息, 用于管理员区分不同的存储源, 此字段仅管理员可见")
|
||||
private String remark;
|
||||
|
||||
@ApiModelProperty(value = "存储源类型", example = "ftp")
|
||||
private StorageTypeEnum type;
|
||||
|
||||
@ApiModelProperty(value = "是否启用", example = "true")
|
||||
private Boolean enable;
|
||||
|
||||
@ApiModelProperty(value = "是否启用文件操作功能", example = "true", notes = "是否启用文件上传,编辑,删除等操作.")
|
||||
private Boolean enableFileOperator;
|
||||
|
||||
@ApiModelProperty(value = "是否允许匿名进行文件操作", example = "true", notes = "是否允许匿名进行文件上传,编辑,删除等操作.")
|
||||
private Boolean enableFileAnnoOperator;
|
||||
|
||||
@ApiModelProperty(value = "是否开启缓存", example = "true")
|
||||
private boolean enableCache;
|
||||
|
||||
@ApiModelProperty(value = "是否开启缓存自动刷新", example = "true")
|
||||
private boolean autoRefreshCache;
|
||||
|
||||
@ApiModelProperty(value = "是否开启搜索", example = "true")
|
||||
private boolean searchEnable;
|
||||
|
||||
@ApiModelProperty(value = "搜索是否忽略大小写", example = "true")
|
||||
private boolean searchIgnoreCase;
|
||||
|
||||
@TableField(value = "`search_mode`")
|
||||
@ApiModelProperty(value = "搜索模式", example = "SEARCH_CACHE", notes = "仅从缓存中搜索或直接全量搜索")
|
||||
private SearchModeEnum searchMode;
|
||||
|
||||
@ApiModelProperty(value = "排序值", example = "1")
|
||||
private Integer orderNum;
|
||||
|
||||
@ApiModelProperty(value = "存储源拓展属性")
|
||||
private StorageSourceAllParam storageSourceAllParam;
|
||||
|
||||
@ApiModelProperty(value = "是否默认开启图片模式", example = "true")
|
||||
private boolean defaultSwitchToImgMode;
|
||||
|
||||
@ApiModelProperty(value = "兼容 readme 模式", example = "true", notes = "兼容模式, 目录文档读取 readme.md 文件")
|
||||
private boolean compatibilityReadme;
|
||||
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.model.request.gd;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Data
|
||||
@ApiModel(value="gd drive 列表请求类")
|
||||
public class GetGdDriveListRequest {
|
||||
|
||||
@NotBlank(message = "accessToken 不能为空")
|
||||
@ApiModelProperty(value = "accessToken", required = true, example = "v7LtfjIbnxLCTj0R3riwhyxcbv4KVH5HuPWHWrrewHMEwjJyUlYXV6D4m1MLJ2dP__GX_7CKCc-HudUetPXWS2wwbfkNs6ydLq3xrk1gHA7wcD_pmt6oNuRXw5mnFzfdLkH5wIG1suQp3p0eHJurzIaCgYKATASATASFQE65dr8hO725r41QtZc9RJVUg12cA0163")
|
||||
private String accessToken;
|
||||
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.model.request.link;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
|
||||
/**
|
||||
* 查询下载日志请求参数
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Data
|
||||
public class QueryDownloadLogRequest {
|
||||
|
||||
@ApiModelProperty(value="文件路径")
|
||||
private String path;
|
||||
|
||||
@ApiModelProperty(value="存储源 key")
|
||||
private String storageKey;
|
||||
|
||||
@ApiModelProperty(value="短链 key")
|
||||
private String shortKey;
|
||||
|
||||
@ApiModelProperty(value="访问时间从")
|
||||
private String dateFrom;
|
||||
|
||||
@ApiModelProperty(value="访问时间至")
|
||||
private String dateTo;
|
||||
|
||||
@ApiModelProperty(value="访问 ip")
|
||||
private String ip;
|
||||
|
||||
@ApiModelProperty(value="访问 user_agent")
|
||||
private String userAgent;
|
||||
|
||||
@ApiModelProperty(value="访问 referer")
|
||||
private String referer;
|
||||
|
||||
@NotEmpty(message = "分页页数不能为空")
|
||||
private Integer page;
|
||||
|
||||
@NotEmpty(message = "每页条数不能为空")
|
||||
private Integer limit;
|
||||
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.model.request.login;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* 验证 2FA 认证返回结果
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@ApiModel(description = "验证二步验证结果")
|
||||
public class VerifyLogin2FARequest {
|
||||
|
||||
@ApiModelProperty(value = "二步验证二维码", required = true, example = "EwBoxxxxxxxxxxxxxxxbAI=")
|
||||
@NotBlank(message = "二步验证密钥不能为空")
|
||||
private String secret;
|
||||
|
||||
@ApiModelProperty(value = "APP 生成的二步验证验证码", required = true, example = "125612")
|
||||
@NotBlank(message = "二步验证验证码不能为空")
|
||||
private String code;
|
||||
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.model.request.s3;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* 获取 S3 bucket 列表请求类
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Data
|
||||
@ApiModel(value="S3 bucket 列表请求类")
|
||||
public class GetS3BucketListRequest {
|
||||
|
||||
@NotBlank(message = "accessKey 不能为空")
|
||||
@ApiModelProperty(value = "accessKey", required = true, example = "XQEWQJI129JAS12")
|
||||
private String accessKey;
|
||||
|
||||
@NotBlank(message = "secretKey 不能为空")
|
||||
@ApiModelProperty(value = "secretKey", required = true, example = "EWQJI129JAS11AE2")
|
||||
private String secretKey;
|
||||
|
||||
@NotBlank(message = "EndPoint 不能为空")
|
||||
@ApiModelProperty(value = "Endpoint 接入点", required = true, example = "oss-cn-beijing.aliyuncs.com")
|
||||
private String endPoint;
|
||||
|
||||
@ApiModelProperty(value = "Endpoint 接入点", required = true, example = "cn-beijing")
|
||||
private String region;
|
||||
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.model.request.setting;
|
||||
|
||||
import im.zhaojun.zfile.admin.model.enums.RefererTypeEnum;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 直链设置请求参数类
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Data
|
||||
@ApiModel(description = "直链设置请求参数类")
|
||||
public class UpdateLinkSettingRequest {
|
||||
|
||||
@ApiModelProperty(value = "是否记录下载日志", example = "true")
|
||||
private Boolean recordDownloadLog;
|
||||
|
||||
@ApiModelProperty(value = "直链 Referer 防盗链类型")
|
||||
private RefererTypeEnum refererType;
|
||||
|
||||
@ApiModelProperty(value = "直链 Referer 是否允许为空")
|
||||
private Boolean refererAllowEmpty;
|
||||
|
||||
@ApiModelProperty(value = "直链 Referer 值")
|
||||
private String refererValue;
|
||||
|
||||
@ApiModelProperty(value = "直链地址前缀")
|
||||
private String directLinkPrefix;
|
||||
|
||||
@ApiModelProperty(value = "是否显示生成直链功能(含直链和路径短链)", example = "true", required = true)
|
||||
private Boolean showLinkBtn;
|
||||
|
||||
@ApiModelProperty(value = "是否显示生成短链功能", example = "true", required = true)
|
||||
private Boolean showShortLink;
|
||||
|
||||
@ApiModelProperty(value = "是否显示生成路径链接功能", example = "true", required = true)
|
||||
private Boolean showPathLink;
|
||||
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.model.request.setting;
|
||||
|
||||
import im.zhaojun.zfile.admin.model.enums.LoginVerifyModeEnum;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 登陆安全设置请求参数类
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Data
|
||||
@ApiModel(description = "登陆安全设置请求参数类")
|
||||
public class UpdateSecuritySettingRequest {
|
||||
|
||||
@ApiModelProperty(value = "是否在前台显示登陆按钮", example = "true")
|
||||
private Boolean showLogin;
|
||||
|
||||
@ApiModelProperty(value = "登陆验证方式,支持验证码和 2FA 认证")
|
||||
private LoginVerifyModeEnum loginVerifyMode;
|
||||
|
||||
@ApiModelProperty(value = "登陆验证 Secret")
|
||||
private String loginVerifySecret;
|
||||
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.model.request.setting;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* 站点设置请求参数类
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Data
|
||||
@ApiModel(description = "站点设置请求参数类")
|
||||
public class UpdateSiteSettingRequest {
|
||||
|
||||
@ApiModelProperty(value = "站点名称", required = true, example = "ZFile Site Name")
|
||||
@NotBlank(message = "站点名称不能为空")
|
||||
private String siteName;
|
||||
|
||||
@ApiModelProperty(value = "站点域名", required = true, example = "https://zfile.vip")
|
||||
@NotBlank(message = "站点域名不能为空")
|
||||
private String domain;
|
||||
|
||||
@ApiModelProperty(value = "前端域名", notes = "前端域名,前后端分离情况下需要配置.", example = "http://xxx.example.com")
|
||||
private String frontDomain;
|
||||
|
||||
@ApiModelProperty(value = "头像地址", example = "https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png")
|
||||
private String avatar;
|
||||
|
||||
@ApiModelProperty(value = "备案号", example = "冀ICP备12345678号-1")
|
||||
private String icp;
|
||||
|
||||
@ApiModelProperty(value = "最大同时上传文件数", example = "5")
|
||||
private Integer maxFileUploads;
|
||||
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.model.request.setting;
|
||||
@@ -1,59 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.model.request.setting;
|
||||
|
||||
import im.zhaojun.zfile.admin.model.enums.FileClickModeEnum;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 显示设置请求参数类
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Data
|
||||
@ApiModel(description = "显示设置请求参数类")
|
||||
public class UpdateViewSettingRequest {
|
||||
|
||||
@ApiModelProperty(value = "根目录是否显示所有存储源", notes = "根目录是否显示所有存储源, 如果为 true, 则根目录显示所有存储源列表, 如果为 false, 则会自动跳转到第一个存储源.", example = "true", required = true)
|
||||
private Boolean rootShowStorage;
|
||||
|
||||
@ApiModelProperty(value = "页面布局", notes = "full:全屏,center:居中", example = "full", required = true)
|
||||
private String layout;
|
||||
|
||||
@ApiModelProperty(value = "列表尺寸", notes = "large:大,default:中,small:小", example = "default", required = true)
|
||||
private String tableSize;
|
||||
|
||||
@ApiModelProperty(value = "自定义视频文件后缀格式")
|
||||
private String customVideoSuffix;
|
||||
|
||||
@ApiModelProperty(value = "自定义图像文件后缀格式")
|
||||
private String customImageSuffix;
|
||||
|
||||
@ApiModelProperty(value = "自定义音频文件后缀格式")
|
||||
private String customAudioSuffix;
|
||||
|
||||
@ApiModelProperty(value = "自定义文本文件后缀格式")
|
||||
private String customTextSuffix;
|
||||
|
||||
@ApiModelProperty(value = "是否显示文档区", example = "true", required = true)
|
||||
private Boolean showDocument;
|
||||
|
||||
@ApiModelProperty(value = "是否显示网站公告", example = "true", required = true)
|
||||
private Boolean showAnnouncement;
|
||||
|
||||
@ApiModelProperty(value = "网站公告", example = "ZFile 网站公告")
|
||||
private String announcement;
|
||||
|
||||
@ApiModelProperty(value = "自定义 CSS")
|
||||
private String customCss;
|
||||
|
||||
@ApiModelProperty(value = "自定义 JS")
|
||||
private String customJs;
|
||||
|
||||
@ApiModelProperty(value = "默认文件点击习惯", example = "click")
|
||||
private FileClickModeEnum fileClickMode;
|
||||
|
||||
@ApiModelProperty(value = "onlyOffice 在线预览地址", example = "http://office.zfile.vip")
|
||||
private String onlyOfficeUrl;
|
||||
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.model.result.gd;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* gd drive 基本信息结果类
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@ApiModel(value="gd drive 基本信息结果类")
|
||||
public class GdDriveInfoResult {
|
||||
|
||||
@ApiModelProperty(value = "drive id", example = "0AGrY0xF1D7PEUk9PVB")
|
||||
private String id;
|
||||
|
||||
@ApiModelProperty(value = "drive 名称", example = "zfile")
|
||||
private String name;
|
||||
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.model.result.link;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import im.zhaojun.zfile.home.model.enums.StorageTypeEnum;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 下载日志结果类
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Data
|
||||
public class DownloadLogResult {
|
||||
|
||||
@TableId(value = "id", type = IdType.INPUT)
|
||||
@ApiModelProperty(value="")
|
||||
private Integer id;
|
||||
|
||||
@ApiModelProperty(value="文件路径")
|
||||
private String path;
|
||||
|
||||
@ApiModelProperty(value = "存储源名称", example = "我的本地存储")
|
||||
private String storageName;
|
||||
|
||||
@ApiModelProperty(value = "存储源类型")
|
||||
private StorageTypeEnum storageType;
|
||||
|
||||
@ApiModelProperty(value = "短链 Key")
|
||||
private String shortKey;
|
||||
|
||||
@ApiModelProperty(value="访问时间")
|
||||
private Date createTime;
|
||||
|
||||
@ApiModelProperty(value="访问 ip")
|
||||
private String ip;
|
||||
|
||||
@ApiModelProperty(value="访问 user_agent")
|
||||
private String userAgent;
|
||||
|
||||
@ApiModelProperty(value="访问 referer")
|
||||
private String referer;
|
||||
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.model.result.link;
|
||||
|
||||
import im.zhaojun.zfile.home.model.enums.StorageTypeEnum;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 短链结果类
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Data
|
||||
public class ShortLinkResult {
|
||||
|
||||
@ApiModelProperty(value = "短链 id", example = "1")
|
||||
private Integer id;
|
||||
|
||||
@ApiModelProperty(value = "存储源名称", example = "我的本地存储")
|
||||
private String storageName;
|
||||
|
||||
@ApiModelProperty(value = "存储源类型")
|
||||
private StorageTypeEnum storageType;
|
||||
|
||||
@ApiModelProperty(value = "短链 key", example = "voldd3")
|
||||
private String shortKey;
|
||||
|
||||
@ApiModelProperty(value = "文件 url", example = "/directlink/1/test02.png")
|
||||
private String url;
|
||||
|
||||
@ApiModelProperty(value = "创建时间", example = "2021-11-22 10:05")
|
||||
private Date createDate;
|
||||
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.model.result.login;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 登陆 2FA 认证生成返回结果
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@ApiModel(description = "生成二步验证结果")
|
||||
public class Login2FAResult {
|
||||
|
||||
@ApiModelProperty(value = "二步验证二维码")
|
||||
private String qrcode;
|
||||
|
||||
@ApiModelProperty(value = "二步验证密钥")
|
||||
private String secret;
|
||||
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.model.result.login;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 生成图片验证码结果类
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Data
|
||||
@ApiModel(description = "生成图片验证码结果类")
|
||||
public class LoginVerifyImgResult {
|
||||
|
||||
@ApiModelProperty(value = "验证码图片", example = "data:image/png;base64,iajsiAAA...")
|
||||
private String imgBase64;
|
||||
|
||||
@ApiModelProperty(value = "验证码 UUID", example = "c140a792-4ca2-4dac-8d4c-35750b78524f")
|
||||
private String uuid;
|
||||
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.model.result.s3;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* S3 bucket 名称结果类
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@ApiModel(value="S3 bucket 名称结果类")
|
||||
public class S3BucketNameResult {
|
||||
|
||||
@ApiModelProperty(value = "bucket 名称", example = "zfile")
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty(value = "bucket 创建时间", example = "2022-01-01 15:22")
|
||||
private Date date;
|
||||
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.model.result.sharepoint;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* Sharepoint 站点信息
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Data
|
||||
@ApiModel(description = "SharePoint 站点结果类")
|
||||
public class SharepointSite {
|
||||
|
||||
@ApiModelProperty(value="站点 id")
|
||||
private String id;
|
||||
|
||||
@ApiModelProperty(value="站点名称")
|
||||
private String displayName;
|
||||
|
||||
@ApiModelProperty(value="站点地址")
|
||||
private String webUrl;
|
||||
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.model.result.sharepoint;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Sharepoint 网站 list 列表
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Data
|
||||
@ApiModel(description = "Sharepoint 网站 list 列表")
|
||||
public class SharepointSiteList {
|
||||
|
||||
@ApiModelProperty(value="站点目录 id")
|
||||
private String id;
|
||||
|
||||
@ApiModelProperty(value="站点目录名称")
|
||||
private String displayName;
|
||||
|
||||
@ApiModelProperty(value="站点目录创建时间")
|
||||
private Date createdDateTime;
|
||||
|
||||
@ApiModelProperty(value="站点目录地址")
|
||||
private String webUrl;
|
||||
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.model.result.storage;
|
||||
|
||||
import im.zhaojun.zfile.admin.model.enums.SearchModeEnum;
|
||||
import im.zhaojun.zfile.common.cache.RefreshTokenCache;
|
||||
import im.zhaojun.zfile.home.model.enums.StorageTypeEnum;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 存储源设置后台管理 Result
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Data
|
||||
@ApiModel(description = "存储源设置后台管理 Result")
|
||||
public class StorageSourceAdminResult {
|
||||
|
||||
@ApiModelProperty(value = "ID, 新增无需填写", example = "1")
|
||||
private Integer id;
|
||||
|
||||
|
||||
@ApiModelProperty(value = "是否启用", example = "true")
|
||||
private Boolean enable;
|
||||
|
||||
|
||||
@ApiModelProperty(value = "是否启用文件操作功能", example = "true", notes = "是否启用文件上传,编辑,删除等操作.")
|
||||
private Boolean enableFileOperator;
|
||||
|
||||
|
||||
@ApiModelProperty(value = "是否允许匿名进行文件操作", example = "true", notes = "是否允许匿名进行文件上传,编辑,删除等操作.")
|
||||
private Boolean enableFileAnnoOperator;
|
||||
|
||||
@ApiModelProperty(value = "是否开启缓存", example = "true")
|
||||
private Boolean enableCache;
|
||||
|
||||
|
||||
@ApiModelProperty(value = "存储源名称", example = "阿里云 OSS 存储")
|
||||
private String name;
|
||||
|
||||
|
||||
@ApiModelProperty(value = "存储源别名", example = "存储源别名,用于 URL 中展示, 如 http://ip:port/{存储源别名}")
|
||||
private String key;
|
||||
|
||||
|
||||
@ApiModelProperty(value = "存储源备注", example = "这是一个备注信息, 用于管理员区分不同的存储源, 此字段仅管理员可见")
|
||||
private String remark;
|
||||
|
||||
|
||||
@ApiModelProperty(value = "是否开启缓存自动刷新", example = "true")
|
||||
private Boolean autoRefreshCache;
|
||||
|
||||
|
||||
@ApiModelProperty(value = "存储源类型")
|
||||
private StorageTypeEnum type;
|
||||
|
||||
|
||||
@ApiModelProperty(value = "是否开启搜索", example = "true")
|
||||
private Boolean searchEnable;
|
||||
|
||||
|
||||
@ApiModelProperty(value = "搜索是否忽略大小写", example = "true")
|
||||
private Boolean searchIgnoreCase;
|
||||
|
||||
|
||||
@ApiModelProperty(value = "搜索模式", example = "SEARCH_CACHE", notes = "仅从缓存中搜索或直接全量搜索")
|
||||
private SearchModeEnum searchMode;
|
||||
|
||||
|
||||
@ApiModelProperty(value = "排序值", example = "1")
|
||||
private Integer orderNum;
|
||||
|
||||
|
||||
@ApiModelProperty(value = "是否默认开启图片模式", example = "true")
|
||||
private Boolean defaultSwitchToImgMode;
|
||||
|
||||
|
||||
@ApiModelProperty(value = "存储源刷新信息")
|
||||
private RefreshTokenCache.RefreshTokenInfo refreshTokenInfo;
|
||||
|
||||
|
||||
@ApiModelProperty(value = "兼容 readme 模式", example = "true", notes = "兼容模式, 目录文档读取 readme.md 文件")
|
||||
private Boolean compatibilityReadme;
|
||||
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.model.verify;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 用于表示校验结果的类
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Data
|
||||
public class VerifyResult {
|
||||
|
||||
/**
|
||||
* 是否成功
|
||||
*/
|
||||
private boolean passed;
|
||||
|
||||
/**
|
||||
* 消息
|
||||
*/
|
||||
private String msg;
|
||||
|
||||
/**
|
||||
* 代码
|
||||
*/
|
||||
private Integer code;
|
||||
|
||||
/**
|
||||
* 表达式
|
||||
*/
|
||||
private String pattern;
|
||||
|
||||
public static VerifyResult success() {
|
||||
VerifyResult verifyResult = new VerifyResult();
|
||||
verifyResult.setPassed(true);
|
||||
return verifyResult;
|
||||
}
|
||||
|
||||
|
||||
public static VerifyResult success(String pattern) {
|
||||
VerifyResult verifyResult = new VerifyResult();
|
||||
verifyResult.setPassed(true);
|
||||
verifyResult.setPattern(pattern);
|
||||
return verifyResult;
|
||||
}
|
||||
|
||||
|
||||
public static VerifyResult fail(String msg, Integer code) {
|
||||
VerifyResult verifyResult = new VerifyResult();
|
||||
verifyResult.setPassed(false);
|
||||
verifyResult.setMsg(msg);
|
||||
verifyResult.setCode(code);
|
||||
return verifyResult;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import im.zhaojun.zfile.admin.mapper.DownloadLogMapper;
|
||||
import im.zhaojun.zfile.admin.model.entity.DownloadLog;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 下载日志 Service
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Service
|
||||
public class DownloadLogService extends ServiceImpl<DownloadLogMapper, DownloadLog> {
|
||||
|
||||
|
||||
}
|
||||
@@ -1,219 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.service;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import im.zhaojun.zfile.admin.mapper.FilterConfigMapper;
|
||||
import im.zhaojun.zfile.admin.model.entity.FilterConfig;
|
||||
import im.zhaojun.zfile.common.exception.FileAccessException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.PathMatcher;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 存储源过滤器 Service
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class FilterConfigService extends ServiceImpl<FilterConfigMapper, FilterConfig> {
|
||||
|
||||
@Resource
|
||||
private FilterConfigMapper filterConfigMapper;
|
||||
|
||||
|
||||
/**
|
||||
* 存储源 ID -> 过滤器列表(全部)缓存.
|
||||
*/
|
||||
private final Map<Integer, List<FilterConfig>> baseCache = new HashMap<>();
|
||||
|
||||
/**
|
||||
* 存储源 ID -> 过滤器列表(禁止访问)缓存.
|
||||
*/
|
||||
private final Map<Integer, List<FilterConfig>> inaccessibleCache = new HashMap<>();
|
||||
|
||||
/**
|
||||
* 存储源 ID -> 过滤器列表(禁止下载)缓存.
|
||||
*/
|
||||
private final Map<Integer, List<FilterConfig>> disableDownloadCache = new HashMap<>();
|
||||
|
||||
|
||||
/**
|
||||
* 根据存储源 ID 获取存储源配置列表
|
||||
*
|
||||
* @param storageId
|
||||
* 存储源 ID
|
||||
*
|
||||
* @return 存储源过滤器配置列表
|
||||
*/
|
||||
public List<FilterConfig> findByStorageId(Integer storageId){
|
||||
if (baseCache.get(storageId) != null) {
|
||||
return baseCache.get(storageId);
|
||||
} else {
|
||||
List<FilterConfig> dbResult = filterConfigMapper.findByStorageId(storageId);
|
||||
baseCache.put(storageId, dbResult);
|
||||
return dbResult;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 批量保存存储源过滤器配置, 会先删除之前的所有配置(在事务中运行)
|
||||
*
|
||||
* @param storageId
|
||||
* 存储源 ID
|
||||
*
|
||||
* @param filterConfigList
|
||||
* 存储源过滤器配置列表
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void batchSave(Integer storageId, List<FilterConfig> filterConfigList) {
|
||||
filterConfigMapper.deleteByStorageId(storageId);
|
||||
super.saveBatch(filterConfigList);
|
||||
baseCache.put(storageId, filterConfigList);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 判断访问的路径是否是不允许访问的
|
||||
*
|
||||
* @param storageId
|
||||
* 存储源 ID
|
||||
*
|
||||
* @param path
|
||||
* 请求路径
|
||||
*
|
||||
* @throws FileAccessException 如果没权限访问此目录, 则抛出异常
|
||||
*
|
||||
*/
|
||||
public void checkPathPermission(Integer storageId, String path) {
|
||||
List<FilterConfig> filterConfigList = findByStorageIdAndInaccessible(storageId);
|
||||
if (testPattern(filterConfigList, path)) {
|
||||
throw new FileAccessException("您没有权限访问该路径");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取所有类型为禁止访问的过滤规则
|
||||
*
|
||||
* @param storageId
|
||||
* 存储 ID
|
||||
*
|
||||
* @return 禁止访问的过滤规则列表
|
||||
*/
|
||||
public List<FilterConfig> findByStorageIdAndInaccessible(Integer storageId){
|
||||
if (inaccessibleCache.get(storageId) != null) {
|
||||
return inaccessibleCache.get(storageId);
|
||||
} else {
|
||||
List<FilterConfig> dbResult = filterConfigMapper.findByStorageIdAndInaccessible(storageId);
|
||||
inaccessibleCache.put(storageId, dbResult);
|
||||
return dbResult;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取所有类型为禁止下载的过滤规则
|
||||
*
|
||||
* @param storageId
|
||||
* 存储 ID
|
||||
*
|
||||
* @return 禁止下载的过滤规则列表
|
||||
*/
|
||||
public List<FilterConfig> findByStorageIdAndDisableDownload(Integer storageId){
|
||||
if (disableDownloadCache.get(storageId) != null) {
|
||||
return disableDownloadCache.get(storageId);
|
||||
} else {
|
||||
List<FilterConfig> dbResult = filterConfigMapper.findByStorageIdAndDisableDownload(storageId);
|
||||
disableDownloadCache.put(storageId, dbResult);
|
||||
return dbResult;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 指定存储源下的文件名称, 根据过滤表达式判断是否会显示, 如果符合任意一条表达式, 表示隐藏则返回 true, 反之表示不隐藏则返回 false.
|
||||
*
|
||||
* @param storageId
|
||||
* 存储源 ID
|
||||
*
|
||||
* @param fileName
|
||||
* 文件名
|
||||
*
|
||||
* @return 是否是隐藏文件夹
|
||||
*/
|
||||
public boolean filterResultIsHidden(Integer storageId, String fileName) {
|
||||
List<FilterConfig> filterConfigList = findByStorageId(storageId);
|
||||
return testPattern(filterConfigList, fileName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 指定存储源下的文件名称, 根据过滤表达式判断文件名和所在路径是否禁止下载, 如果符合任意一条表达式, 则返回 true, 反之则返回 false.
|
||||
*
|
||||
* @param storageId
|
||||
* 存储源 ID
|
||||
*
|
||||
* @param fileName
|
||||
* 文件名
|
||||
*
|
||||
* @return 是否显示
|
||||
*/
|
||||
public boolean filterResultIsDisableDownload(Integer storageId, String fileName) {
|
||||
List<FilterConfig> filterConfigList = findByStorageIdAndDisableDownload(storageId);
|
||||
String filePath = FileUtil.getParent(fileName, 1);
|
||||
if (StrUtil.isEmpty(filePath)) {
|
||||
return testPattern(filterConfigList, fileName);
|
||||
} else {
|
||||
return testPattern(filterConfigList, fileName) || testPattern(filterConfigList, filePath);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据规则表达式和测试字符串进行匹配,如测试字符串和其中一个规则匹配上,则返回 true,反之返回 false。
|
||||
*
|
||||
* @param patternList
|
||||
* 规则列表
|
||||
*
|
||||
* @param test
|
||||
*
|
||||
* 测试字符串
|
||||
*
|
||||
* @return 是否显示
|
||||
*/
|
||||
private boolean testPattern(List<FilterConfig> patternList, String test) {
|
||||
for (FilterConfig filterConfig : patternList) {
|
||||
String expression = filterConfig.getExpression();
|
||||
|
||||
if (StrUtil.isEmpty(expression)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
PathMatcher pathMatcher = FileSystems.getDefault().getPathMatcher("glob:" + expression);
|
||||
boolean match = pathMatcher.matches(Paths.get(test));
|
||||
if (match) {
|
||||
return true;
|
||||
}
|
||||
log.debug("regex: {}, name {}, contains: {}", expression, test, match);
|
||||
} catch (Exception e) {
|
||||
log.debug("regex: {}, name {}, parse error, skip expression", expression, test);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,159 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.service;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import im.zhaojun.zfile.admin.mapper.PasswordConfigMapper;
|
||||
import im.zhaojun.zfile.admin.model.entity.PasswordConfig;
|
||||
import im.zhaojun.zfile.admin.model.verify.VerifyResult;
|
||||
import im.zhaojun.zfile.common.util.AjaxJson;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.PathMatcher;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 存储源密码配置 Service
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class PasswordConfigService extends ServiceImpl<PasswordConfigMapper, PasswordConfig> {
|
||||
|
||||
@Resource
|
||||
private PasswordConfigMapper passwordConfigMapper;
|
||||
|
||||
|
||||
/**
|
||||
* 存储源 ID -> 密码规则列表(全部)缓存.
|
||||
*/
|
||||
private final Map<Integer, List<PasswordConfig>> baseCache = new HashMap<>();
|
||||
|
||||
|
||||
/**
|
||||
* 根据存储源 ID 查询密码规则列表
|
||||
*
|
||||
* @param storageId
|
||||
* 存储源 ID
|
||||
*
|
||||
* @return 密码规则列表
|
||||
*/
|
||||
public List<PasswordConfig> findByStorageId(Integer storageId) {
|
||||
if (baseCache.get(storageId) != null) {
|
||||
return baseCache.get(storageId);
|
||||
} else {
|
||||
List<PasswordConfig> dbResult = passwordConfigMapper.findByStorageId(storageId);
|
||||
baseCache.put(storageId, dbResult);
|
||||
return dbResult;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 批量保存指定存储源 ID 的密码规则列表
|
||||
*
|
||||
* @param storageId
|
||||
* 存储源 ID
|
||||
*
|
||||
* @param passwordConfigList
|
||||
* 存储源类别
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void batchSave(Integer storageId, List<PasswordConfig> passwordConfigList) {
|
||||
passwordConfigMapper.deleteByStorageId(storageId);
|
||||
super.saveBatch(passwordConfigList);
|
||||
baseCache.put(storageId, passwordConfigList);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 校验密码
|
||||
*
|
||||
* @param storageId
|
||||
* 存储源 ID
|
||||
*
|
||||
* @param path
|
||||
* 请求路径
|
||||
*
|
||||
* @param inputPassword
|
||||
* 用户输入的密码
|
||||
*
|
||||
* @return 是否校验通过
|
||||
*/
|
||||
public VerifyResult verifyPassword(Integer storageId, String path, String inputPassword) {
|
||||
List<PasswordConfig> passwordConfigList = findByStorageId(storageId);
|
||||
|
||||
for (PasswordConfig passwordConfig : passwordConfigList) {
|
||||
String expression = passwordConfig.getExpression();
|
||||
if (StrUtil.isEmpty(expression)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
PathMatcher pathMatcher = FileSystems.getDefault()
|
||||
.getPathMatcher("glob:" + expression);
|
||||
// 判断当前请求路径是否和规则路径表达式匹配
|
||||
boolean match = pathMatcher.matches(Paths.get(path));
|
||||
// 如果匹配且输入了密码则校验
|
||||
if (match) {
|
||||
if (StrUtil.isEmpty(inputPassword)) {
|
||||
return VerifyResult.fail("此文件夹需要密码.", AjaxJson.REQUIRED_PASSWORD);
|
||||
}
|
||||
|
||||
String expectedPassword = passwordConfig.getPassword();
|
||||
if (matchPassword(expectedPassword, inputPassword)) {
|
||||
log.debug("匹配文件夹密码 path: {}, expression: {}, 用户输入: {}, 匹配成功", path, expression, inputPassword);
|
||||
return VerifyResult.success(expression);
|
||||
}
|
||||
log.debug("匹配文件夹密码 path: {}, expression: {}, 用户输入: {}, 不匹配.", path, expression, inputPassword);
|
||||
return VerifyResult.fail("此文件夹密码错误.", AjaxJson.INVALID_PASSWORD);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("匹配文件夹密码 path: {}, expression: {}, 用户输入: {}, 解析错误, 跳过此规则.",
|
||||
path, expression, inputPassword, e);
|
||||
}
|
||||
}
|
||||
|
||||
log.debug("校验文件夹密码 path: {}, 没有匹配的表达式, 不进行密码校验.", path);
|
||||
return VerifyResult.success();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 校验两个密码是否相同, 忽略空白字符
|
||||
*
|
||||
* @param expectedPasswordContent
|
||||
* 预期密码
|
||||
*
|
||||
* @param password
|
||||
* 实际输入密码
|
||||
*
|
||||
* @return 是否匹配
|
||||
*/
|
||||
private boolean matchPassword(String expectedPasswordContent, String password) {
|
||||
if (Objects.equals(expectedPasswordContent, password)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (expectedPasswordContent == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (password == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
expectedPasswordContent = expectedPasswordContent.replace("\n", "").trim();
|
||||
password = password.replace("\n", "").trim();
|
||||
return Objects.equals(expectedPasswordContent, password);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.service;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import im.zhaojun.zfile.admin.mapper.ReadmeConfigMapper;
|
||||
import im.zhaojun.zfile.admin.model.entity.ReadmeConfig;
|
||||
import im.zhaojun.zfile.common.constant.ZFileConstant;
|
||||
import im.zhaojun.zfile.common.util.StringUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.PathMatcher;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 存储源 readme 配置 Service
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class ReadmeConfigService extends ServiceImpl<ReadmeConfigMapper, ReadmeConfig> {
|
||||
|
||||
@Resource
|
||||
private ReadmeConfigMapper readmeConfigMapper;
|
||||
|
||||
|
||||
/**
|
||||
* 根据存储源 ID 查询文档配置
|
||||
*
|
||||
* @param storageId
|
||||
* 存储源ID
|
||||
*
|
||||
* @return 存储源文档配置列表
|
||||
*/
|
||||
public List<ReadmeConfig> findByStorageId(Integer storageId){
|
||||
return readmeConfigMapper.findByStorageId(storageId);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 批量保存存储源 readme 配置, 会先删除之前的所有配置(在事务中运行)
|
||||
*
|
||||
* @param storageId
|
||||
* 存储源 ID
|
||||
*
|
||||
* @param filterConfigList
|
||||
* 存储源 readme 配置列表
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void batchSave(Integer storageId, List<ReadmeConfig> filterConfigList) {
|
||||
readmeConfigMapper.deleteByStorageId(storageId);
|
||||
super.saveBatch(filterConfigList);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 根据存储源指定路径下的 readme 配置
|
||||
*
|
||||
* @param storageId
|
||||
* 存储源ID
|
||||
*
|
||||
* @param path
|
||||
* 文件夹路径
|
||||
*
|
||||
* @return 存储源 readme 配置列表
|
||||
*/
|
||||
public ReadmeConfig findReadmeByPath(Integer storageId, String path) {
|
||||
List<ReadmeConfig> readmeConfigList = readmeConfigMapper.findByStorageId(storageId);
|
||||
return getReadmeByTestPattern(readmeConfigList, path);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据规则表达式和测试字符串进行匹配,如测试字符串和其中一个规则匹配上,则返回 true,反之返回 false。
|
||||
*
|
||||
* @param patternList
|
||||
* 规则列表
|
||||
*
|
||||
* @param test
|
||||
* 测试字符串
|
||||
*
|
||||
* @return 是否显示
|
||||
*/
|
||||
private ReadmeConfig getReadmeByTestPattern(List<ReadmeConfig> patternList, String test) {
|
||||
test = StringUtils.concat(test, ZFileConstant.PATH_SEPARATOR);
|
||||
|
||||
for (ReadmeConfig filterConfig : patternList) {
|
||||
String expression = filterConfig.getExpression();
|
||||
if (StrUtil.isEmpty(expression)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
PathMatcher pathMatcher = FileSystems.getDefault().getPathMatcher("glob:" + expression);
|
||||
boolean match = pathMatcher.matches(Paths.get(test));
|
||||
if (match) {
|
||||
return filterConfig;
|
||||
}
|
||||
log.debug("regex: {}, name {}, contains: {}", expression, test, match);
|
||||
} catch (Exception e) {
|
||||
log.debug("regex: {}, name {}, parse error, skip expression", expression, test);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,219 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.service;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.util.BooleanUtil;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import im.zhaojun.zfile.admin.mapper.ShortLinkMapper;
|
||||
import im.zhaojun.zfile.admin.model.entity.DownloadLog;
|
||||
import im.zhaojun.zfile.admin.model.entity.ShortLink;
|
||||
import im.zhaojun.zfile.common.context.StorageSourceContext;
|
||||
import im.zhaojun.zfile.common.exception.InvalidStorageSourceException;
|
||||
import im.zhaojun.zfile.common.exception.file.operator.DownloadFileException;
|
||||
import im.zhaojun.zfile.common.util.HttpUtil;
|
||||
import im.zhaojun.zfile.common.util.RequestHolder;
|
||||
import im.zhaojun.zfile.home.model.dto.SystemConfigDTO;
|
||||
import im.zhaojun.zfile.home.service.base.AbstractBaseFileService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.http.util.EncodingUtils;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 短链 Service
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class ShortLinkService extends ServiceImpl<ShortLinkMapper, ShortLink> implements IService<ShortLink> {
|
||||
|
||||
@Resource
|
||||
private ShortLinkMapper shortLinkMapper;
|
||||
|
||||
@Resource
|
||||
private StorageSourceService storageSourceService;
|
||||
|
||||
@Resource
|
||||
private StorageSourceContext storageSourceContext;
|
||||
|
||||
@Resource
|
||||
private SystemConfigService systemConfigService;
|
||||
|
||||
@Resource
|
||||
private DownloadLogService downloadLogService;
|
||||
|
||||
/**
|
||||
* 根据短链接 key 查询短链接
|
||||
*
|
||||
* @param key
|
||||
* 短链接 key
|
||||
*
|
||||
* @return 短链接信息
|
||||
*/
|
||||
public ShortLink findByKey(String key) {
|
||||
return shortLinkMapper.findByKey(key);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据短链接 id 查询短链接
|
||||
*
|
||||
* @param id
|
||||
* 短链接 id
|
||||
*
|
||||
* @return 短链接信息
|
||||
*/
|
||||
public ShortLink findById(Integer id) {
|
||||
return shortLinkMapper.selectById(id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据存储源 ID 和文件路径查询短链接
|
||||
*
|
||||
* @param storageId
|
||||
* 存储源 ID
|
||||
*
|
||||
* @param url
|
||||
* 短链接 url
|
||||
*
|
||||
* @return 短链接信息
|
||||
*/
|
||||
public ShortLink findByStorageIdAndUrl(Integer storageId, String url) {
|
||||
return shortLinkMapper.findByStorageIdAndUrl(storageId, url);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据存储源 KEY 和文件路径查询短链接
|
||||
*
|
||||
* @param storageKey
|
||||
* 存储源 KEY
|
||||
*
|
||||
* @param url
|
||||
* 短链接 url
|
||||
*
|
||||
* @return 短链接信息
|
||||
*/
|
||||
public ShortLink findByStorageKeyAndUrl(String storageKey,String url) {
|
||||
Integer storageId = storageSourceService.findIdByKey(storageKey);
|
||||
return findByStorageIdAndUrl(storageId, url);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 为存储源指定路径生成短链接, 保证生成的短连接 key 是不同的
|
||||
*
|
||||
* @param storageId
|
||||
* 存储源 id
|
||||
*
|
||||
* @param fullPath
|
||||
* 存储源路径
|
||||
*
|
||||
* @return 生成后的短链接信息
|
||||
*/
|
||||
public ShortLink generatorShortLink(Integer storageId, String fullPath) {
|
||||
ShortLink shortLink;
|
||||
String randomKey;
|
||||
do {
|
||||
// 获取短链
|
||||
randomKey = RandomUtil.randomString(6);
|
||||
shortLink = findByKey(randomKey);
|
||||
} while (shortLink != null);
|
||||
|
||||
shortLink = new ShortLink();
|
||||
shortLink.setShortKey(randomKey);
|
||||
shortLink.setUrl(fullPath);
|
||||
shortLink.setCreateDate(new Date());
|
||||
shortLink.setStorageId(storageId);
|
||||
save(shortLink);
|
||||
|
||||
return shortLink;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 处理指定存储源的下载请求
|
||||
*
|
||||
* @param storageKey
|
||||
* 存储源 key
|
||||
*
|
||||
* @param filePath
|
||||
* 文件路径
|
||||
*
|
||||
* @param shortKey
|
||||
* 短链接 key
|
||||
*
|
||||
* @throws IOException 可能抛出的 IO 异常
|
||||
*/
|
||||
public void handlerDownload(String storageKey, String filePath, String shortKey) throws IOException {
|
||||
HttpServletResponse response = RequestHolder.getResponse();
|
||||
|
||||
// 获取存储源 Service
|
||||
AbstractBaseFileService<?> fileService;
|
||||
try {
|
||||
fileService = storageSourceContext.getByKey(storageKey);
|
||||
} catch (InvalidStorageSourceException e) {
|
||||
log.error("无效的存储源,存储源 key {}, 文件路径 {}", storageKey, filePath);
|
||||
response.setHeader(HttpHeaders.CONTENT_TYPE, "text/plain;charset=utf-8");
|
||||
response.getWriter().write("无效的或初始化失败的存储源, 请联系管理员!");
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取文件下载链接
|
||||
String downloadUrl;
|
||||
try {
|
||||
downloadUrl = fileService.getDownloadUrl(filePath);
|
||||
} catch (DownloadFileException e) {
|
||||
log.error("获取文件下载链接异常 {}. 存储源 ID: {}, 文件路径: {}", e.getMessage(), e.getStorageId(), e.getPathAndName());
|
||||
response.setHeader(HttpHeaders.CONTENT_TYPE, "text/plain;charset=utf-8");
|
||||
response.getWriter().write("获取下载链接异常,请联系管理员!");
|
||||
return;
|
||||
}
|
||||
|
||||
// 判断下载链接是否为空
|
||||
if (StrUtil.isEmpty(downloadUrl)) {
|
||||
log.error("获取到文件下载链接为空,存储源 key {}, 文件路径 {}", storageKey, filePath);
|
||||
response.setHeader(HttpHeaders.CONTENT_TYPE, "text/plain;charset=utf-8");
|
||||
response.getWriter().write("获取下载链接异常,请联系管理员![2]");
|
||||
}
|
||||
|
||||
// 记录下载日志.
|
||||
SystemConfigDTO systemConfig = systemConfigService.getSystemConfig();
|
||||
Boolean recordDownloadLog = systemConfig.getRecordDownloadLog();
|
||||
if (BooleanUtil.isTrue(recordDownloadLog)) {
|
||||
DownloadLog downloadLog = new DownloadLog(filePath, storageKey, shortKey);
|
||||
downloadLogService.save(downloadLog);
|
||||
}
|
||||
|
||||
// 判断下载链接是否为 m3u8 格式, 如果是则返回 m3u8 内容.
|
||||
if (StrUtil.equalsIgnoreCase(FileUtil.extName(filePath), "m3u8")) {
|
||||
String textContent = HttpUtil.getTextContent(downloadUrl);
|
||||
response.setContentType("application/vnd.apple.mpegurl;charset=utf-8");
|
||||
OutputStream outputStream = response.getOutputStream();
|
||||
byte[] textContentBytes = EncodingUtils.getBytes(textContent, CharsetUtil.CHARSET_UTF_8.displayName());
|
||||
IoUtil.write(outputStream, true, textContentBytes);
|
||||
return;
|
||||
}
|
||||
|
||||
// 禁止直链被浏览器 302 缓存.
|
||||
response.setHeader(HttpHeaders.CACHE_CONTROL, "no-cache, no-store, must-revalidate, private");
|
||||
response.setHeader(HttpHeaders.PRAGMA, "no-cache");
|
||||
response.setHeader(HttpHeaders.EXPIRES, "0");
|
||||
|
||||
// 重定向到下载链接.
|
||||
response.sendRedirect(downloadUrl);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,119 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.service;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import im.zhaojun.zfile.admin.mapper.StorageSourceConfigMapper;
|
||||
import im.zhaojun.zfile.admin.model.entity.StorageSourceConfig;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 存储源拓展配置 Service
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class StorageSourceConfigService extends ServiceImpl<StorageSourceConfigMapper, StorageSourceConfig> implements IService<StorageSourceConfig> {
|
||||
|
||||
@Resource
|
||||
private StorageSourceConfigMapper storageSourceConfigMapper;
|
||||
|
||||
/**
|
||||
* 存储源 ID -> 存储源参数列表对象缓存
|
||||
*/
|
||||
private final Map<Integer, List<StorageSourceConfig>> sourceConfigConfigMapCache = new HashMap<>();
|
||||
|
||||
/**
|
||||
* 根据存储源 ID 查询存储源拓展配置, 并按照存储源 id 排序
|
||||
*
|
||||
* @param storageId
|
||||
* 存储源 ID
|
||||
*
|
||||
* @return 存储源拓展配置列表
|
||||
*/
|
||||
public List<StorageSourceConfig> selectStorageConfigByStorageId(Integer storageId) {
|
||||
if (sourceConfigConfigMapCache.containsKey(storageId)) {
|
||||
return sourceConfigConfigMapCache.get(storageId);
|
||||
} else {
|
||||
List<StorageSourceConfig> dbResult = storageSourceConfigMapper.findByStorageIdOrderById(storageId);
|
||||
sourceConfigConfigMapCache.put(storageId, dbResult);
|
||||
return dbResult;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取指定存储源的指定参数名称
|
||||
*
|
||||
* @param storageId
|
||||
* 存储源 id
|
||||
*
|
||||
* @param name
|
||||
* 参数名
|
||||
*
|
||||
* @return 参数信息
|
||||
*/
|
||||
public StorageSourceConfig findByStorageIdAndName(Integer storageId, String name) {
|
||||
return storageSourceConfigMapper.findByStorageIdAndName(storageId, name);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 批量更新存储源设置
|
||||
*
|
||||
* @param storageSourceConfigList
|
||||
* 存储源设置列表
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateStorageConfig(List<StorageSourceConfig> storageSourceConfigList) {
|
||||
super.updateBatchById(storageSourceConfigList);
|
||||
if (CollUtil.isNotEmpty(storageSourceConfigList)) {
|
||||
StorageSourceConfig first = CollUtil.getFirst(storageSourceConfigList);
|
||||
Integer storageId = first.getStorageId();
|
||||
sourceConfigConfigMapCache.remove(storageId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据存储源 id 删除所有设置
|
||||
*
|
||||
* @param id
|
||||
* 存储源 ID
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deleteByStorageId(Integer id) {
|
||||
storageSourceConfigMapper.deleteByStorageId(id);
|
||||
sourceConfigConfigMapCache.remove(id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 批量保存
|
||||
*
|
||||
* @param entityList
|
||||
* 实体对象集合
|
||||
*
|
||||
* @return 是否保存成功
|
||||
*/
|
||||
@Override
|
||||
public boolean saveBatch(Collection<StorageSourceConfig> entityList) {
|
||||
if (CollUtil.isNotEmpty(entityList)) {
|
||||
StorageSourceConfig storageSourceConfig = CollUtil.getFirst(entityList);
|
||||
Integer storageId = storageSourceConfig.getStorageId();
|
||||
sourceConfigConfigMapCache.put(storageId, new ArrayList<>(entityList));
|
||||
}
|
||||
return saveBatch(entityList, DEFAULT_BATCH_SIZE);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,503 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.service;
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.ReflectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import im.zhaojun.zfile.admin.annotation.model.StorageSourceParamDef;
|
||||
import im.zhaojun.zfile.admin.mapper.StorageSourceMapper;
|
||||
import im.zhaojun.zfile.admin.model.entity.StorageSource;
|
||||
import im.zhaojun.zfile.admin.model.entity.StorageSourceConfig;
|
||||
import im.zhaojun.zfile.admin.model.param.IStorageParam;
|
||||
import im.zhaojun.zfile.admin.model.request.SaveStorageSourceRequest;
|
||||
import im.zhaojun.zfile.common.cache.ZFileCache;
|
||||
import im.zhaojun.zfile.common.context.StorageSourceContext;
|
||||
import im.zhaojun.zfile.common.exception.InitializeStorageSourceException;
|
||||
import im.zhaojun.zfile.common.exception.InvalidStorageSourceException;
|
||||
import im.zhaojun.zfile.home.model.dto.CacheInfoDTO;
|
||||
import im.zhaojun.zfile.home.model.dto.StorageSourceAllParam;
|
||||
import im.zhaojun.zfile.home.model.dto.StorageSourceDTO;
|
||||
import im.zhaojun.zfile.home.model.enums.StorageTypeEnum;
|
||||
import im.zhaojun.zfile.home.model.request.UpdateStorageSortRequest;
|
||||
import im.zhaojun.zfile.home.service.base.AbstractBaseFileService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 存储源基本信息 Service
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class StorageSourceService extends ServiceImpl<StorageSourceMapper, StorageSource> implements IService<StorageSource> {
|
||||
|
||||
@Resource
|
||||
private StorageSourceMapper storageSourceMapper;
|
||||
|
||||
@Resource
|
||||
private StorageSourceConfigService storageSourceConfigService;
|
||||
|
||||
@Resource
|
||||
private StorageSourceContext storageSourceContext;
|
||||
|
||||
@Resource
|
||||
private ZFileCache zFileCache;
|
||||
|
||||
public static final Class<StorageSourceAllParam> STORAGE_SOURCE_ALL_PARAM_CLASS = StorageSourceAllParam.class;
|
||||
|
||||
|
||||
/**
|
||||
* 存储源 ID -> 存储源对象缓存
|
||||
*/
|
||||
private final Map<Integer, StorageSource> storageIdMapCache = new HashMap<>();
|
||||
|
||||
|
||||
/**
|
||||
* 存储源 KEY -> 存储源对象缓存
|
||||
*/
|
||||
private final Map<String, StorageSource> storageKeyMapCache = new HashMap<>();
|
||||
|
||||
|
||||
/**
|
||||
* 获取所有存储源列表
|
||||
*
|
||||
* @return 存储源列表
|
||||
*/
|
||||
public List<StorageSource> findAllOrderByOrderNum() {
|
||||
return storageSourceMapper.findAllOrderByOrderNum();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取所有已启用的存储源列表,按照存储源的排序号排序
|
||||
*
|
||||
* @return 已启用的存储源列表
|
||||
*/
|
||||
public List<StorageSource> findListByEnableOrderByOrderNum() {
|
||||
return storageSourceMapper.findListByEnableOrderByOrderNum();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取指定存储源设置
|
||||
*
|
||||
* @param id
|
||||
* 存储源 ID
|
||||
*
|
||||
* @return 存储源设置
|
||||
*/
|
||||
public StorageSource findById(Integer id) {
|
||||
if (storageIdMapCache.get(id) != null) {
|
||||
return storageIdMapCache.get(id);
|
||||
} else {
|
||||
StorageSource dbResult = storageSourceMapper.selectById(id);
|
||||
storageIdMapCache.put(id, dbResult);
|
||||
return dbResult;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取指定存储源 DTO 对象, 此对象包含详细的参数设置.
|
||||
*
|
||||
* @param id
|
||||
* 存储源 ID
|
||||
*
|
||||
* @return 存储源 DTO
|
||||
*/
|
||||
public StorageSourceDTO findStorageSourceDTOById(Integer id) {
|
||||
StorageSource storageSource = findById(id);
|
||||
Boolean defaultSwitchToImgMode = storageSource.getDefaultSwitchToImgMode();
|
||||
if (defaultSwitchToImgMode == null) {
|
||||
storageSource.setDefaultSwitchToImgMode(false);
|
||||
}
|
||||
|
||||
StorageSourceDTO storageSourceDTO = new StorageSourceDTO();
|
||||
BeanUtils.copyProperties(storageSource, storageSourceDTO);
|
||||
|
||||
List<StorageSourceConfig> storageSourceConfigList = storageSourceConfigService.selectStorageConfigByStorageId(storageSource.getId());
|
||||
|
||||
StorageSourceAllParam storageSourceAllParam = new StorageSourceAllParam();
|
||||
for (StorageSourceConfig storageSourceConfig : storageSourceConfigList) {
|
||||
String name = storageSourceConfig.getName();
|
||||
String value = storageSourceConfig.getValue();
|
||||
|
||||
Field declaredField;
|
||||
try {
|
||||
declaredField = STORAGE_SOURCE_ALL_PARAM_CLASS.getDeclaredField(name);
|
||||
declaredField.setAccessible(true);
|
||||
|
||||
Class<?> paramFieldType = declaredField.getType();
|
||||
Object convertToValue = Convert.convert(paramFieldType, value);
|
||||
declaredField.set(storageSourceAllParam, convertToValue);
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
log.error("通过反射, 将字段 {} 注入 StorageSourceDTO 时出现异常:", name, e);
|
||||
}
|
||||
}
|
||||
|
||||
storageSourceDTO.setStorageSourceAllParam(storageSourceAllParam);
|
||||
return storageSourceDTO;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据 id 获取指定存储源的类型.
|
||||
*
|
||||
* @param id
|
||||
* 存储源 ID
|
||||
*
|
||||
* @return 存储源对应的类型.
|
||||
*/
|
||||
public StorageTypeEnum findStorageTypeById(Integer id) {
|
||||
return findById(id).getType();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 保存存储源基本信息及其对应的参数设置
|
||||
*
|
||||
* @param saveStorageSourceRequest
|
||||
* 存储源 DTO 对象
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void saveStorageSource(SaveStorageSourceRequest saveStorageSourceRequest) {
|
||||
|
||||
// 判断是新增还是修改
|
||||
boolean updateFlag = saveStorageSourceRequest.getId() != null;
|
||||
|
||||
// 保存基本信息
|
||||
StorageSource storageSource = new StorageSource();
|
||||
StorageTypeEnum storageType = saveStorageSourceRequest.getType();
|
||||
BeanUtils.copyProperties(saveStorageSourceRequest, storageSource);
|
||||
|
||||
if (storageSource.getId() == null) {
|
||||
Integer nextId = selectNextId();
|
||||
storageSource.setId(nextId);
|
||||
}
|
||||
|
||||
|
||||
// 获取通过 id 缓存的对象
|
||||
StorageSource cacheStorageSource = storageIdMapCache.get(storageSource.getId());
|
||||
// 如果缓存的对象和当前的对象 key 不同, 则说明修改了 key, 需要移除 key 缓存, 并重新写入.
|
||||
if (ObjectUtil.isNotEmpty(cacheStorageSource) &&
|
||||
!StrUtil.equals(cacheStorageSource.getKey(), storageSource.getKey())) {
|
||||
storageKeyMapCache.remove(cacheStorageSource.getKey());
|
||||
}
|
||||
|
||||
super.saveOrUpdate(storageSource);
|
||||
|
||||
if (StrUtil.isEmpty(storageSource.getKey()) && !StrUtil.equals(storageSource.getId().toString(), storageSource.getKey())) {
|
||||
storageSource.setKey(Convert.toStr(storageSource.getId()));
|
||||
baseMapper.updateById(storageSource);
|
||||
}
|
||||
storageKeyMapCache.put(storageSource.getKey(), storageSource);
|
||||
|
||||
StorageSourceAllParam storageSourceAllParam = saveStorageSourceRequest.getStorageSourceAllParam();
|
||||
|
||||
// 获取该存储源类型需要的参数列表
|
||||
List<StorageSourceParamDef> storageSourceParamList = StorageSourceContext.getStorageSourceParamListByType(storageType);
|
||||
|
||||
List<StorageSourceConfig> storageSourceConfigList = new ArrayList<>();
|
||||
storageSourceConfigService.deleteByStorageId(saveStorageSourceRequest.getId());
|
||||
|
||||
for (StorageSourceParamDef storageSourceParam : storageSourceParamList) {
|
||||
String paramKey = storageSourceParam.getKey();
|
||||
String paramName = storageSourceParam.getName();
|
||||
|
||||
StorageSourceConfig storageSourceConfig = new StorageSourceConfig();
|
||||
storageSourceConfigList.add(storageSourceConfig);
|
||||
|
||||
Object fieldValue = ReflectUtil.getFieldValue(storageSourceAllParam, paramKey);
|
||||
String fieldStrValue = Convert.toStr(fieldValue);
|
||||
|
||||
boolean paramRequired = storageSourceParam.isRequired();
|
||||
String paramDefaultValue = storageSourceParam.getDefaultValue();
|
||||
|
||||
// 如果是必填的, 并且值为空, 则抛出异常
|
||||
if (paramRequired && StrUtil.isEmpty(fieldStrValue)) {
|
||||
throw new InitializeStorageSourceException("存储源参数配置错误: [" + paramName + "] 不能为空");
|
||||
}
|
||||
|
||||
// 如果默认值不为空, 且输入值为空, 则使用默认值
|
||||
if (StrUtil.isNotEmpty(paramDefaultValue) && StrUtil.isEmpty(fieldStrValue)) {
|
||||
fieldStrValue = paramDefaultValue;
|
||||
}
|
||||
|
||||
storageSourceConfig.setTitle(paramName);
|
||||
storageSourceConfig.setName(paramKey);
|
||||
storageSourceConfig.setValue(fieldStrValue);
|
||||
storageSourceConfig.setType(storageType);
|
||||
storageSourceConfig.setStorageId(storageSource.getId());
|
||||
}
|
||||
storageSourceConfigService.saveBatch(storageSourceConfigList);
|
||||
|
||||
storageSourceContext.init(storageSource.getId());
|
||||
|
||||
AbstractBaseFileService<IStorageParam> driveService = storageSourceContext.get(storageSource.getId());
|
||||
if (driveService.getIsUnInitialized()) {
|
||||
throw new InitializeStorageSourceException("初始化异常, 请检查配置是否正确.");
|
||||
}
|
||||
|
||||
if (storageSource.getAutoRefreshCache()) {
|
||||
startAutoCacheRefresh(storageSource.getId());
|
||||
} else if (updateFlag) {
|
||||
stopAutoCacheRefresh(storageSource.getId());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查询存储源最大的 ID
|
||||
*
|
||||
* @return 存储源最大 ID
|
||||
*/
|
||||
public synchronized Integer selectNextId() {
|
||||
Integer maxId = storageSourceMapper.selectMaxId();
|
||||
if (maxId == null) {
|
||||
return 1;
|
||||
} else {
|
||||
return maxId + 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 删除指定存储源设置, 会级联删除其参数设置
|
||||
*
|
||||
* @param id
|
||||
* 存储源 ID
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deleteById(Integer id) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("尝试删除存储源, storageId: {}", id);
|
||||
}
|
||||
StorageSource storageSource = findById(id);
|
||||
storageSourceMapper.deleteById(id);
|
||||
storageSourceConfigService.deleteByStorageId(id);
|
||||
if (storageSource.getEnableCache()) {
|
||||
zFileCache.stopAutoCacheRefresh(id);
|
||||
zFileCache.clear(id);
|
||||
}
|
||||
String key = storageSource.getKey();
|
||||
storageIdMapCache.remove(id);
|
||||
storageKeyMapCache.remove(key);
|
||||
storageSourceContext.destroy(id);
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("尝试删除存储源成功, 已清理相关数据, storageId: {}", id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 更新指定存储源的缓存启用状态
|
||||
*
|
||||
* @param storageId
|
||||
* 存储源 ID
|
||||
*
|
||||
* @param cacheEnable
|
||||
* 是否启用缓存
|
||||
*/
|
||||
public void updateCacheStatus(Integer storageId, Boolean cacheEnable) {
|
||||
StorageSource storageSource = findById(storageId);
|
||||
if (storageSource != null) {
|
||||
storageSource.setEnableCache(cacheEnable);
|
||||
super.saveOrUpdate(storageSource);
|
||||
storageIdMapCache.put(storageId, storageSource);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取指定存储源的缓存信息
|
||||
*
|
||||
* @param storageId
|
||||
* 存储源 ID
|
||||
*
|
||||
* @return 缓存信息
|
||||
*/
|
||||
public CacheInfoDTO findCacheInfo(Integer storageId) {
|
||||
long hitCount = zFileCache.getHitCount(storageId);
|
||||
long missCount = zFileCache.getMissCount(storageId);
|
||||
Set<String> keys = zFileCache.keySet(storageId);
|
||||
int cacheCount = keys.size();
|
||||
return new CacheInfoDTO(cacheCount, hitCount, missCount, keys);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 刷新指定 key 的缓存:
|
||||
* 1. 清空此 key 的缓存.
|
||||
* 2. 重新调用方法写入缓存.
|
||||
*
|
||||
* @param storageId
|
||||
* 存储源 ID
|
||||
*
|
||||
* @param key
|
||||
* 缓存 key (文件夹名称)
|
||||
*/
|
||||
public void refreshCache(Integer storageId, String key) throws Exception {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("手动刷新缓存 storageId: {}, key: {}", storageId, key);
|
||||
}
|
||||
zFileCache.remove(storageId, key);
|
||||
AbstractBaseFileService<?> baseFileService = storageSourceContext.get(storageId);
|
||||
baseFileService.fileList(key);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 开启缓存自动刷新
|
||||
*
|
||||
* @param storageId
|
||||
* 存储源 ID
|
||||
*/
|
||||
public void startAutoCacheRefresh(Integer storageId) {
|
||||
StorageSource storageSource = findById(storageId);
|
||||
storageSource.setAutoRefreshCache(true);
|
||||
super.saveOrUpdate(storageSource);
|
||||
storageIdMapCache.put(storageId, storageSource);
|
||||
zFileCache.startAutoCacheRefresh(storageId);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 停止缓存自动刷新
|
||||
*
|
||||
* @param storageId
|
||||
* 存储源 ID
|
||||
*/
|
||||
public void stopAutoCacheRefresh(Integer storageId) {
|
||||
StorageSource storageSource = findById(storageId);
|
||||
storageSource.setAutoRefreshCache(false);
|
||||
super.saveOrUpdate(storageSource);
|
||||
storageIdMapCache.put(storageId, storageSource);
|
||||
zFileCache.stopAutoCacheRefresh(storageId);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 清理缓存
|
||||
*
|
||||
* @param storageId
|
||||
* 存储源 ID
|
||||
*/
|
||||
public void clearCache(Integer storageId) {
|
||||
zFileCache.clear(storageId);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 交换存储源排序
|
||||
*
|
||||
* @param updateStorageSortRequestList
|
||||
* 更新排序的存储源 id 及排序值列表
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateStorageSort(List<UpdateStorageSortRequest> updateStorageSortRequestList) {
|
||||
for (int i = 0; i < updateStorageSortRequestList.size(); i++) {
|
||||
UpdateStorageSortRequest item = updateStorageSortRequestList.get(i);
|
||||
if (!Objects.equals(i, item.getOrderNum())) {
|
||||
storageSourceMapper.updateSetOrderNumById(i, item.getId());
|
||||
storageIdMapCache.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据存储源 key 获取存储源
|
||||
*
|
||||
* @param storageKey
|
||||
* 存储源 key
|
||||
*
|
||||
* @throws InvalidStorageSourceException 存储源不存在时, 抛出异常.
|
||||
*
|
||||
* @return 存储源信息
|
||||
*/
|
||||
public StorageSource findByStorageKey(String storageKey) {
|
||||
if (storageKeyMapCache.containsKey(storageKey)) {
|
||||
return storageKeyMapCache.get(storageKey);
|
||||
} else {
|
||||
StorageSource storageSource = storageSourceMapper.findByStorageKey(storageKey);
|
||||
if (storageSource != null) {
|
||||
storageKeyMapCache.put(storageKey, storageSource);
|
||||
}
|
||||
return storageSource;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 判断存储源 key 是否已存在 (不读取缓存)
|
||||
*
|
||||
* @param storageKey
|
||||
* 存储源 key
|
||||
*
|
||||
* @return 是否已存在
|
||||
*/
|
||||
public boolean existByStorageKey(String storageKey) {
|
||||
return storageSourceMapper.findIdByStorageKey(storageKey) != null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据存储源 id 获取存储源 key
|
||||
*
|
||||
* @param id
|
||||
* 存储源 id
|
||||
*
|
||||
* @return 存储源 key
|
||||
*/
|
||||
public String findKeyById(Integer id){
|
||||
return findById(id).getKey();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据存储源 key 获取存储源
|
||||
*
|
||||
* @param storageKey
|
||||
* 存储源 key
|
||||
*
|
||||
* @return 存储源信息
|
||||
*/
|
||||
public Integer findIdByKey(String storageKey) {
|
||||
StorageSource storageSource = findByStorageKey(storageKey);
|
||||
if (storageSource == null) {
|
||||
return null;
|
||||
} else {
|
||||
return storageSource.getId();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean updateById(StorageSource entity) {
|
||||
if (entity != null) {
|
||||
Integer id = entity.getId();
|
||||
storageIdMapCache.put(id, entity);
|
||||
storageKeyMapCache.put(entity.getKey(), entity);
|
||||
}
|
||||
return super.updateById(entity);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,270 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.service;
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.convert.ConvertException;
|
||||
import cn.hutool.core.util.EnumUtil;
|
||||
import cn.hutool.core.util.HexUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.crypto.SecureUtil;
|
||||
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import im.zhaojun.zfile.admin.constant.SystemConfigConstant;
|
||||
import im.zhaojun.zfile.admin.mapper.SystemConfigMapper;
|
||||
import im.zhaojun.zfile.admin.model.entity.SystemConfig;
|
||||
import im.zhaojun.zfile.admin.model.enums.LoginVerifyModeEnum;
|
||||
import im.zhaojun.zfile.common.cache.ZFileCache;
|
||||
import im.zhaojun.zfile.common.util.EnumConvertUtils;
|
||||
import im.zhaojun.zfile.home.model.dto.SystemConfigDTO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.annotation.DependsOn;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 系统设置 Service
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@DependsOn("zFileCache")
|
||||
public class SystemConfigService extends ServiceImpl<SystemConfigMapper, SystemConfig> {
|
||||
|
||||
private static final String DEFAULT_USERNAME = "admin";
|
||||
|
||||
private static final String DEFAULT_PASSWORD = "123456";
|
||||
|
||||
private static final LoginVerifyModeEnum DEFAULT_LOGIN_VERIFY_MODE = LoginVerifyModeEnum.IMG_VERIFY_MODE;
|
||||
|
||||
@Resource
|
||||
private ZFileCache zFileCache;
|
||||
|
||||
@Resource
|
||||
private SystemConfigMapper systemConfigMapper;
|
||||
|
||||
private final Class<SystemConfigDTO> systemConfigClazz = SystemConfigDTO.class;
|
||||
|
||||
/**
|
||||
* 获取系统设置, 如果缓存中有, 则去缓存取, 没有则查询数据库并写入到缓存中.
|
||||
*
|
||||
* @return 系统设置
|
||||
*/
|
||||
public SystemConfigDTO getSystemConfig() {
|
||||
SystemConfigDTO cacheConfig = zFileCache.getConfig();
|
||||
if (cacheConfig != null) {
|
||||
return cacheConfig;
|
||||
}
|
||||
|
||||
SystemConfigDTO systemConfigDTO = new SystemConfigDTO();
|
||||
List<SystemConfig> systemConfigList = systemConfigMapper.findAll();
|
||||
|
||||
for (SystemConfig systemConfig : systemConfigList) {
|
||||
String key = systemConfig.getName();
|
||||
|
||||
try {
|
||||
Field field = systemConfigClazz.getDeclaredField(key);
|
||||
field.setAccessible(true);
|
||||
String strVal = systemConfig.getValue();
|
||||
Class<?> fieldType = field.getType();
|
||||
|
||||
Object convertVal;
|
||||
if (EnumUtil.isEnum(fieldType)) {
|
||||
convertVal = EnumConvertUtils.convertStrToEnum(fieldType, strVal);
|
||||
} else {
|
||||
convertVal = Convert.convert(fieldType, strVal);
|
||||
}
|
||||
field.set(systemConfigDTO, convertVal);
|
||||
} catch (NoSuchFieldException | IllegalAccessException | ConvertException e) {
|
||||
log.error("通过反射, 将字段 {} 注入 SystemConfigDTO 时出现异常:", key, e);
|
||||
}
|
||||
}
|
||||
|
||||
zFileCache.updateConfig(systemConfigDTO);
|
||||
return systemConfigDTO;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 更新系统设置, 并清空缓存中的内容.
|
||||
*
|
||||
* @param systemConfigDTO
|
||||
* 系统设置 dto
|
||||
*/
|
||||
public void updateSystemConfig(SystemConfigDTO systemConfigDTO) {
|
||||
List<SystemConfig> systemConfigList = new ArrayList<>();
|
||||
|
||||
Field[] fields = systemConfigClazz.getDeclaredFields();
|
||||
for (Field field : fields) {
|
||||
String key = field.getName();
|
||||
SystemConfig systemConfig = systemConfigMapper.findByName(key);
|
||||
if (systemConfig != null) {
|
||||
field.setAccessible(true);
|
||||
Object val = null;
|
||||
|
||||
try {
|
||||
val = field.get(systemConfigDTO);
|
||||
} catch (IllegalAccessException e) {
|
||||
log.error("通过反射, 从 SystemConfigDTO 获取字段 {} 时出现异常:", key, e);
|
||||
}
|
||||
|
||||
if (val != null) {
|
||||
// 如果是枚举类型, 则取 value 值.
|
||||
if (EnumUtil.isEnum(val)) {
|
||||
val = EnumConvertUtils.convertEnumToStr(val);
|
||||
}
|
||||
systemConfig.setValue(Convert.toStr(val));
|
||||
systemConfigList.add(systemConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
zFileCache.removeConfig();
|
||||
|
||||
systemConfigList.forEach(systemConfig -> systemConfigMapper.updateById(systemConfig));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 重置管理员登录信息, 重置登录账号为 admin, 密码为 123456, 登录校验方式为 图形验证码.
|
||||
*/
|
||||
public void resetAdminLoginInfo() {
|
||||
SystemConfig usernameConfig = systemConfigMapper.findByName(SystemConfigConstant.USERNAME);
|
||||
usernameConfig.setValue(DEFAULT_USERNAME);
|
||||
saveOrUpdate(usernameConfig);
|
||||
|
||||
String encryptionPassword = SecureUtil.md5(DEFAULT_PASSWORD);
|
||||
SystemConfig passwordConfig = systemConfigMapper.findByName(SystemConfigConstant.PASSWORD);
|
||||
passwordConfig.setValue(encryptionPassword);
|
||||
saveOrUpdate(passwordConfig);
|
||||
|
||||
SystemConfig loginVerifyModeConfig = systemConfigMapper.findByName(SystemConfigConstant.LOGIN_VERIFY_MODE);
|
||||
loginVerifyModeConfig.setValue(DEFAULT_LOGIN_VERIFY_MODE.getValue());
|
||||
saveOrUpdate(loginVerifyModeConfig);
|
||||
|
||||
zFileCache.removeConfig();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取是否已安装初始化
|
||||
*
|
||||
* @return 是否已安装初始化
|
||||
*/
|
||||
public boolean getIsInstall() {
|
||||
SystemConfigDTO systemConfigDTO = getSystemConfig();
|
||||
return StrUtil.isNotEmpty(systemConfigDTO.getUsername());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取管理员名称
|
||||
*
|
||||
* @return 管理员名称
|
||||
*/
|
||||
public String getAdminUsername() {
|
||||
SystemConfigDTO systemConfigDTO = getSystemConfig();
|
||||
return systemConfigDTO.getUsername();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取系统是否已初始化
|
||||
*
|
||||
* @return 管理员名称
|
||||
*/
|
||||
public Boolean getSystemIsInstalled() {
|
||||
return getSystemConfig().getInstalled();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取后端站点域名
|
||||
*
|
||||
* @return 后端站点域名
|
||||
*/
|
||||
public String getDomain() {
|
||||
SystemConfigDTO systemConfigDTO = getSystemConfig();
|
||||
return systemConfigDTO.getDomain();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取前端站点域名
|
||||
*
|
||||
* @return 前端站点域名
|
||||
*/
|
||||
public String getFrontDomain() {
|
||||
SystemConfigDTO systemConfigDTO = getSystemConfig();
|
||||
return systemConfigDTO.getFrontDomain();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取实际的前端站点域名
|
||||
*
|
||||
* @return 实际的前端站点域名
|
||||
*/
|
||||
public String getRealFrontDomain() {
|
||||
SystemConfigDTO systemConfigDTO = getSystemConfig();
|
||||
|
||||
String baseUrl = "";
|
||||
|
||||
if (StrUtil.isNotEmpty(systemConfigDTO.getFrontDomain())) {
|
||||
baseUrl = systemConfigDTO.getFrontDomain();
|
||||
} else if (StrUtil.isNotEmpty(systemConfigDTO.getDomain())) {
|
||||
baseUrl = systemConfigDTO.getDomain();
|
||||
}
|
||||
|
||||
return baseUrl;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取前端地址下的 403 页面地址.
|
||||
*
|
||||
* @return 前端地址下的 403 页面地址.
|
||||
*
|
||||
*/
|
||||
public String getForbiddenUrl() {
|
||||
return getRealFrontDomain() + "/403";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取直链前缀
|
||||
*
|
||||
* @return 直链前缀
|
||||
*/
|
||||
public String getDirectLinkPrefix() {
|
||||
SystemConfigDTO systemConfigDTO = getSystemConfig();
|
||||
return systemConfigDTO.getDirectLinkPrefix();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取 RSA Hex 格式密钥
|
||||
*
|
||||
* @return RSA Hex 格式密钥
|
||||
*/
|
||||
public String getRsaHexKey() {
|
||||
SystemConfigDTO systemConfigDTO = getSystemConfig();
|
||||
String rsaHexKey = systemConfigDTO.getRsaHexKey();
|
||||
if (StrUtil.isEmpty(rsaHexKey)) {
|
||||
byte[] key = SecureUtil.generateKey(SymmetricAlgorithm.AES.getValue()).getEncoded();
|
||||
rsaHexKey = HexUtil.encodeHexStr(key);
|
||||
|
||||
SystemConfig loginVerifyModeConfig = systemConfigMapper.findByName(SystemConfigConstant.RSA_HEX_KEY);
|
||||
loginVerifyModeConfig.setValue(rsaHexKey);
|
||||
saveOrUpdate(loginVerifyModeConfig);
|
||||
|
||||
systemConfigDTO.setRsaHexKey(rsaHexKey);
|
||||
zFileCache.updateConfig(systemConfigDTO);
|
||||
}
|
||||
return rsaHexKey;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
package im.zhaojun.zfile.admin.service.login;
|
||||
|
||||
import dev.samstevens.totp.code.CodeVerifier;
|
||||
import dev.samstevens.totp.exceptions.QrGenerationException;
|
||||
import dev.samstevens.totp.qr.QrData;
|
||||
import dev.samstevens.totp.qr.QrDataFactory;
|
||||
import dev.samstevens.totp.qr.QrGenerator;
|
||||
import dev.samstevens.totp.secret.SecretGenerator;
|
||||
import im.zhaojun.zfile.common.exception.LoginVerifyException;
|
||||
import im.zhaojun.zfile.admin.model.request.login.VerifyLogin2FARequest;
|
||||
import im.zhaojun.zfile.admin.model.result.login.Login2FAResult;
|
||||
import im.zhaojun.zfile.home.model.dto.SystemConfigDTO;
|
||||
import im.zhaojun.zfile.admin.model.enums.LoginVerifyModeEnum;
|
||||
import im.zhaojun.zfile.admin.service.SystemConfigService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import static dev.samstevens.totp.util.Utils.getDataUriForImage;
|
||||
|
||||
/**
|
||||
* 2FA 双因素认证 Service
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Service
|
||||
public class TwoFAVerifyService {
|
||||
|
||||
@Resource
|
||||
private SecretGenerator secretGenerator;
|
||||
|
||||
@Resource
|
||||
private QrDataFactory qrDataFactory;
|
||||
|
||||
@Resource
|
||||
private QrGenerator qrGenerator;
|
||||
|
||||
@Resource
|
||||
private CodeVerifier verifier;
|
||||
|
||||
@Resource
|
||||
private SystemConfigService systemConfigService;
|
||||
|
||||
|
||||
/**
|
||||
* 生成 2FA 双因素认证二维码和密钥
|
||||
*
|
||||
* @return 2FA 双因素认证二维码和密钥
|
||||
* @throws QrGenerationException 二维码生成异常
|
||||
*/
|
||||
public Login2FAResult setupDevice() throws QrGenerationException {
|
||||
// 生成 2FA 密钥
|
||||
String secret = secretGenerator.generate();
|
||||
QrData data = qrDataFactory.newBuilder().secret(secret).issuer("ZFile").build();
|
||||
|
||||
// 将生成的 2FA 密钥转换为 Base64 图像字符串
|
||||
String qrCodeImage = getDataUriForImage(
|
||||
qrGenerator.generate(data),
|
||||
qrGenerator.getImageMimeType());
|
||||
|
||||
return new Login2FAResult(qrCodeImage, secret);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 验证 2FA 双因素认证是否正确,正确则进行绑定.
|
||||
*
|
||||
* @param verifyLogin2FARequest
|
||||
* 2FA 双因素认证请求参数
|
||||
*/
|
||||
public void deviceVerify(VerifyLogin2FARequest verifyLogin2FARequest) {
|
||||
String secret = verifyLogin2FARequest.getSecret();
|
||||
String code = verifyLogin2FARequest.getCode();
|
||||
|
||||
if (verifier.isValidCode(secret, code)) {
|
||||
SystemConfigDTO systemConfig = systemConfigService.getSystemConfig();
|
||||
systemConfig.setLoginVerifyMode(LoginVerifyModeEnum.TWO_FACTOR_AUTHENTICATION_MODE);
|
||||
systemConfig.setLoginVerifySecret(secret);
|
||||
systemConfigService.updateSystemConfig(systemConfig);
|
||||
} else {
|
||||
throw new LoginVerifyException("验证码不正确");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 验证 2FA 双因素认证.
|
||||
*
|
||||
* @param loginVerifySecret
|
||||
* 2FA 双因素认证密钥
|
||||
*
|
||||
* @param verifyCode
|
||||
* 2FA 双因素认证验证码
|
||||
*/
|
||||
public void checkCode(String loginVerifySecret, String verifyCode) {
|
||||
if (!verifier.isValidCode(loginVerifySecret, verifyCode)) {
|
||||
throw new LoginVerifyException("验证码错误或已失效");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
package im.zhaojun.zfile.common.cache;
|
||||
|
||||
import cn.hutool.cache.impl.TimedCache;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import im.zhaojun.zfile.common.context.StorageSourceContext;
|
||||
import im.zhaojun.zfile.admin.model.dto.StorageSourceCacheKey;
|
||||
import im.zhaojun.zfile.home.service.base.AbstractBaseFileService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* 自定义缓存类, 实现缓存超时后自动刷新
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Slf4j
|
||||
public class MyTimedCache<K, V> extends TimedCache<K, V> {
|
||||
|
||||
private StorageSourceContext storageSourceContext;
|
||||
|
||||
public MyTimedCache(long timeout) {
|
||||
super(timeout);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 当缓存超时后自动刷新
|
||||
*
|
||||
* @param key
|
||||
* 缓存 key
|
||||
*
|
||||
* @param cachedObject
|
||||
* 缓存值
|
||||
*/
|
||||
@Override
|
||||
protected void onRemove(K key, V cachedObject) {
|
||||
if (storageSourceContext == null) {
|
||||
storageSourceContext = SpringUtil.getBean(StorageSourceContext.class);
|
||||
}
|
||||
|
||||
StorageSourceCacheKey cacheKey = (StorageSourceCacheKey) key;
|
||||
AbstractBaseFileService<?> baseFileService = storageSourceContext.get(cacheKey.getStorageId());
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("尝试刷新缓存: {}", cacheKey);
|
||||
}
|
||||
|
||||
if (baseFileService == null) {
|
||||
log.error("尝试刷新缓存: {}, 时出现异常, 存储源已不存在", cacheKey);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
baseFileService.fileList(cacheKey.getKey());
|
||||
} catch (Exception e) {
|
||||
log.error("尝试刷新缓存 {} 失败", cacheKey);
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,257 +0,0 @@
|
||||
package im.zhaojun.zfile.common.cache;
|
||||
|
||||
import cn.hutool.cache.impl.CacheObj;
|
||||
import im.zhaojun.zfile.admin.model.dto.StorageSourceCacheKey;
|
||||
import im.zhaojun.zfile.admin.model.entity.StorageSource;
|
||||
import im.zhaojun.zfile.admin.service.StorageSourceService;
|
||||
import im.zhaojun.zfile.common.context.StorageSourceContext;
|
||||
import im.zhaojun.zfile.home.model.dto.SystemConfigDTO;
|
||||
import im.zhaojun.zfile.home.model.result.FileItemResult;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
/**
|
||||
* ZFile 缓存工具类
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Service("zFileCache")
|
||||
@Slf4j
|
||||
public class ZFileCache {
|
||||
|
||||
@Resource
|
||||
private StorageSourceService storageSourceService;
|
||||
|
||||
@Resource
|
||||
private StorageSourceContext storageSourceContext;
|
||||
|
||||
/**
|
||||
* 缓存过期时间
|
||||
*/
|
||||
@Value("${zfile.cache.timeout}")
|
||||
private long timeout;
|
||||
|
||||
/**
|
||||
* 缓存自动刷新间隔
|
||||
*/
|
||||
@Value("${zfile.cache.auto-refresh.interval}")
|
||||
private long autoRefreshInterval;
|
||||
|
||||
/**
|
||||
* 文件/文件对象缓存.
|
||||
*
|
||||
* ConcurrentMap<Integer, ConcurrentHashMap<String, List<FileItemDTO>>>
|
||||
* ConcurrentMap<storageId, ConcurrentHashMap<key, value>>
|
||||
*
|
||||
* storageId: 存储源 ID
|
||||
* key: 文件夹路径
|
||||
* value: 文件夹中内容
|
||||
*/
|
||||
private final ConcurrentMap<Integer, MyTimedCache<StorageSourceCacheKey, List<FileItemResult>>> storageSourcesCache = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* 系统设置缓存
|
||||
*/
|
||||
private SystemConfigDTO systemConfigCache;
|
||||
|
||||
|
||||
/**
|
||||
* 写入缓存
|
||||
*
|
||||
* @param storageId
|
||||
* 存储源 ID
|
||||
*
|
||||
* @param key
|
||||
* 文件夹路径
|
||||
*
|
||||
* @param value
|
||||
* 文件夹中列表
|
||||
*/
|
||||
public synchronized void put(Integer storageId, String key, List<FileItemResult> value) {
|
||||
getCacheByStorageId(storageId).put(new StorageSourceCacheKey(storageId, key), value);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取指定存储源, 某个文件夹的名称
|
||||
*
|
||||
* @param storageId
|
||||
* 存储源 ID
|
||||
*
|
||||
* @param key
|
||||
* 文件夹路径
|
||||
*
|
||||
* @return 存储源中文件夹的内容
|
||||
*/
|
||||
public List<FileItemResult> get(Integer storageId, String key) {
|
||||
return getCacheByStorageId(storageId).get(new StorageSourceCacheKey(storageId, key), false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 清空指定存储源的缓存.
|
||||
*
|
||||
* @param storageId
|
||||
* 存储源 ID
|
||||
*/
|
||||
public void clear(Integer storageId) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("清空存储源所有缓存, storageId: {}", storageId);
|
||||
}
|
||||
getCacheByStorageId(storageId).clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 获取所有缓存 key (文件夹名称)
|
||||
*
|
||||
* @return 所有缓存 key
|
||||
*/
|
||||
public Set<String> keySet(Integer storageId) {
|
||||
Iterator<CacheObj<StorageSourceCacheKey, List<FileItemResult>>> cacheObjIterator = getCacheByStorageId(storageId).cacheObjIterator();
|
||||
Set<String> keys = new HashSet<>();
|
||||
while (cacheObjIterator.hasNext()) {
|
||||
keys.add(cacheObjIterator.next().getKey().getKey());
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 从缓存中删除指定存储源的某个路径的缓存
|
||||
*
|
||||
* @param storageId
|
||||
* 存储源 ID
|
||||
*
|
||||
* @param key
|
||||
* 文件夹路径
|
||||
*/
|
||||
public void remove(Integer storageId, String key) {
|
||||
getCacheByStorageId(storageId).remove(new StorageSourceCacheKey(storageId, key));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 更新缓存中的系统设置
|
||||
*
|
||||
* @param systemConfigCache
|
||||
* 系统设置
|
||||
*/
|
||||
public void updateConfig(SystemConfigDTO systemConfigCache) {
|
||||
this.systemConfigCache = systemConfigCache;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 从缓存中获取系统设置
|
||||
*
|
||||
* @return 系统设置
|
||||
*/
|
||||
public SystemConfigDTO getConfig() {
|
||||
return this.systemConfigCache;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 清空系统设置缓存
|
||||
*/
|
||||
public void removeConfig() {
|
||||
this.systemConfigCache = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取指定存储源对应的缓存
|
||||
*
|
||||
* @param storageId
|
||||
* 存储源 ID
|
||||
*
|
||||
* @return 存储源对应的缓存
|
||||
*/
|
||||
private synchronized MyTimedCache<StorageSourceCacheKey, List<FileItemResult>> getCacheByStorageId(Integer storageId) {
|
||||
MyTimedCache<StorageSourceCacheKey, List<FileItemResult>> driveCache = storageSourcesCache.get(storageId);
|
||||
if (driveCache == null) {
|
||||
driveCache = new MyTimedCache<>(timeout * 1000);
|
||||
storageSourcesCache.put(storageId, driveCache);
|
||||
startAutoCacheRefresh(storageId);
|
||||
}
|
||||
return driveCache;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取指定存储源的缓存命中数
|
||||
*
|
||||
* @param storageId
|
||||
* 存储源 ID
|
||||
*
|
||||
* @return 缓存命中数
|
||||
*/
|
||||
public long getHitCount(Integer storageId) {
|
||||
return getCacheByStorageId(storageId).getHitCount();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取指定存储源的缓存未命中数
|
||||
*
|
||||
* @param storageId
|
||||
* 存储源 ID
|
||||
*
|
||||
* @return 缓存未命中数
|
||||
*/
|
||||
public long getMissCount(Integer storageId) {
|
||||
return getCacheByStorageId(storageId).getMissCount();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 开启缓存自动刷新
|
||||
*
|
||||
* @param storageId
|
||||
* 存储源 ID
|
||||
*/
|
||||
public void startAutoCacheRefresh(Integer storageId) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("开启缓存自动刷新 storageId: {}", storageId);
|
||||
}
|
||||
StorageSource storageSource = storageSourceService.findById(storageId);
|
||||
Boolean autoRefreshCache = storageSource.getAutoRefreshCache();
|
||||
if (autoRefreshCache != null && autoRefreshCache) {
|
||||
MyTimedCache<StorageSourceCacheKey, List<FileItemResult>> driveCache = storageSourcesCache.get(storageId);
|
||||
if (driveCache == null) {
|
||||
driveCache = new MyTimedCache<>(timeout * 1000);
|
||||
storageSourcesCache.put(storageId, driveCache);
|
||||
}
|
||||
driveCache.schedulePrune(autoRefreshInterval * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 停止缓存自动刷新
|
||||
*
|
||||
* @param storageId
|
||||
* 存储源 ID
|
||||
*/
|
||||
public void stopAutoCacheRefresh(Integer storageId) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("停止缓存自动刷新 storageId: {}", storageId);
|
||||
}
|
||||
MyTimedCache<StorageSourceCacheKey, List<FileItemResult>> driveCache = storageSourcesCache.get(storageId);
|
||||
if (driveCache != null) {
|
||||
driveCache.cancelPruneSchedule();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
package im.zhaojun.zfile.common.config;
|
||||
@@ -1 +0,0 @@
|
||||
package im.zhaojun.zfile.common.config;
|
||||
@@ -1,60 +0,0 @@
|
||||
package im.zhaojun.zfile.common.config;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.annotation.DbType;
|
||||
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
|
||||
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.Resource;
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* mybatis-plus 配置类
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Configuration
|
||||
public class MyBatisPlusConfig {
|
||||
|
||||
@Resource
|
||||
private DataSource dataSource;
|
||||
|
||||
@Value("${spring.datasource.driver-class-name}")
|
||||
private String datasourceDriveClassName;
|
||||
|
||||
@Value("${spring.datasource.url}")
|
||||
private String datasourceUrl;
|
||||
|
||||
/**
|
||||
* 如果是 sqlite 数据库,自动创建数据库文件所在目录
|
||||
*/
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
if (StrUtil.equals(datasourceDriveClassName, "org.sqlite.JDBC")) {
|
||||
String path = datasourceUrl.replace("jdbc:sqlite:", "");
|
||||
String folderPath = FileUtil.getParent(path, 1);
|
||||
if (!FileUtil.exist(folderPath)) {
|
||||
FileUtil.mkdir(folderPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* mybatis plus 分页插件配置
|
||||
*/
|
||||
@Bean
|
||||
public MybatisPlusInterceptor mybatisPlusInterceptor() throws SQLException {
|
||||
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
|
||||
String databaseProductName = dataSource.getConnection().getMetaData().getDatabaseProductName();
|
||||
DbType dbType = DbType.getDbType(databaseProductName);
|
||||
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(dbType));
|
||||
return interceptor;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,173 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011-2022, baomidou (jobob@qq.com).
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package im.zhaojun.zfile.common.config;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.EnumValue;
|
||||
import com.baomidou.mybatisplus.annotation.IEnum;
|
||||
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
||||
import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
|
||||
import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||
import org.apache.ibatis.reflection.DefaultReflectorFactory;
|
||||
import org.apache.ibatis.reflection.MetaClass;
|
||||
import org.apache.ibatis.reflection.ReflectorFactory;
|
||||
import org.apache.ibatis.reflection.invoker.Invoker;
|
||||
import org.apache.ibatis.type.BaseTypeHandler;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* 自定义枚举属性转换器
|
||||
*
|
||||
* @author hubin
|
||||
* @since 2017-10-11
|
||||
*/
|
||||
public class MybatisEnumTypeHandler<E extends Enum<E>> extends BaseTypeHandler<E> {
|
||||
|
||||
private static final Map<String, String> TABLE_METHOD_OF_ENUM_TYPES = new ConcurrentHashMap<>();
|
||||
private static final ReflectorFactory REFLECTOR_FACTORY = new DefaultReflectorFactory();
|
||||
private final Class<E> enumClassType;
|
||||
private final Class<?> propertyType;
|
||||
private final Invoker getInvoker;
|
||||
|
||||
public MybatisEnumTypeHandler(Class<E> enumClassType) {
|
||||
if (enumClassType == null) {
|
||||
throw new IllegalArgumentException("Type argument cannot be null");
|
||||
}
|
||||
this.enumClassType = enumClassType;
|
||||
MetaClass metaClass = MetaClass.forClass(enumClassType, REFLECTOR_FACTORY);
|
||||
String name = "value";
|
||||
if (!IEnum.class.isAssignableFrom(enumClassType)) {
|
||||
name = findEnumValueFieldName(this.enumClassType).orElseThrow(() -> new IllegalArgumentException(String.format("Could not find @EnumValue in Class: %s.", this.enumClassType.getName())));
|
||||
}
|
||||
this.propertyType = ReflectionKit.resolvePrimitiveIfNecessary(metaClass.getGetterType(name));
|
||||
this.getInvoker = metaClass.getGetInvoker(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找标记标记EnumValue字段
|
||||
*
|
||||
* @param clazz class
|
||||
* @return EnumValue字段
|
||||
* @since 3.3.1
|
||||
*/
|
||||
public static Optional<String> findEnumValueFieldName(Class<?> clazz) {
|
||||
if (clazz != null && clazz.isEnum()) {
|
||||
String className = clazz.getName();
|
||||
return Optional.ofNullable(CollectionUtils.computeIfAbsent(TABLE_METHOD_OF_ENUM_TYPES, className, key -> {
|
||||
Optional<Field> fieldOptional = findEnumValueAnnotationField(clazz);
|
||||
return fieldOptional.map(Field::getName).orElse(null);
|
||||
}));
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
private static Optional<Field> findEnumValueAnnotationField(Class<?> clazz) {
|
||||
return Arrays.stream(clazz.getDeclaredFields()).filter(field -> field.isAnnotationPresent(EnumValue.class)).findFirst();
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为MP枚举处理
|
||||
*
|
||||
* @param clazz class
|
||||
* @return 是否为MP枚举处理
|
||||
* @since 3.3.1
|
||||
*/
|
||||
public static boolean isMpEnums(Class<?> clazz) {
|
||||
return clazz != null && clazz.isEnum() && (IEnum.class.isAssignableFrom(clazz) || findEnumValueFieldName(clazz).isPresent());
|
||||
}
|
||||
|
||||
@SuppressWarnings("Duplicates")
|
||||
@Override
|
||||
public void setNonNullParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType)
|
||||
throws SQLException {
|
||||
if (jdbcType == null) {
|
||||
ps.setObject(i, this.getValue(parameter));
|
||||
} else {
|
||||
// see r3589
|
||||
ps.setObject(i, this.getValue(parameter), jdbcType.TYPE_CODE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
|
||||
Object value = rs.getObject(columnName);
|
||||
if (null == value && rs.wasNull()) {
|
||||
return null;
|
||||
}
|
||||
return this.valueOf(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
|
||||
Object value = rs.getObject(columnIndex, this.propertyType);
|
||||
if (null == value && rs.wasNull()) {
|
||||
return null;
|
||||
}
|
||||
return this.valueOf(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
|
||||
Object value = cs.getObject(columnIndex, this.propertyType);
|
||||
if (null == value && cs.wasNull()) {
|
||||
return null;
|
||||
}
|
||||
return this.valueOf(value);
|
||||
}
|
||||
|
||||
private E valueOf(Object value) {
|
||||
E[] es = this.enumClassType.getEnumConstants();
|
||||
return Arrays.stream(es).filter((e) -> equalsValue(value, getValue(e))).findAny().orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 值比较
|
||||
*
|
||||
* @param sourceValue 数据库字段值
|
||||
* @param targetValue 当前枚举属性值
|
||||
* @return 是否匹配
|
||||
* @since 3.3.0
|
||||
*/
|
||||
protected boolean equalsValue(Object sourceValue, Object targetValue) {
|
||||
String sValue = StringUtils.toStringTrim(sourceValue);
|
||||
String tValue = StringUtils.toStringTrim(targetValue);
|
||||
if (sourceValue instanceof Number && targetValue instanceof Number
|
||||
&& new BigDecimal(sValue).compareTo(new BigDecimal(tValue)) == 0) {
|
||||
return true;
|
||||
}
|
||||
return Objects.equals(sValue, tValue);
|
||||
}
|
||||
|
||||
private Object getValue(Object object) {
|
||||
try {
|
||||
return this.getInvoker.invoke(object, new Object[0]);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw ExceptionUtils.mpe(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
package im.zhaojun.zfile.common.config;
|
||||
|
||||
import im.zhaojun.zfile.admin.constant.StorageConfigConstant;
|
||||
import im.zhaojun.zfile.admin.model.entity.StorageSourceConfig;
|
||||
import im.zhaojun.zfile.admin.service.StorageSourceConfigService;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.client.ClientHttpRequestInterceptor;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
|
||||
import org.springframework.http.client.OkHttp3ClientHttpRequestFactory;
|
||||
import org.springframework.http.converter.StringHttpMessageConverter;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* restTemplate 相关配置
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Configuration
|
||||
public class RestTemplateConfig {
|
||||
|
||||
@Resource
|
||||
private StorageSourceConfigService storageSourceConfigService;
|
||||
|
||||
/**
|
||||
* OneDrive 请求 RestTemplate.
|
||||
* 获取 header 中的 storageId 来判断到底是哪个存储源 ID, 在请求头中添加 Bearer: Authorization {token} 信息, 用于 API 认证.
|
||||
*/
|
||||
@Bean
|
||||
public RestTemplate oneDriveRestTemplate() {
|
||||
RestTemplate restTemplate = new RestTemplate();
|
||||
OkHttp3ClientHttpRequestFactory factory = new OkHttp3ClientHttpRequestFactory();
|
||||
restTemplate.setRequestFactory(factory);
|
||||
ClientHttpRequestInterceptor interceptor = (httpRequest, bytes, clientHttpRequestExecution) -> {
|
||||
HttpHeaders headers = httpRequest.getHeaders();
|
||||
Integer storageId = Integer.valueOf(((List)headers.get("storageId")).get(0).toString());
|
||||
|
||||
StorageSourceConfig accessTokenConfig =
|
||||
storageSourceConfigService.findByStorageIdAndName(storageId, StorageConfigConstant.ACCESS_TOKEN_KEY);
|
||||
|
||||
String tokenValue = String.format("%s %s", "Bearer", accessTokenConfig.getValue());
|
||||
httpRequest.getHeaders().add("Authorization", tokenValue);
|
||||
return clientHttpRequestExecution.execute(httpRequest, bytes);
|
||||
};
|
||||
restTemplate.setInterceptors(Collections.singletonList(interceptor));
|
||||
return restTemplate;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* restTemplate 设置请求和响应字符集都为 UTF-8, 并设置响应头为 Content-Type: application/text;
|
||||
*/
|
||||
@Bean
|
||||
public RestTemplate restTemplate(){
|
||||
HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
|
||||
HttpClient httpClient = HttpClientBuilder.create().build();
|
||||
httpRequestFactory.setHttpClient(httpClient);
|
||||
RestTemplate restTemplate = new RestTemplate(httpRequestFactory);
|
||||
restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
|
||||
restTemplate.setInterceptors(Collections.singletonList((request, body, execution) -> {
|
||||
ClientHttpResponse response = execution.execute(request, body);
|
||||
HttpHeaders headers = response.getHeaders();
|
||||
headers.put("Content-Type", Collections.singletonList("application/text"));
|
||||
return response;
|
||||
}));
|
||||
|
||||
return restTemplate;
|
||||
}
|
||||
|
||||
}
|
||||