Skip to content

Commit 6184a97

Browse files
authored
Merge branch 'ling-drag0n:main' into main
2 parents f017dc3 + dd06b88 commit 6184a97

File tree

209 files changed

+6871
-1737
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

209 files changed

+6871
-1737
lines changed

README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
# CloudPaste - Online Clipboard 📋
1+
# CloudPaste 📋
22

33
<div align="center">
44
<p>
55
<a href="README_CN.md">中文</a> | <a href="README.md">English</a> |
6-
<a href="https://www.readme-i18n.com/ling-drag0n/CloudPaste?lang=es">Español</a> |
7-
<a href="https://www.readme-i18n.com/ling-drag0n/CloudPaste?lang=fr">français</a> |
8-
<a href="https://www.readme-i18n.com/ling-drag0n/CloudPaste?lang=ja">日本語</a>
6+
<a href="https://www.readme-i18n.com/ling-drag0n/CloudPaste?lang=es">Español</a> |
7+
<a href="https://www.readme-i18n.com/ling-drag0n/CloudPaste?lang=fr">français</a> |
8+
<a href="https://www.readme-i18n.com/ling-drag0n/CloudPaste?lang=ja">日本語</a>
99
</p>
1010
<img width="100" height="100" src="https://img.icons8.com/dusk/100/paste.png" alt="paste"/>
11-
<h3>Cloudflare-based online clipboard and file sharing service with Markdown editing and file upload support</h3>
11+
<h3>🌩️ Serverless file management and Markdown sharing tool, supports multiple storage aggregation, online preview of 30+ file formats, and WebDAV mounting</h3>
1212
</div>
1313

1414
<div align="center">
@@ -61,7 +61,7 @@
6161
### Multi-Storage Support
6262

