feat: Implement OCToken NFT Open Collaborator Award mechanism (Fixes #53)#76
feat: Implement OCToken NFT Open Collaborator Award mechanism (Fixes #53)#76sureshchouksey8 wants to merge 6 commits into
Conversation
📝 WalkthroughWalkthrough新增 Award 类型字段,并实现 ChangesAward 颁发
🎯 3 (Moderate) | ⏱️ ~20 分钟
可能相关的 PR
建议标签
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 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.
Actionable comments posted: 1
🧹 Nitpick comments (1)
pages/api/Lark/award/issue.ts (1)
13-15: ⚡ Quick win建议补充
walletAddress格式校验,避免脏数据入库。当前只校验非空,非法地址也会被写入
Award记录,后续发放/查询会出现数据一致性问题。建议在参数校验阶段增加地址格式检查。✅ 可直接应用的最小修复
if (!recordId || !walletAddress) { context.throw(400, 'recordId and walletAddress are required'); } + if (!/^0x[a-fA-F0-9]{40}$/.test(walletAddress)) { + context.throw(400, 'walletAddress format is invalid'); + }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@pages/api/Lark/award/issue.ts` around lines 13 - 15, 当前只对 walletAddress 做了非空校验,应增加格式校验以避免非法地址入库:在 issue.ts 中对 recordId 和 walletAddress 的现有校验位置(与 context.throw(400, ...) 同块)加入地址格式验证(例如以 /^0x[a-fA-F0-9]{40}$/ 或项目统一的 isValidAddress(address) 工具函数进行校验),如果验证失败则用 context.throw(400, 'invalid walletAddress') 返回错误;确保后续写入 Award 记录前通过该校验。
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@pages/api/Lark/award/issue.ts`:
- Around line 18-19: The current code fabricates transactionHash and tokenId
locally instead of calling the real minting/issuance service; replace the
Math.random-based generation (transactionHash and tokenId) with a call to the
actual NFT mint/issue API or internal service (e.g., call mintService.mint(...)
or nftIssuer.issue(...)), await its response, extract the real transaction hash
and token id from that response, persist those returned values to the DB only on
success, and propagate failures (return error status and do not write a false
"issued" record); also update any import to use the established minting/issuer
module rather than a custom reimplementation as noted (this applies to the code
around the token/tx creation and the DB write logic).
---
Nitpick comments:
In `@pages/api/Lark/award/issue.ts`:
- Around line 13-15: 当前只对 walletAddress 做了非空校验,应增加格式校验以避免非法地址入库:在 issue.ts 中对
recordId 和 walletAddress 的现有校验位置(与 context.throw(400, ...) 同块)加入地址格式验证(例如以
/^0x[a-fA-F0-9]{40}$/ 或项目统一的 isValidAddress(address) 工具函数进行校验),如果验证失败则用
context.throw(400, 'invalid walletAddress') 返回错误;确保后续写入 Award 记录前通过该校验。
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 301da9bf-45d2-4afe-a63d-882e323de5e7
📒 Files selected for processing (2)
models/Award.tspages/api/Lark/award/issue.ts
|
Validation update for linked bounty #53:
Current PR head is |
|
Addressed the remaining CodeRabbit wallet validation nit in What changed:
Validation rerun locally:
This keeps PR #76 aligned with issue #53 while preventing malformed wallet data from entering the award table. |
|
Scope clarification for review on #53: While rechecking CodeRabbit's note about the generated So the current PR should be reviewed as the Lark/Bitable award issuance data-flow slice:
I do not want to overclaim this as a real on-chain mint without an existing OCToken service contract/API in the project. If the intended acceptance criterion is real chain minting, please point me to the issuer API/contract/module to integrate; otherwise this is ready for review as the award-table issuance workflow for the |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (1)
pages/api/Lark/award/issue.ts (1)
13-40: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value避免使用
any,请补充强类型以符合 TypeScript 规范。
(context.request as any).body与await response.json()(data为隐式any)绕过了类型检查,data.transactionHash/data.tokenId缺乏校验保障。建议为请求体与铸造响应定义接口类型。🔧 示意:为请求体与响应定义类型
- const { recordId, walletAddress } = (context.request as any).body; + const { recordId, walletAddress } = context.request.body as { + recordId?: string; + walletAddress?: string; + }; @@ - const data = await response.json(); - transactionHash = data.transactionHash; - tokenId = data.tokenId; + const data = (await response.json()) as { + transactionHash?: string; + tokenId?: string; + }; + transactionHash = data.transactionHash; + tokenId = data.tokenId;如代码规范
**/*.{ts,tsx}所述:“Let TypeScript infer types when possible to avoid verbose annotations”,应避免使用any削弱类型安全。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@pages/api/Lark/award/issue.ts` around lines 13 - 40, The issue is that `issue.ts` uses `any` for both the incoming request body and the mint API response, which bypasses TypeScript safety. Update the handler around `context.request` and the `fetch`/`response.json()` flow by introducing explicit interfaces for the request payload and the mint response, then use those types instead of `(context.request as any).body` and untyped `data` in the `walletAddress`, `recordId`, `transactionHash`, and `tokenId` assignments. Keep the validation in `issue`/`mint` flow intact, but ensure the parsed JSON is checked against the typed response shape before reading its fields.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@pages/api/Lark/award/issue.ts`:
- Around line 26-47: 外部铸造调用缺少超时控制,`issue.ts` 中的 `fetch(mintApiUrl, ...)` 可能因
`NFT_MINT_API` 慢响应而一直挂起;请在该铸造请求里加入 `AbortController` 或等效超时机制,并让超时时间与默认
`mintApiUrl` 一样可通过配置覆盖。更新 `context.throw` 处理路径,确保超时被明确转换为 502/可读错误,并保留
`transactionHash`、`tokenId` 的现有校验逻辑不变。
- Line 12: The issue is that the /issue endpoint in router.post currently only
authenticates with verifyJWT and lacks authorization checks for the specific
resource being awarded. Add a permission check inside the award handler to
verify the authenticated user is allowed to operate on the targeted
walletAddress or recordId, such as confirming ownership or requiring admin
privileges, and reject unauthorized requests before proceeding with the issue
flow.
- Around line 12-57: Add an idempotency check to the award issuance flow in the
router.post('/issue') handler before calling the Mint API. Use AwardModel to
query whether the incoming recordId already has an existing issuance record, and
if it does, either return the existing transaction/token data or throw a 409
conflict instead of minting again. Keep the check close to the existing fetch
logic so the repeated-submit path is handled before any external side effects.
---
Nitpick comments:
In `@pages/api/Lark/award/issue.ts`:
- Around line 13-40: The issue is that `issue.ts` uses `any` for both the
incoming request body and the mint API response, which bypasses TypeScript
safety. Update the handler around `context.request` and the
`fetch`/`response.json()` flow by introducing explicit interfaces for the
request payload and the mint response, then use those types instead of
`(context.request as any).body` and untyped `data` in the `walletAddress`,
`recordId`, `transactionHash`, and `tokenId` assignments. Keep the validation in
`issue`/`mint` flow intact, but ensure the parsed JSON is checked against the
typed response shape before reading its fields.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 99777876-4de5-4f5f-8732-247dd4c540f4
📒 Files selected for processing (1)
pages/api/Lark/award/issue.ts
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
pages/api/Lark/award/issue.ts (2)
13-25: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win先校验
recordId类型再访问 Lark 与铸造服务。当前只做 truthy 检查,数组或对象会继续进入
getOne()、mint 请求体和updateOne()。请收窄为非空字符串并复用规范化后的值。建议修复
- const { recordId, walletAddress } = (context.request as any).body; + const { recordId, walletAddress } = (context.request.body ?? {}) as { + recordId?: unknown; + walletAddress?: unknown; + }; - if (!recordId || !walletAddress) { + if (typeof recordId !== 'string' || !recordId.trim() || !walletAddress) { context.throw(400, 'recordId and walletAddress are required'); } + + const awardRecordId = recordId.trim(); - const award = await awardModel.getOne(recordId); + const award = await awardModel.getOne(awardRecordId);并在 mint 请求与
updateOne()中使用awardRecordId。Also applies to: 63-67, 89-96
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@pages/api/Lark/award/issue.ts` around lines 13 - 25, The current `recordId` validation in `issue` only checks truthiness, so non-string values can flow into `AwardModel.getOne()`, the Lark mint request, and `updateOne()`. Tighten the input check to require a non-empty string, normalize it once into a canonical variable such as `awardRecordId`, and then use that normalized value everywhere the record ID is passed, including the mint request body and `updateOne()`.
74-80: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win校验 mint 响应 schema 后再写回。
response.json()是不可信边界;仅做 truthy 检查会让对象、错误格式哈希等值进入持久化。至少校验transactionHash为字符串且符合交易哈希格式,并把tokenId规范化为非空字符串。建议修复
- const data = await response.json(); - transactionHash = data.transactionHash; - tokenId = data.tokenId; + const data = (await response.json()) as { + transactionHash?: unknown; + tokenId?: unknown; + }; + + if ( + typeof data.transactionHash !== 'string' || + !/^0x[a-fA-F0-9]{64}$/.test(data.transactionHash) || + (typeof data.tokenId !== 'string' && typeof data.tokenId !== 'number') || + `${data.tokenId}`.trim() === '' + ) { + throw new Error('Invalid response from minting service'); + } + + transactionHash = data.transactionHash; + tokenId = `${data.tokenId}`; - if (!transactionHash || !tokenId) { - throw new Error('Invalid response from minting service'); - }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@pages/api/Lark/award/issue.ts` around lines 74 - 80, The mint response handling in issueToken should validate the parsed JSON before assigning transactionHash and tokenId. In the response.json() flow, replace the simple truthy check with explicit schema validation: ensure transactionHash is a string matching the expected transaction-hash format and tokenId is normalized to a non-empty string before any write-back or downstream use. If validation fails, keep throwing the invalid response error from issueToken.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@pages/api/Lark/award/issue.ts`:
- Around line 44-52: The current idempotency check in issue flow returns an
existing award purely from transactionHash/tokenId and does not bind the result
to walletAddress, so concurrent requests can still double-mint and later
overwrite each other via updateOne. Update the award issuance path in issue.ts
to make minting idempotent by recordId or by reserving an “issuing” lock/status
before calling the external mint service, then finalize the record after
success; also verify the incoming walletAddress matches the stored wallet and
return 409 on mismatch. Apply the same fix to the duplicated logic around the
referenced issue-processing block so both paths use the same wallet-bound
concurrency guard.
- Around line 36-40: 当前发放授权逻辑在 issueAward 相关校验里使用了 currentUser.name 与 “Robot”
展示名以及 award.nominator/award.nomineeName 做比较,存在重名和篡改风险。请改为基于 JWT 负载中的稳定字段
currentUser.id 做权限判断,并把奖项记录中参与比对的字段切换为内部 ID(包括 Robot 的 ID 0)。确保 issue.ts
中这段授权分支只依赖 ID 级别的身份校验,避免继续使用文本身份。
---
Outside diff comments:
In `@pages/api/Lark/award/issue.ts`:
- Around line 13-25: The current `recordId` validation in `issue` only checks
truthiness, so non-string values can flow into `AwardModel.getOne()`, the Lark
mint request, and `updateOne()`. Tighten the input check to require a non-empty
string, normalize it once into a canonical variable such as `awardRecordId`, and
then use that normalized value everywhere the record ID is passed, including the
mint request body and `updateOne()`.
- Around line 74-80: The mint response handling in issueToken should validate
the parsed JSON before assigning transactionHash and tokenId. In the
response.json() flow, replace the simple truthy check with explicit schema
validation: ensure transactionHash is a string matching the expected
transaction-hash format and tokenId is normalized to a non-empty string before
any write-back or downstream use. If validation fails, keep throwing the invalid
response error from issueToken.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: ac4efecc-2cb5-4b9a-b13e-5faaebc537c2
📒 Files selected for processing (1)
pages/api/Lark/award/issue.ts
| if ( | ||
| currentUser.name !== 'Robot' && | ||
| currentUser.name !== award.nominator && | ||
| currentUser.name !== award.nomineeName | ||
| ) { |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# 验证 verifyJWT 写入 context.state.user 的字段,以及是否已有稳定 role/id 可复用。
rg -nP -C4 '\bverifyJWT\b|context\.state\.user|state\.user|isAdmin|role|userId|email|name' pages models --type=tsRepository: Open-Source-Bazaar/Open-Source-Bazaar.github.io
Length of output: 47055
不要用展示名和 Robot 字符串做发放授权。
currentUser.name 是文本身份,存在重名或篡改风险。验证确认 JWT 负载中包含稳定字段 id(其中 Robot 的 ID 为 0)。请改用 currentUser.id 进行权限校验,并将奖项记录中的比对字段对应为内部 ID,确保认证逻辑的稳定性与安全性。
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@pages/api/Lark/award/issue.ts` around lines 36 - 40, 当前发放授权逻辑在 issueAward
相关校验里使用了 currentUser.name 与 “Robot” 展示名以及 award.nominator/award.nomineeName
做比较,存在重名和篡改风险。请改为基于 JWT 负载中的稳定字段 currentUser.id 做权限判断,并把奖项记录中参与比对的字段切换为内部 ID(包括
Robot 的 ID 0)。确保 issue.ts 中这段授权分支只依赖 ID 级别的身份校验,避免继续使用文本身份。
…n NFT award issue endpoint
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (4)
pages/api/Lark/award/issue.ts (4)
43-45: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win先规范化钱包地址再做幂等绑定。
正则允许 checksum / mixed-case 地址,但 Line 83 是原始字符串比较;同一个 Ethereum 地址只要大小写不同就会被误判为不同钱包并返回 409。
建议修复
if (typeof walletAddress !== 'string' || !EthereumAddressPattern.test(walletAddress)) { context.throw(400, 'walletAddress must be a valid Ethereum address'); } + const normalizedWalletAddress = walletAddress.toLowerCase();- if (award.walletAddress && award.walletAddress !== walletAddress) { + if ( + award.walletAddress && + String(award.walletAddress).toLowerCase() !== normalizedWalletAddress + ) {- walletAddress, + walletAddress: normalizedWalletAddress,- body: JSON.stringify({ walletAddress, recordId }), + body: JSON.stringify({ walletAddress: normalizedWalletAddress, recordId }),Also applies to: 83-84, 95-99, 112-116, 149-154
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@pages/api/Lark/award/issue.ts` around lines 43 - 45, Normalize walletAddress to a canonical form before any idempotency or duplicate-binding checks, because the current raw-string comparisons in the issue flow can treat the same Ethereum address with different casing as different wallets. Update the validation and comparison logic in the award issue handler so the value is normalized once after the EthereumAddressPattern check, then reuse that normalized value in the existing binding/409 paths and any subsequent comparisons in the issue flow.
37-40: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win校验
recordId必须是非空字符串。当前只做 truthy 检查,数组/对象等请求体也会进入
getOne()/updateOne(),把非法 ID 传到模型层。建议修复
const { recordId, walletAddress } = (context.request as any).body; - if (!recordId || !walletAddress) { + if (typeof recordId !== 'string' || !recordId.trim() || !walletAddress) { context.throw(400, 'recordId and walletAddress are required'); } + + const normalizedRecordId = recordId.trim();同时把后续
recordId参数替换为normalizedRecordId。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@pages/api/Lark/award/issue.ts` around lines 37 - 40, The recordId validation in the award issue API only checks truthiness, so non-string values like arrays or objects can still flow into getOne() and updateOne(). Update the handler in issue() to validate recordId as a non-empty string, normalize it into a normalizedRecordId value, and use that normalized variable for the subsequent model calls and any related checks.
108-110: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win为
NFT_MINT_TIMEOUT做正数兜底。
parseInt对非法、0、负数配置不会回退默认值,可能导致立即 abort 或异常超时配置,进而让发放流程整体失败。建议修复
- const timeoutVal = parseInt(process.env.NFT_MINT_TIMEOUT || '10000', 10); + const parsedTimeout = Number(process.env.NFT_MINT_TIMEOUT); + const timeoutVal = + Number.isFinite(parsedTimeout) && parsedTimeout > 0 ? parsedTimeout : 10_000;🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@pages/api/Lark/award/issue.ts` around lines 108 - 110, `NFT_MINT_TIMEOUT` 的解析缺少正数兜底,非法值、0 或负数会被直接用于 `setTimeout` 导致异常超时行为。请在 `issue.ts` 中围绕 `timeoutVal` 和 `AbortController` 增加校验:先解析环境变量,再在 `timeoutVal` 非法或小于等于 0 时回退到默认值 10000,确保 `setTimeout(() => controller.abort(), timeoutVal)` 只使用有效正数超时。
123-129: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win不要把 mint 响应的任意 truthy 值写成凭证。
当前只检查非空;如果 mint 服务返回对象、错误格式哈希或空白
tokenId,记录会被标记为已颁发但凭证不可用。建议修复
const data = await response.json(); - transactionHash = data.transactionHash; - tokenId = data.tokenId; - if (!transactionHash || !tokenId) { + if ( + typeof data.transactionHash !== 'string' || + !/^0x[a-fA-F0-9]{64}$/.test(data.transactionHash) || + typeof data.tokenId !== 'string' || + !data.tokenId.trim() + ) { throw new Error('Invalid response from minting service'); } + + transactionHash = data.transactionHash; + tokenId = data.tokenId.trim();🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@pages/api/Lark/award/issue.ts` around lines 123 - 129, The mint response handling in the issue flow is too permissive and can persist non-usable values as credentials. In the award issuance logic around the response.json parsing, tighten validation before assigning transactionHash and tokenId: verify both fields are the expected primitive string values, reject objects/other truthy shapes, and treat blank or whitespace-only tokenId as invalid. Keep the existing invalid-response error path in the issue handler so only a real transaction hash and usable token ID are written.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@pages/api/Lark/award/issue.ts`:
- Around line 12-20: getUserIds currently does not fully normalize IDs to
strings, and its Boolean filtering can drop valid values like 0, which can break
the later includes-based authorization check in the award issue flow. Update
getUserIds in issue.ts so every branch returns stringified IDs consistently, and
replace the truthy filter with an explicit non-null/non-undefined check; make
sure the downstream logic around the includes check and display-name fallback
continues to work with the normalized string IDs.
---
Outside diff comments:
In `@pages/api/Lark/award/issue.ts`:
- Around line 43-45: Normalize walletAddress to a canonical form before any
idempotency or duplicate-binding checks, because the current raw-string
comparisons in the issue flow can treat the same Ethereum address with different
casing as different wallets. Update the validation and comparison logic in the
award issue handler so the value is normalized once after the
EthereumAddressPattern check, then reuse that normalized value in the existing
binding/409 paths and any subsequent comparisons in the issue flow.
- Around line 37-40: The recordId validation in the award issue API only checks
truthiness, so non-string values like arrays or objects can still flow into
getOne() and updateOne(). Update the handler in issue() to validate recordId as
a non-empty string, normalize it into a normalizedRecordId value, and use that
normalized variable for the subsequent model calls and any related checks.
- Around line 108-110: `NFT_MINT_TIMEOUT` 的解析缺少正数兜底,非法值、0 或负数会被直接用于 `setTimeout`
导致异常超时行为。请在 `issue.ts` 中围绕 `timeoutVal` 和 `AbortController` 增加校验:先解析环境变量,再在
`timeoutVal` 非法或小于等于 0 时回退到默认值 10000,确保 `setTimeout(() => controller.abort(),
timeoutVal)` 只使用有效正数超时。
- Around line 123-129: The mint response handling in the issue flow is too
permissive and can persist non-usable values as credentials. In the award
issuance logic around the response.json parsing, tighten validation before
assigning transactionHash and tokenId: verify both fields are the expected
primitive string values, reject objects/other truthy shapes, and treat blank or
whitespace-only tokenId as invalid. Keep the existing invalid-response error
path in the issue handler so only a real transaction hash and usable token ID
are written.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 9d8b1b81-0c61-4f2c-b1f9-b0eb8119344f
📒 Files selected for processing (1)
pages/api/Lark/award/issue.ts
| const getUserIds = (field: any): string[] => { | ||
| if (!field) return []; | ||
| if (Array.isArray(field)) { | ||
| return field.map(u => (typeof u === 'object' && u ? u.id : String(u))).filter(Boolean); | ||
| } | ||
| if (typeof field === 'object' && field) { | ||
| return [field.id].filter(Boolean); | ||
| } | ||
| return [String(field)]; |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
把 getUserIds 的返回值真正归一化为字符串。
当前对象分支会返回原始 id,且 .filter(Boolean) 会丢掉数值 0;但 Line 64 后续用字符串 ID 做 includes,这会导致 ID 授权误判并落到展示名兜底。
建议修复
const getUserIds = (field: any): string[] => {
if (!field) return [];
if (Array.isArray(field)) {
- return field.map(u => (typeof u === 'object' && u ? u.id : String(u))).filter(Boolean);
+ return field
+ .map(u => (typeof u === 'object' && u ? u.id : u))
+ .filter(id => id !== undefined && id !== null && id !== '')
+ .map(String);
}
if (typeof field === 'object' && field) {
- return [field.id].filter(Boolean);
+ return field.id === undefined || field.id === null || field.id === ''
+ ? []
+ : [String(field.id)];
}
return [String(field)];
};Also applies to: 64-69
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@pages/api/Lark/award/issue.ts` around lines 12 - 20, getUserIds currently
does not fully normalize IDs to strings, and its Boolean filtering can drop
valid values like 0, which can break the later includes-based authorization
check in the award issue flow. Update getUserIds in issue.ts so every branch
returns stringified IDs consistently, and replace the truthy filter with an
explicit non-null/non-undefined check; make sure the downstream logic around the
includes check and display-name fallback continues to work with the normalized
string IDs.
Closes #53
Summary by CodeRabbit
新功能
数据模型变更
Award关键字段(如投票数、钱包地址、交易哈希、代币ID)字段枚举与类型约束。💳 Payout Details
Please send the bounty rewards to the following payout methods: