vendure-graphql-reviewing
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseVendure GraphQL Reviewing
Vendure GraphQL 审查
Purpose
目的
Audit Vendure GraphQL resolvers and schema extensions for violations and anti-patterns.
审查Vendure GraphQL解析器和Schema扩展中的违规情况与不良实践。
Review Workflow
审查流程
Step 1: Identify GraphQL Files
步骤1:定位GraphQL文件
bash
undefinedbash
undefinedFind resolver files
查找解析器文件
find . -name "*.resolver.ts"
find . -name "*.resolver.ts"
Find schema files
查找Schema文件
find . -name "schema.ts" -o -name "*.graphql"
undefinedfind . -name "schema.ts" -o -name "*.graphql"
undefinedStep 2: Run Automated Checks
步骤2:运行自动化检查
bash
undefinedbash
undefined=== CRITICAL VIOLATIONS ===
=== 严重违规项 ===
Missing @Ctx() RequestContext
缺失@Ctx() RequestContext
grep -rn "@Query|@Mutation" --include="*.resolver.ts" -A 5 | grep -v "@Ctx()"
grep -rn "@Query|@Mutation" --include="*.resolver.ts" -A 5 | grep -v "@Ctx()"
Missing @Resolver decorator
缺失@Resolver装饰器
grep -rn "export class.Resolver" --include=".resolver.ts" | grep -v "@Resolver"
grep -rn "export class.Resolver" --include=".resolver.ts" | grep -v "@Resolver"
Missing @Allow permissions
缺失@Allow权限装饰器
grep -rn "@Query|@Mutation" --include="*.resolver.ts" -A 3 | grep -v "@Allow"
grep -rn "@Query|@Mutation" --include="*.resolver.ts" -A 3 | grep -v "@Allow"
=== HIGH PRIORITY ===
=== 高优先级项 ===
Direct entity returns (should use DTOs or proper types)
直接返回实体(应使用DTO或合适的类型)
grep -rn "Promise<.Entity>" --include=".resolver.ts"
grep -rn "Promise<.Entity>" --include=".resolver.ts"
Missing @Transaction on mutations
Mutation缺失@Transaction装饰器
grep -rn "@Mutation" --include="*.resolver.ts" -A 2 | grep -v "@Transaction"
grep -rn "@Mutation" --include="*.resolver.ts" -A 2 | grep -v "@Transaction"
InputMaybe not handled correctly
InputMaybe处理不当
grep -rn "!== undefined" --include=".service.ts" | grep -v "&& . !== null"
grep -rn "!== undefined" --include=".service.ts" | grep -v "&& . !== null"
=== MEDIUM PRIORITY ===
=== 中优先级项 ===
Hardcoded permission strings
硬编码权限字符串
grep -rn "@Allow(['"]" --include="*.resolver.ts"
grep -rn "@Allow(['"]" --include="*.resolver.ts"
Missing error handling
缺失错误处理
grep -rn "async.@Ctx" --include=".resolver.ts" -A 10 | grep -v "throw|catch|try"
undefinedgrep -rn "async.@Ctx" --include=".resolver.ts" -A 10 | grep -v "throw|catch|try"
undefinedStep 3: Manual Review Checklist
步骤3:人工审查检查清单
Schema
Schema
- Uses gql template literal
- Input types for all mutations
- Proper type definitions
- Admin vs Shop separation clear
- No sensitive fields in Shop API
- 使用gql模板字面量
- 所有Mutation都定义了输入类型
- 类型定义规范
- Admin与Shop接口分离清晰
- Shop API未包含敏感字段
Resolvers
解析器
- @Resolver() decorator present
- @Ctx() ctx: RequestContext on all methods
- @Allow() with appropriate permissions
- @Transaction() on mutations
- Service injection (not direct DB access)
- 存在@Resolver()装饰器
- 所有方法都包含@Ctx() ctx: RequestContext参数
- 配置了@Allow()权限装饰器
- Mutation上添加了@Transaction()装饰器
- 通过服务注入访问数据(而非直接操作数据库)
Security
安全性
- Shop API doesn't expose admin data
- Owner permission checked for user resources
- Input validation present
- Error messages don't leak sensitive info
- Shop API未暴露Admin数据
- 用户资源已校验所有者权限
- 存在输入验证逻辑
- 错误信息未泄露敏感内容
Severity Classification
严重程度分类
CRITICAL (Must Fix)
严重(必须修复)
- Missing RequestContext parameter
- No permission decorators
- Shop API exposes admin data
- Direct database access in resolvers
- 缺失RequestContext参数
- 无权限装饰器
- Shop API暴露Admin数据
- 解析器中直接操作数据库
HIGH (Should Fix)
高优先级(应该修复)
- Missing @Transaction on mutations
- InputMaybe not handled correctly
- No error handling
- Entity types returned directly
- Mutation缺失@Transaction装饰器
- InputMaybe处理不当
- 无错误处理逻辑
- 直接返回实体类型
MEDIUM (Should Fix)
中优先级(建议修复)
- Missing input validation
- Poor error messages
- Inconsistent naming
- 缺失输入验证
- 错误信息不规范
- 命名不一致
Common Violations
常见违规案例
1. Missing RequestContext
1. 缺失RequestContext
Violation:
typescript
@Query()
@Allow(Permission.ReadSettings)
async myQuery(): Promise<MyEntity[]> { // No ctx!
return this.service.findAll();
}Fix:
typescript
@Query()
@Allow(Permission.ReadSettings)
async myQuery(@Ctx() ctx: RequestContext): Promise<MyEntity[]> {
return this.service.findAll(ctx);
}违规代码:
typescript
@Query()
@Allow(Permission.ReadSettings)
async myQuery(): Promise<MyEntity[]> { // 无ctx参数!
return this.service.findAll();
}修复后代码:
typescript
@Query()
@Allow(Permission.ReadSettings)
async myQuery(@Ctx() ctx: RequestContext): Promise<MyEntity[]> {
return this.service.findAll(ctx);
}2. Missing Permission Decorator
2. 缺失权限装饰器
Violation:
typescript
@Query()
async myQuery(@Ctx() ctx: RequestContext): Promise<MyEntity[]> {
// No @Allow - anyone can call this!
return this.service.findAll(ctx);
}Fix:
typescript
@Query()
@Allow(Permission.ReadSettings) // Explicit permission
async myQuery(@Ctx() ctx: RequestContext): Promise<MyEntity[]> {
return this.service.findAll(ctx);
}违规代码:
typescript
@Query()
async myQuery(@Ctx() ctx: RequestContext): Promise<MyEntity[]> {
// 无@Allow装饰器 - 任何人都可调用此接口!
return this.service.findAll(ctx);
}修复后代码:
typescript
@Query()
@Allow(Permission.ReadSettings) // 显式声明权限
async myQuery(@Ctx() ctx: RequestContext): Promise<MyEntity[]> {
return this.service.findAll(ctx);
}3. InputMaybe Bug
3. InputMaybe 问题
Violation:
typescript
// Only checks undefined, null passes through!
if (input.name !== undefined) {
entity.name = input.name;
}Fix:
typescript
// Check both undefined AND null
if (input.name !== undefined && input.name !== null) {
entity.name = input.name;
}违规代码:
typescript
// 仅检查undefined,null会被忽略!
if (input.name !== undefined) {
entity.name = input.name;
}修复后代码:
typescript
// 同时检查undefined和null
if (input.name !== undefined && input.name !== null) {
entity.name = input.name;
}4. Missing Transaction
4. 缺失事务装饰器
Violation:
typescript
@Mutation()
@Allow(Permission.UpdateSettings)
async updateData(@Ctx() ctx: RequestContext, @Args() args): Promise<MyEntity> {
// No @Transaction - partial updates possible on error!
await this.service.updateA(ctx, args);
await this.service.updateB(ctx, args); // If this fails, A is updated
}Fix:
typescript
@Mutation()
@Transaction() // Atomic operation
@Allow(Permission.UpdateSettings)
async updateData(@Ctx() ctx: RequestContext, @Args() args): Promise<MyEntity> {
await this.service.updateA(ctx, args);
await this.service.updateB(ctx, args);
}违规代码:
typescript
@Mutation()
@Allow(Permission.UpdateSettings)
async updateData(@Ctx() ctx: RequestContext, @Args() args): Promise<MyEntity> {
// 无@Transaction装饰器 - 出错时可能导致部分更新!
await this.service.updateA(ctx, args);
await this.service.updateB(ctx, args); // 若此步骤失败,A已被更新
}修复后代码:
typescript
@Mutation()
@Transaction() // 原子操作
@Allow(Permission.UpdateSettings)
async updateData(@Ctx() ctx: RequestContext, @Args() args): Promise<MyEntity> {
await this.service.updateA(ctx, args);
await this.service.updateB(ctx, args);
}5. Shop API Leaking Admin Data
5. Shop API 泄露Admin数据
Violation:
typescript
// Shop schema
const shopSchema = gql`
type User {
id: ID!
email: String!
internalNotes: String! # Admin-only field exposed!
}
`;Fix:
typescript
// Shop schema - limited fields
const shopSchema = gql`
type User {
id: ID!
email: String!
# internalNotes excluded
}
`;违规代码:
typescript
// Shop Schema
const shopSchema = gql`
type User {
id: ID!
email: String!
internalNotes: String! # 暴露了仅Admin可见的字段!
}
`;修复后代码:
typescript
// Shop Schema - 仅保留必要字段
const shopSchema = gql`
type User {
id: ID!
email: String!
// 移除internalNotes字段
}
`;Quick Detection Commands
快速检测命令
bash
undefinedbash
undefinedAll-in-one GraphQL audit
一站式GraphQL审计
echo "=== CRITICAL: Missing @Ctx ===" &&
grep -rn "@Query|@Mutation" --include=".resolver.ts" -A 5 | grep -v "@Ctx" | head -20 &&
echo "" &&
echo "=== HIGH: Missing @Allow ===" &&
grep -rn "@Query|@Mutation" --include=".resolver.ts" -A 3 | grep -v "@Allow" | head -20 &&
echo "" &&
echo "=== MEDIUM: InputMaybe issues ===" &&
grep -rn "!== undefined" --include=".ts" | grep -v "&& . !== null" | head -20
grep -rn "@Query|@Mutation" --include=".resolver.ts" -A 5 | grep -v "@Ctx" | head -20 &&
echo "" &&
echo "=== HIGH: Missing @Allow ===" &&
grep -rn "@Query|@Mutation" --include=".resolver.ts" -A 3 | grep -v "@Allow" | head -20 &&
echo "" &&
echo "=== MEDIUM: InputMaybe issues ===" &&
grep -rn "!== undefined" --include=".ts" | grep -v "&& . !== null" | head -20
---echo "=== 严重:缺失@Ctx ===" &&
grep -rn "@Query|@Mutation" --include=".resolver.ts" -A 5 | grep -v "@Ctx" | head -20 &&
echo "" &&
echo "=== 高优先级:缺失@Allow ===" &&
grep -rn "@Query|@Mutation" --include=".resolver.ts" -A 3 | grep -v "@Allow" | head -20 &&
echo "" &&
echo "=== 中优先级:InputMaybe问题 ===" &&
grep -rn "!== undefined" --include=".ts" | grep -v "&& . !== null" | head -20
grep -rn "@Query|@Mutation" --include=".resolver.ts" -A 5 | grep -v "@Ctx" | head -20 &&
echo "" &&
echo "=== 高优先级:缺失@Allow ===" &&
grep -rn "@Query|@Mutation" --include=".resolver.ts" -A 3 | grep -v "@Allow" | head -20 &&
echo "" &&
echo "=== 中优先级:InputMaybe问题 ===" &&
grep -rn "!== undefined" --include=".ts" | grep -v "&& . !== null" | head -20
---Review Output Template
审查输出模板
markdown
undefinedmarkdown
undefinedGraphQL Review: [Component Name]
GraphQL审查:[组件名称]
Summary
摘要
[Overview of GraphQL code quality]
[GraphQL代码质量概述]
Critical Issues (Must Fix)
严重问题(必须修复)
- [Issue] -
file:line
- [问题描述] -
文件:行号
High Priority
高优先级问题
- [Issue] -
file:line
- [问题描述] -
文件:行号
Passed Checks
通过的检查项
- All resolvers have @Resolver decorator
- RequestContext passed consistently
- Permissions declared
- 所有解析器都有@Resolver装饰器
- RequestContext传递一致
- 已声明权限配置
Recommendations
建议
- [Suggestions]
---[改进建议]
---Cross-Reference
交叉参考
All rules match patterns in vendure-graphql-writing skill.
所有规则均与vendure-graphql-writing技能中的模式匹配。
Related Skills
相关技能
- vendure-graphql-writing - GraphQL patterns
- vendure-plugin-reviewing - Plugin-level review
- vendure-graphql-writing - GraphQL编写规范
- vendure-plugin-reviewing - 插件级审查