6363
- **S3 Compatible**: Cloudflare R2, Backblaze B2, AWS S3, Alibaba Cloud OSS, Tencent Cloud COS, MinIO, etc.
64-
- **Cloud Storage Integration**: WebDAV, OneDrive, Google Drive, Telegram, GitHub API/Releases (read-only), etc.
64+
- **Cloud Storage Integration**: WebDAV, OneDrive, Google Drive, Telegram, HuggingFace Database, GitHub API/Releases (read-only), etc.
6565
- **Local Storage**: Docker deployment supports local file system
6666
- **Smart Upload**: Frontend pre-signed direct upload + streaming upload + chunked resumable upload, with real-time progress display, minimizing CF limitations
6767
- **File Preview**: Direct preview support for 30+ formats (images, videos, audio, PDF, Office, code, e-books, etc.), others can be previewed through external IFrame embedding [KKFileview](https://github.com/kekingcn/kkFileView)

README_CN.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
# CloudPaste - 在线剪贴板 📋
1+
# CloudPaste 📋
22

33
<div align="center">
44
<p>
55
<a href="README_CN.md">中文</a> | <a href="README.md">English</a> |
6-
<a href="https://www.readme-i18n.com/ling-drag0n/CloudPaste?lang=es">Español</a> |
7-
<a href="https://www.readme-i18n.com/ling-drag0n/CloudPaste?lang=fr">français</a> |
8-
<a href="https://www.readme-i18n.com/ling-drag0n/CloudPaste?lang=ja">日本語</a>
6+
<a href="https://www.readme-i18n.com/ling-drag0n/CloudPaste?lang=es">Español</a> |
7+
<a href="https://www.readme-i18n.com/ling-drag0n/CloudPaste?lang=fr">français</a> |
8+
<a href="https://www.readme-i18n.com/ling-drag0n/CloudPaste?lang=ja">日本語</a>
99
</p>
1010
<img width="100" height="100" src="https://img.icons8.com/dusk/100/paste.png" alt="paste"/>
11-
<h3>基于 Cloudflare 的在线剪贴板和文件分享服务,支持 Markdown 编辑和文件上传</h3>
11+
<h3>🌩️ Serverless 文件管理与 Markdown 分享工具,支持多种存储聚合、30+文件格式在线预览 与 WebDAV挂载</h3>
1212
</div>
1313

1414
<div align="center">
@@ -61,7 +61,7 @@
6161
### 多存储支持
6262

6363
- **S3 兼容**:Cloudflare R2、Backblaze B2、AWS S3、阿里云 OSS、腾讯云 COS、MinIO 等
64-
- **网盘集成**:WebDAV、OneDrive、Google Drive、Telegram、GitHub API/Releases(只读)等等
64+
- **网盘集成**:WebDAV、OneDrive、Google Drive、Telegram、HuggingFace Database、GitHub API/Releases(只读)等等
6565
- **本地存储**:Docker 部署支持本地文件系统
6666
- **智能上传**:前端预签名直传 + 流式上传 +分片断点续传,进度实时显示,最大限度摆脱cf限制
6767
- **文件预览**:支持30+种格式直接预览(图片、视频、音频、PDF、Office、代码、电子书等),其余可通过外部IFrame嵌入[KKFileview](https://github.com/kekingcn/kkFileView)预览

backend/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "cloudpaste-api",
3-
"version": "1.8.0",
3+
"version": "1.9.0",
44
"description": "CloudPaste API基于Cloudflare Workers和D1数据库",
55
"main": "unified-entry.js",
66
"scripts": {
@@ -27,15 +27,15 @@
2727
"@aws-sdk/client-s3": "3.726.1",
2828
"@aws-sdk/lib-storage": "3.726.1",
2929
"@aws-sdk/s3-request-presigner": "3.726.1",
30-
"@huggingface/hub": "^2.7.1",
3130
"@hono/node-server": "^1.19.6",
31+
"@huggingface/hub": "^2.7.1",
3232
"better-sqlite3": "^12.5.0",
33+
"cron-parser": "^5.4.0",
3334
"fast-xml-parser": "^5.2.5",
3435
"file-type": "^21.0.0",
3536
"hono": "^4.10.6",
3637
"mime-types": "^3.0.1",
3738
"node-schedule": "^2.1.1",
38-
"cron-parser": "^5.4.0",
3939
"tsx": "^4.21.0",
4040
"webdav": "^5.8.0"
4141
},

backend/src/repositories/StorageConfigRepository.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,10 @@ export class StorageConfigRepository extends BaseRepository {
3131
row,
3232
});
3333

34+
// 注意:row(表字段)优先级应高于 config_json(投影字段)
3435
const merged = {
35-
...row,
3636
...(projected && typeof projected === "object" ? projected : {}),
37+
...row,
3738
};
3839

3940
// 保留原始 config_json 对象(非枚举属性,避免对外暴露)

backend/src/routes/fs/multipart.js

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { MountManager } from "../../storage/managers/MountManager.js";
55
import { FileSystem } from "../../storage/fs/FileSystem.js";
66
import { getEncryptionSecret } from "../../utils/environmentUtils.js";
77
import { usePolicy } from "../../security/policies/policies.js";
8-
import { findUploadSessionById, updateUploadSessionById } from "../../utils/uploadSessions.js";
8+
import { findUploadSessionById, normalizeUploadSessionUserId, updateUploadSessionById } from "../../utils/uploadSessions.js";
99
import { validateFsItemName } from "../../storage/fs/utils/FsInputValidator.js";
1010

1111
/**
@@ -93,6 +93,24 @@ export const registerMultipartRoutes = (router, helpers) => {
9393
return { db: c.env.DB, encryptionSecret: getEncryptionSecret(c), repositoryFactory: c.get("repos"), userInfo, userIdOrInfo, userType };
9494
};
9595

96+
const assertUploadSessionOwnedByUser = (sessionRow, userIdOrInfo, userType) => {
97+
if (!sessionRow) {
98+
throw new ValidationError("未找到对应的上传会话");
99+
}
100+
101+
const expectedUserId = normalizeUploadSessionUserId(userIdOrInfo, userType);
102+
const rowUserId = String(sessionRow.user_id || "");
103+
const rowUserType = String(sessionRow.user_type || "");
104+
105+
// 必须至少匹配 user_id;user_type 为空时视为兼容旧数据(不做强校验)
106+
const idMatches = rowUserId === String(expectedUserId || "");
107+
const typeMatches = !rowUserType || rowUserType === String(userType || "");
108+
109+
if (!idMatches || !typeMatches) {
110+
throw new AuthenticationError("上传会话不属于当前用户,拒绝访问");
111+
}
112+
};
113+
96114
const assertValidFileName = (fileName) => {
97115
const result = validateFsItemName(fileName);
98116
if (result.valid) return;
@@ -148,6 +166,9 @@ export const registerMultipartRoutes = (router, helpers) => {
148166
assertValidFileName(fileName);
149167
}
150168

169+
const sessionRow = await findUploadSessionById(db, { id: uploadId });
170+
assertUploadSessionOwnedByUser(sessionRow, userIdOrInfo, userType);
171+
151172
const mountManager = new MountManager(db, encryptionSecret, repositoryFactory, { env: c.env });
152173
const fileSystem = new FileSystem(mountManager);
153174
const safeParts = Array.isArray(parts) ? parts : [];
@@ -167,6 +188,9 @@ export const registerMultipartRoutes = (router, helpers) => {
167188

168189
assertValidFileName(fileName);
169190

191+
const sessionRow = await findUploadSessionById(db, { id: uploadId });
192+
assertUploadSessionOwnedByUser(sessionRow, userIdOrInfo, userType);
193+
170194
const mountManager = new MountManager(db, encryptionSecret, repositoryFactory, { env: c.env });
171195
const fileSystem = new FileSystem(mountManager);
172196
await fileSystem.abortFrontendMultipartUpload(path, uploadId, fileName, userIdOrInfo, userType);
@@ -200,6 +224,9 @@ export const registerMultipartRoutes = (router, helpers) => {
200224

201225
assertValidFileName(fileName);
202226

227+
const sessionRow = await findUploadSessionById(db, { id: uploadId });
228+
assertUploadSessionOwnedByUser(sessionRow, userIdOrInfo, userType);
229+
203230
const mountManager = new MountManager(db, encryptionSecret, repositoryFactory, { env: c.env });
204231
const fileSystem = new FileSystem(mountManager);
205232
const result = await fileSystem.listMultipartParts(path, uploadId, fileName, userIdOrInfo, userType);
@@ -219,6 +246,9 @@ export const registerMultipartRoutes = (router, helpers) => {
219246

220247
const safePartNumbers = Array.isArray(partNumbers) ? partNumbers : [];
221248

249+
const sessionRow = await findUploadSessionById(db, { id: uploadId });
250+
assertUploadSessionOwnedByUser(sessionRow, userIdOrInfo, userType);
251+
222252
// 状态机推进:请求分片 URL 视为“开始上传”
223253
try {
224254
await updateUploadSessionById(db, {
@@ -266,9 +296,7 @@ export const registerMultipartRoutes = (router, helpers) => {
266296
const contentLength = contentLengthHeader ? Number.parseInt(contentLengthHeader, 10) || 0 : 0;
267297

268298
const sessionRow = await findUploadSessionById(db, { id: uploadId });
269-
if (!sessionRow) {
270-
throw new ValidationError("未找到对应的上传会话");
271-
}
299+
assertUploadSessionOwnedByUser(sessionRow, userIdOrInfo, userType);
272300

273301
const mountManager = new MountManager(db, encryptionSecret, repositoryFactory, { env: c.env });
274302
const fileSystem = new FileSystem(mountManager);

backend/src/routes/systemRoutes.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ systemRoutes.get("/api/version", async (c) => {
9797
const isDocker = runtimeEnv === "docker";
9898

9999
// 统一的默认版本配置
100-
const DEFAULT_VERSION = "1.8.0";
100+
const DEFAULT_VERSION = "1.9.0";
101101
const DEFAULT_NAME = "cloudpaste-api";
102102

103103
let version = DEFAULT_VERSION;

0 commit comments

Comments
 (0)