-
Notifications
You must be signed in to change notification settings - Fork 6
[add] Markdown export & Document copy API of Lark documents #43
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
[add] JWT parser & verifier middlewares [optimize] update Upstream packages
📝 Walkthrough功能概览本次提交新增两个 Lark 文档 API 端点(复制、Markdown 下载)并重构核心 API 中间件,引入 JWT 认证工具,改进错误处理机制,优化前置物质解析逻辑,约涉及 4 个文件的新增与修改。 变更汇总
代码审查工作量评估🎯 3 (中等复杂度) | ⏱️ ~20 分钟 关键审查点:
诗
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (1)
pages/api/core.ts (1)
108-109: ReDoS 风险较低,但建议使用字符串方法替代正则静态分析工具标记了从变量构造正则表达式的潜在 ReDoS 风险。虽然在当前场景下
prefix是受控的(默认为'pages'),但使用字符串方法更安全且性能更好。🔎 建议使用 startsWith + slice 替代正则
- const path = `${parentPath}/${name}`.replace(new RegExp(`^${prefix}`), ''); + const fullPath = `${parentPath}/${name}`; + const path = fullPath.startsWith(prefix) ? fullPath.slice(prefix.length) : fullPath;
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
package.jsonis excluded by none and included by nonepnpm-lock.yamlis excluded by!**/pnpm-lock.yaml,!pnpm-lock.yamland included by none
📒 Files selected for processing (4)
pages/api/Lark/document/copy/[...slug].tspages/api/Lark/document/markdown/[...slug].tspages/api/Lark/file/[id]/[name].tspages/api/core.ts
🧰 Additional context used
📓 Path-based instructions (3)
{models,pages/api}/**/*.ts
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Import and use the configured githubClient from models/Base.ts; do not create new GitHub API instances
Files:
pages/api/Lark/document/copy/[...slug].tspages/api/Lark/file/[id]/[name].tspages/api/Lark/document/markdown/[...slug].tspages/api/core.ts
{models,pages/api}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Decode Base64 GitHub content using atob(item.content) when processing responses
Files:
pages/api/Lark/document/copy/[...slug].tspages/api/Lark/file/[id]/[name].tspages/api/Lark/document/markdown/[...slug].tspages/api/core.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.{ts,tsx}: Use optional chaining and modern ECMAScript features
Let TypeScript infer types when possible to avoid verbose annotations
Import from established sources (e.g., ContentModel from mobx-github, utilities from web-utility) rather than reimplementing
Use minimal exports and avoid unnecessary custom implementations
Files:
pages/api/Lark/document/copy/[...slug].tspages/api/Lark/file/[id]/[name].tspages/api/Lark/document/markdown/[...slug].tspages/api/core.ts
🧬 Code graph analysis (1)
pages/api/core.ts (1)
models/configuration.ts (2)
process(9-9)LarkAppMeta(27-31)
🪛 ast-grep (0.40.3)
pages/api/core.ts
[warning] 108-108: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(^${prefix})
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html
(regexp-from-variable)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Build-and-Deploy
🔇 Additional comments (7)
pages/api/core.ts (3)
19-29: JWT 中间件配置清晰,结构合理
parseJWT(带passthrough: true)和verifyJWT的分离设计很好:
parseJWT用于可选认证场景,即使 Token 无效也会继续执行verifyJWT用于强制认证场景TypeScript 类型
JWTContext正确地使用了联合类型来表示两种可能的状态。
111-127: pageListOf 重构逻辑清晰重构后的逻辑更加简洁:
- 只处理 MDX 文件并附加 meta
- 目录只在有子项时才 yield
- 使用
Array.fromAsync替代手动收集整体结构和可读性有明显提升。
102-102:parentPath与项目 Node.js 版本完全兼容项目已升级至 Node.js 22,
Dirent.parentPath属性(Node.js 18.17.0+ 支持)在当前版本完全兼容,无需调整。pages/api/Lark/file/[id]/[name].ts (2)
33-37: 错误响应处理改进合理先尝试解析 JSON,失败时回退到纯文本,这种处理方式更加健壮。能够正确处理 Lark API 返回的各种错误格式。
50-51: 响应体赋值简化清晰使用三元表达式统一处理 GET 和 HEAD 请求,代码更简洁。
@ts-expect-error用于 Web Stream 与 Node.js Stream 的类型兼容性是合理的临时方案。pages/api/Lark/document/markdown/[...slug].ts (1)
8-15: 新路由结构清晰,中间件使用正确路由正确使用了
safeAPI和verifyJWT中间件进行错误处理和认证保护。Content-Type设置正确包含了 charset。建议可选:对
type参数进行校验,确保只接受合法的文档类型(如'docx'、'wiki'等)。🔎 可选:添加类型校验
router.get('/:type/:id', safeAPI, verifyJWT, async context => { const { type, id } = context.params; + + const validTypes = ['docx', 'wiki', 'sheet', 'bitable']; + if (!validTypes.includes(type)) { + context.status = 400; + context.body = { message: `Invalid document type: ${type}` }; + return; + } const markdown = await lark.downloadMarkdown(`${type}/${id}`);pages/api/Lark/document/copy/[...slug].ts (1)
7-7: bodyParser 禁用配置正确由于使用 Koa 中间件处理请求体,正确禁用了 Next.js 默认的 body parser。
| router.post('/:type/:id', safeAPI, verifyJWT, async (context: Context) => { | ||
| const { type, id } = context.params, | ||
| { name, parentToken } = Reflect.get(context.request, 'body'); | ||
|
|
||
| context.body = await lark.copyFile(`${type as 'wiki'}/${id}`, name, parentToken); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
类型安全问题:建议改进请求体访问方式
使用 Reflect.get(context.request, 'body') 绕过类型检查不是最佳实践。另外,type as 'wiki' 的强制类型断言可能导致运行时错误。
🔎 建议:添加类型定义和输入校验
+interface CopyRequestBody {
+ name: string;
+ parentToken: string;
+}
+
+type DocumentType = 'wiki' | 'docx';
+
router.post('/:type/:id', safeAPI, verifyJWT, async (context: Context) => {
- const { type, id } = context.params,
- { name, parentToken } = Reflect.get(context.request, 'body');
+ const { type, id } = context.params;
+ const body = (context.request as any).body as CopyRequestBody;
+
+ if (!body?.name || !body?.parentToken) {
+ context.status = 400;
+ context.body = { message: 'Missing required fields: name, parentToken' };
+ return;
+ }
+
+ const validTypes: DocumentType[] = ['wiki', 'docx'];
+ if (!validTypes.includes(type as DocumentType)) {
+ context.status = 400;
+ context.body = { message: `Invalid document type: ${type}` };
+ return;
+ }
- context.body = await lark.copyFile(`${type as 'wiki'}/${id}`, name, parentToken);
+ context.body = await lark.copyFile(`${type}/${id}`, body.name, body.parentToken);
});🤖 Prompt for AI Agents
In pages/api/Lark/document/copy/[...slug].ts around lines 11 to 16, the handler
uses Reflect.get(context.request, 'body') and a forced assertion type as 'wiki',
which bypasses type safety and can cause runtime errors; replace this with a
strongly typed request body interface (e.g., interface CopyRequest { name:
string; parentToken?: string }), parse and validate the body using the
framework's request body API into that type, validate required fields (name) and
that context.params.type is one of the allowed values (e.g., 'wiki') before
calling lark.copyFile, and return a 4xx error if validation fails instead of
using a blind type assertion.
Summary by CodeRabbit
发行说明
新功能
改进
✏️ Tip: You can customize this high-level summary in your review settings.