@svton/cli 1.2.2 → 1.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +6 -13
- package/dist/index.mjs +6 -13
- package/package.json +1 -3
- package/templates/apps/admin/next-env.d.ts +0 -2
- package/templates/apps/admin/next.config.js +0 -15
- package/templates/apps/admin/package.json.tpl +0 -54
- package/templates/apps/admin/postcss.config.js +0 -6
- package/templates/apps/admin/src/app/globals.css +0 -37
- package/templates/apps/admin/src/app/layout.tsx +0 -19
- package/templates/apps/admin/src/app/login/page.tsx +0 -96
- package/templates/apps/admin/src/app/page.tsx +0 -8
- package/templates/apps/admin/src/app/users/page.tsx +0 -165
- package/templates/apps/admin/src/components/ui/switch.tsx +0 -29
- package/templates/apps/admin/src/hooks/useAPI.ts +0 -130
- package/templates/apps/admin/src/lib/api-client.ts +0 -112
- package/templates/apps/admin/src/lib/api-server.ts +0 -95
- package/templates/apps/admin/tailwind.config.js +0 -54
- package/templates/apps/admin/tsconfig.json +0 -22
- package/templates/apps/backend/.env.example +0 -29
- package/templates/apps/backend/nest-cli.json +0 -8
- package/templates/apps/backend/package.json.tpl +0 -57
- package/templates/apps/backend/prisma/schema.prisma +0 -72
- package/templates/apps/backend/prisma/seed.ts +0 -32
- package/templates/apps/backend/src/app.controller.ts +0 -15
- package/templates/apps/backend/src/app.module.ts +0 -85
- package/templates/apps/backend/src/app.service.ts +0 -12
- package/templates/apps/backend/src/auth/auth.controller.ts +0 -31
- package/templates/apps/backend/src/auth/auth.module.ts +0 -27
- package/templates/apps/backend/src/auth/auth.service.ts +0 -89
- package/templates/apps/backend/src/auth/jwt-auth.guard.ts +0 -5
- package/templates/apps/backend/src/auth/jwt.strategy.ts +0 -27
- package/templates/apps/backend/src/config/env.schema.ts +0 -35
- package/templates/apps/backend/src/main.ts +0 -51
- package/templates/apps/backend/src/object-storage/object-storage.controller.ts +0 -114
- package/templates/apps/backend/src/object-storage/object-storage.module.ts +0 -7
- package/templates/apps/backend/src/prisma/prisma.module.ts +0 -9
- package/templates/apps/backend/src/prisma/prisma.service.ts +0 -13
- package/templates/apps/backend/src/user/user.controller.ts +0 -50
- package/templates/apps/backend/src/user/user.module.ts +0 -12
- package/templates/apps/backend/src/user/user.service.ts +0 -117
- package/templates/apps/backend/tsconfig.json +0 -23
- package/templates/apps/mobile/babel.config.js +0 -8
- package/templates/apps/mobile/config/index.ts +0 -65
- package/templates/apps/mobile/package.json.tpl +0 -48
- package/templates/apps/mobile/project.config.json.tpl +0 -17
- package/templates/apps/mobile/src/app.config.ts +0 -9
- package/templates/apps/mobile/src/app.scss +0 -4
- package/templates/apps/mobile/src/app.ts +0 -8
- package/templates/apps/mobile/src/hooks/useAPI.ts +0 -285
- package/templates/apps/mobile/src/pages/index/index.scss +0 -7
- package/templates/apps/mobile/src/pages/index/index.tsx +0 -49
- package/templates/apps/mobile/src/services/api.ts +0 -155
- package/templates/apps/mobile/src/services/upload.service.ts +0 -41
- package/templates/apps/mobile/tsconfig.json +0 -21
- package/templates/configs/authz.config.ts +0 -10
- package/templates/configs/cache.config.ts +0 -14
- package/templates/configs/oauth.config.ts +0 -20
- package/templates/configs/payment.config.ts +0 -44
- package/templates/configs/queue.config.ts +0 -21
- package/templates/configs/rate-limit.config.ts +0 -16
- package/templates/configs/sms.config.ts +0 -11
- package/templates/configs/storage.config.ts +0 -14
- package/templates/examples/README.md +0 -258
- package/templates/examples/authz/README.md +0 -273
- package/templates/examples/authz/roles.guard.ts +0 -37
- package/templates/examples/authz/user.controller.ts +0 -116
- package/templates/examples/cache/README.md +0 -82
- package/templates/examples/cache/user.controller.ts +0 -42
- package/templates/examples/cache/user.service.ts +0 -78
- package/templates/examples/oauth/README.md +0 -192
- package/templates/examples/oauth/auth.controller.ts +0 -99
- package/templates/examples/oauth/auth.service.ts +0 -97
- package/templates/examples/payment/README.md +0 -151
- package/templates/examples/payment/order.controller.ts +0 -56
- package/templates/examples/payment/order.service.ts +0 -132
- package/templates/examples/payment/webhook.controller.ts +0 -73
- package/templates/examples/queue/README.md +0 -134
- package/templates/examples/queue/email.controller.ts +0 -34
- package/templates/examples/queue/email.processor.ts +0 -68
- package/templates/examples/queue/email.service.ts +0 -64
- package/templates/examples/rate-limit/README.md +0 -249
- package/templates/examples/rate-limit/api.controller.ts +0 -113
- package/templates/examples/sms/README.md +0 -121
- package/templates/examples/sms/sms.service.ts +0 -69
- package/templates/examples/sms/verification.controller.ts +0 -100
- package/templates/examples/storage/README.md +0 -224
- package/templates/examples/storage/upload.controller.ts +0 -117
- package/templates/examples/storage/upload.service.ts +0 -123
- package/templates/packages/types/package.json.tpl +0 -16
- package/templates/packages/types/src/api.ts +0 -88
- package/templates/packages/types/src/common.ts +0 -89
- package/templates/packages/types/src/index.ts +0 -3
- package/templates/packages/types/tsconfig.json +0 -16
- package/templates/skills/authz.skill.md +0 -42
- package/templates/skills/base.skill.md +0 -57
- package/templates/skills/cache.skill.md +0 -88
- package/templates/skills/oauth.skill.md +0 -41
- package/templates/skills/payment.skill.md +0 -129
- package/templates/skills/queue.skill.md +0 -140
- package/templates/skills/rate-limit.skill.md +0 -38
- package/templates/skills/sms.skill.md +0 -39
- package/templates/skills/storage.skill.md +0 -42
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { ConfigService } from '@nestjs/config';
|
|
2
|
-
import { QueueModuleOptions } from '@svton/nestjs-queue';
|
|
3
|
-
|
|
4
|
-
export const useQueueConfig = (
|
|
5
|
-
configService: ConfigService,
|
|
6
|
-
): QueueModuleOptions => ({
|
|
7
|
-
connection: {
|
|
8
|
-
host: configService.get('REDIS_HOST', 'localhost'),
|
|
9
|
-
port: parseInt(configService.get('REDIS_PORT', '6379'), 10),
|
|
10
|
-
password: configService.get('REDIS_PASSWORD'),
|
|
11
|
-
},
|
|
12
|
-
defaultJobOptions: {
|
|
13
|
-
attempts: 3,
|
|
14
|
-
backoff: {
|
|
15
|
-
type: 'exponential',
|
|
16
|
-
delay: 1000,
|
|
17
|
-
},
|
|
18
|
-
removeOnComplete: true,
|
|
19
|
-
removeOnFail: false,
|
|
20
|
-
},
|
|
21
|
-
});
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { ConfigService } from '@nestjs/config';
|
|
2
|
-
import { RateLimitModuleOptions } from '@svton/nestjs-rate-limit';
|
|
3
|
-
|
|
4
|
-
export const useRateLimitConfig = (
|
|
5
|
-
configService: ConfigService,
|
|
6
|
-
): RateLimitModuleOptions => ({
|
|
7
|
-
redis: {
|
|
8
|
-
host: configService.get('REDIS_HOST', 'localhost'),
|
|
9
|
-
port: parseInt(configService.get('REDIS_PORT', '6379'), 10),
|
|
10
|
-
password: configService.get('REDIS_PASSWORD'),
|
|
11
|
-
},
|
|
12
|
-
global: {
|
|
13
|
-
ttl: 60, // 时间窗口(秒)
|
|
14
|
-
limit: 100, // 最大请求数
|
|
15
|
-
},
|
|
16
|
-
});
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { ConfigService } from '@nestjs/config';
|
|
2
|
-
import { SmsModuleOptions } from '@svton/nestjs-sms';
|
|
3
|
-
|
|
4
|
-
export const useSmsConfig = (
|
|
5
|
-
configService: ConfigService,
|
|
6
|
-
): SmsModuleOptions => ({
|
|
7
|
-
provider: configService.get('SMS_PROVIDER', 'aliyun'),
|
|
8
|
-
accessKeyId: configService.get('SMS_ACCESS_KEY_ID'),
|
|
9
|
-
accessKeySecret: configService.get('SMS_ACCESS_KEY_SECRET'),
|
|
10
|
-
signName: configService.get('SMS_SIGN_NAME'),
|
|
11
|
-
});
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { ConfigService } from '@nestjs/config';
|
|
2
|
-
import { ObjectStorageModuleOptions } from '@svton/nestjs-object-storage';
|
|
3
|
-
|
|
4
|
-
export const useStorageConfig = (
|
|
5
|
-
configService: ConfigService,
|
|
6
|
-
): ObjectStorageModuleOptions => ({
|
|
7
|
-
provider: configService.get('STORAGE_PROVIDER', 'qiniu'),
|
|
8
|
-
qiniu: {
|
|
9
|
-
accessKey: configService.get('QINIU_ACCESS_KEY'),
|
|
10
|
-
secretKey: configService.get('QINIU_SECRET_KEY'),
|
|
11
|
-
bucket: configService.get('QINIU_BUCKET'),
|
|
12
|
-
domain: configService.get('QINIU_DOMAIN'),
|
|
13
|
-
},
|
|
14
|
-
});
|
|
@@ -1,258 +0,0 @@
|
|
|
1
|
-
# Svton 功能示例代码
|
|
2
|
-
|
|
3
|
-
本目录包含所有 Svton 功能模块的完整示例代码。
|
|
4
|
-
|
|
5
|
-
## 📦 已完成的示例
|
|
6
|
-
|
|
7
|
-
### 1. Cache - 缓存 ✅
|
|
8
|
-
|
|
9
|
-
**目录**: `cache/`
|
|
10
|
-
|
|
11
|
-
**文件**:
|
|
12
|
-
- `user.service.ts` - 缓存装饰器使用示例
|
|
13
|
-
- `user.controller.ts` - Controller 层示例
|
|
14
|
-
- `README.md` - 详细使用文档
|
|
15
|
-
|
|
16
|
-
**核心功能**:
|
|
17
|
-
- @Cacheable - 缓存查询结果
|
|
18
|
-
- @CacheEvict - 清除缓存
|
|
19
|
-
- @CachePut - 更新缓存
|
|
20
|
-
- 支持 Key 表达式和通配符
|
|
21
|
-
|
|
22
|
-
### 2. Queue - 消息队列 ✅
|
|
23
|
-
|
|
24
|
-
**目录**: `queue/`
|
|
25
|
-
|
|
26
|
-
**文件**:
|
|
27
|
-
- `email.processor.ts` - 队列处理器示例
|
|
28
|
-
- `email.service.ts` - 服务层示例
|
|
29
|
-
- `email.controller.ts` - Controller 层示例
|
|
30
|
-
- `README.md` - 详细使用文档
|
|
31
|
-
|
|
32
|
-
**核心功能**:
|
|
33
|
-
- 添加任务到队列
|
|
34
|
-
- 定义任务处理器
|
|
35
|
-
- 延迟执行、重试策略
|
|
36
|
-
- 定时任务、优先级控制
|
|
37
|
-
|
|
38
|
-
### 3. Payment - 支付 ✅
|
|
39
|
-
|
|
40
|
-
**目录**: `payment/`
|
|
41
|
-
|
|
42
|
-
**文件**:
|
|
43
|
-
- `order.service.ts` - 订单服务示例
|
|
44
|
-
- `order.controller.ts` - 支付接口示例
|
|
45
|
-
- `webhook.controller.ts` - 支付回调处理示例
|
|
46
|
-
- `README.md` - 详细使用文档
|
|
47
|
-
|
|
48
|
-
**核心功能**:
|
|
49
|
-
- 微信支付(JSAPI、Native、APP、H5)
|
|
50
|
-
- 支付宝(PC、H5、APP)
|
|
51
|
-
- 订单查询、退款
|
|
52
|
-
- 支付回调处理
|
|
53
|
-
|
|
54
|
-
### 4. SMS - 短信 ✅
|
|
55
|
-
|
|
56
|
-
**目录**: `sms/`
|
|
57
|
-
|
|
58
|
-
**文件**:
|
|
59
|
-
- `sms.service.ts` - 短信服务示例
|
|
60
|
-
- `verification.controller.ts` - 验证码控制器示例
|
|
61
|
-
- `README.md` - 详细使用文档
|
|
62
|
-
|
|
63
|
-
**核心功能**:
|
|
64
|
-
- 发送验证码
|
|
65
|
-
- 发送通知短信
|
|
66
|
-
- 批量发送
|
|
67
|
-
- 验证码验证
|
|
68
|
-
|
|
69
|
-
### 5. OAuth - OAuth 登录 ✅
|
|
70
|
-
|
|
71
|
-
**目录**: `oauth/`
|
|
72
|
-
|
|
73
|
-
**文件**:
|
|
74
|
-
- `auth.service.ts` - 认证服务示例
|
|
75
|
-
- `auth.controller.ts` - 认证控制器示例
|
|
76
|
-
- `README.md` - 详细使用文档
|
|
77
|
-
|
|
78
|
-
**核心功能**:
|
|
79
|
-
- 微信开放平台登录(PC 扫码)
|
|
80
|
-
- 微信公众号登录(网页授权)
|
|
81
|
-
- 微信小程序登录
|
|
82
|
-
- 小程序获取手机号
|
|
83
|
-
|
|
84
|
-
### 6. Storage - 对象存储 ✅
|
|
85
|
-
|
|
86
|
-
**目录**: `storage/`
|
|
87
|
-
|
|
88
|
-
**文件**:
|
|
89
|
-
- `upload.service.ts` - 上传服务示例
|
|
90
|
-
- `upload.controller.ts` - 上传控制器示例
|
|
91
|
-
- `README.md` - 详细使用文档
|
|
92
|
-
|
|
93
|
-
**核心功能**:
|
|
94
|
-
- 服务端上传文件
|
|
95
|
-
- 客户端直传
|
|
96
|
-
- 图片处理(缩略图、裁剪)
|
|
97
|
-
- 文件删除、移动、复制
|
|
98
|
-
- 私有文件访问
|
|
99
|
-
|
|
100
|
-
### 7. Rate Limit - 限流 ✅
|
|
101
|
-
|
|
102
|
-
**目录**: `rate-limit/`
|
|
103
|
-
|
|
104
|
-
**文件**:
|
|
105
|
-
- `api.controller.ts` - API 控制器示例
|
|
106
|
-
- `README.md` - 详细使用文档
|
|
107
|
-
|
|
108
|
-
**核心功能**:
|
|
109
|
-
- 接口限流
|
|
110
|
-
- 多种限流策略
|
|
111
|
-
- 防暴力破解
|
|
112
|
-
- 验证码防刷
|
|
113
|
-
- 自定义限流 Key
|
|
114
|
-
|
|
115
|
-
### 8. Authz - 权限控制 ✅
|
|
116
|
-
|
|
117
|
-
**目录**: `authz/`
|
|
118
|
-
|
|
119
|
-
**文件**:
|
|
120
|
-
- `user.controller.ts` - 用户控制器示例
|
|
121
|
-
- `roles.guard.ts` - 角色守卫示例
|
|
122
|
-
- `README.md` - 详细使用文档
|
|
123
|
-
|
|
124
|
-
**核心功能**:
|
|
125
|
-
- 角色权限控制
|
|
126
|
-
- 细粒度权限控制
|
|
127
|
-
- 动态权限检查
|
|
128
|
-
- 资源级权限
|
|
129
|
-
|
|
130
|
-
## 🎯 示例特点
|
|
131
|
-
|
|
132
|
-
### 1. 可直接运行
|
|
133
|
-
|
|
134
|
-
所有示例代码都是完整的、可运行的,包含:
|
|
135
|
-
- 完整的 Service 层实现
|
|
136
|
-
- 完整的 Controller 层实现
|
|
137
|
-
- 详细的代码注释
|
|
138
|
-
- 实际的业务场景
|
|
139
|
-
|
|
140
|
-
### 2. 详细文档
|
|
141
|
-
|
|
142
|
-
每个示例都包含 README.md,包括:
|
|
143
|
-
- 功能说明
|
|
144
|
-
- 核心 API 使用方式
|
|
145
|
-
- 测试接口示例
|
|
146
|
-
- 环境变量配置
|
|
147
|
-
- 最佳实践
|
|
148
|
-
- 常见场景
|
|
149
|
-
- 官方文档链接
|
|
150
|
-
|
|
151
|
-
### 3. 最佳实践
|
|
152
|
-
|
|
153
|
-
展示推荐的使用方式:
|
|
154
|
-
- 错误处理
|
|
155
|
-
- 参数验证
|
|
156
|
-
- 安全性考虑
|
|
157
|
-
- 性能优化
|
|
158
|
-
- 代码组织
|
|
159
|
-
|
|
160
|
-
### 4. 测试友好
|
|
161
|
-
|
|
162
|
-
提供完整的测试命令:
|
|
163
|
-
- curl 命令示例
|
|
164
|
-
- 请求参数示例
|
|
165
|
-
- 响应格式示例
|
|
166
|
-
|
|
167
|
-
## 📚 使用方式
|
|
168
|
-
|
|
169
|
-
### 1. 查看示例
|
|
170
|
-
|
|
171
|
-
```bash
|
|
172
|
-
cd src/examples/cache
|
|
173
|
-
cat README.md
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
### 2. 运行示例
|
|
177
|
-
|
|
178
|
-
```bash
|
|
179
|
-
# 启动项目
|
|
180
|
-
pnpm dev
|
|
181
|
-
|
|
182
|
-
# 测试接口
|
|
183
|
-
curl http://localhost:3000/examples/users/1
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
### 3. 学习代码
|
|
187
|
-
|
|
188
|
-
每个示例都有详细的注释,可以直接阅读代码学习。
|
|
189
|
-
|
|
190
|
-
### 4. 复制使用
|
|
191
|
-
|
|
192
|
-
可以直接复制示例代码到你的项目中使用。
|
|
193
|
-
|
|
194
|
-
## 🔧 环境配置
|
|
195
|
-
|
|
196
|
-
所有示例都需要配置相应的环境变量,请参考 `.env.example` 文件。
|
|
197
|
-
|
|
198
|
-
### 必需配置
|
|
199
|
-
|
|
200
|
-
- **Redis**(cache, queue, rate-limit)
|
|
201
|
-
```env
|
|
202
|
-
REDIS_HOST=localhost
|
|
203
|
-
REDIS_PORT=6379
|
|
204
|
-
REDIS_PASSWORD=
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
### 可选配置
|
|
208
|
-
|
|
209
|
-
根据使用的功能配置:
|
|
210
|
-
|
|
211
|
-
- **支付**(payment)
|
|
212
|
-
```env
|
|
213
|
-
WECHAT_MCH_ID=
|
|
214
|
-
WECHAT_PRIVATE_KEY=
|
|
215
|
-
ALIPAY_APP_ID=
|
|
216
|
-
ALIPAY_PRIVATE_KEY=
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
- **短信**(sms)
|
|
220
|
-
```env
|
|
221
|
-
SMS_PROVIDER=aliyun
|
|
222
|
-
SMS_ACCESS_KEY_ID=
|
|
223
|
-
SMS_ACCESS_KEY_SECRET=
|
|
224
|
-
```
|
|
225
|
-
|
|
226
|
-
- **OAuth**(oauth)
|
|
227
|
-
```env
|
|
228
|
-
WECHAT_OPEN_APP_ID=
|
|
229
|
-
WECHAT_OPEN_APP_SECRET=
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
- **对象存储**(storage)
|
|
233
|
-
```env
|
|
234
|
-
QINIU_ACCESS_KEY=
|
|
235
|
-
QINIU_SECRET_KEY=
|
|
236
|
-
QINIU_BUCKET=
|
|
237
|
-
```
|
|
238
|
-
|
|
239
|
-
## 📖 文档资源
|
|
240
|
-
|
|
241
|
-
- Svton 官方文档:https://751848178.github.io/svton
|
|
242
|
-
- GitHub:https://github.com/751848178/svton
|
|
243
|
-
|
|
244
|
-
## 💡 开发建议
|
|
245
|
-
|
|
246
|
-
1. **先看 README**:每个示例都有详细的 README,先阅读了解功能
|
|
247
|
-
2. **查看代码**:阅读示例代码,理解实现方式
|
|
248
|
-
3. **运行测试**:使用提供的 curl 命令测试接口
|
|
249
|
-
4. **修改尝试**:根据自己的需求修改示例代码
|
|
250
|
-
5. **查看文档**:遇到问题查看官方文档
|
|
251
|
-
|
|
252
|
-
## 🤝 贡献
|
|
253
|
-
|
|
254
|
-
如果你有更好的示例或发现问题,欢迎提交 PR 或 Issue。
|
|
255
|
-
|
|
256
|
-
## 📝 许可
|
|
257
|
-
|
|
258
|
-
MIT License
|
|
@@ -1,273 +0,0 @@
|
|
|
1
|
-
# 权限控制示例
|
|
2
|
-
|
|
3
|
-
本示例展示如何使用 `@svton/nestjs-authz` 模块实现 RBAC 权限管理。
|
|
4
|
-
|
|
5
|
-
## 文件说明
|
|
6
|
-
|
|
7
|
-
- `user.controller.ts` - 用户控制器,展示权限控制
|
|
8
|
-
- `roles.guard.ts` - 角色守卫,验证用户权限
|
|
9
|
-
|
|
10
|
-
## 核心装饰器
|
|
11
|
-
|
|
12
|
-
### @Roles - 角色权限
|
|
13
|
-
|
|
14
|
-
限制只有特定角色才能访问:
|
|
15
|
-
|
|
16
|
-
```typescript
|
|
17
|
-
@Roles('admin')
|
|
18
|
-
@Get('admin')
|
|
19
|
-
async adminOnly() {
|
|
20
|
-
return { message: 'Admin only' };
|
|
21
|
-
}
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
支持多个角色(满足其一即可):
|
|
25
|
-
|
|
26
|
-
```typescript
|
|
27
|
-
@Roles('admin', 'manager')
|
|
28
|
-
@Get('list')
|
|
29
|
-
async list() {
|
|
30
|
-
return { message: 'Admin or Manager' };
|
|
31
|
-
}
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
### @Permissions - 细粒度权限
|
|
35
|
-
|
|
36
|
-
基于权限点的访问控制:
|
|
37
|
-
|
|
38
|
-
```typescript
|
|
39
|
-
@Permissions('user:delete')
|
|
40
|
-
@Delete(':id')
|
|
41
|
-
async delete(@Param('id') id: string) {
|
|
42
|
-
return { message: 'User deleted' };
|
|
43
|
-
}
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
支持多个权限(需要全部满足):
|
|
47
|
-
|
|
48
|
-
```typescript
|
|
49
|
-
@Permissions('user:update', 'user:sensitive')
|
|
50
|
-
@Put(':id/sensitive')
|
|
51
|
-
async updateSensitive() {
|
|
52
|
-
return { message: 'Updated' };
|
|
53
|
-
}
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
### 组合使用
|
|
57
|
-
|
|
58
|
-
同时检查角色和权限:
|
|
59
|
-
|
|
60
|
-
```typescript
|
|
61
|
-
@Roles('admin')
|
|
62
|
-
@Permissions('user:delete')
|
|
63
|
-
@Delete(':id')
|
|
64
|
-
async delete() {
|
|
65
|
-
// 需要 admin 角色且有 user:delete 权限
|
|
66
|
-
}
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
## 权限模型
|
|
70
|
-
|
|
71
|
-
### 角色(Roles)
|
|
72
|
-
|
|
73
|
-
- `admin` - 管理员,拥有所有权限
|
|
74
|
-
- `manager` - 管理者,拥有部分管理权限
|
|
75
|
-
- `user` - 普通用户,基础权限
|
|
76
|
-
- `guest` - 访客,只读权限
|
|
77
|
-
|
|
78
|
-
### 权限点(Permissions)
|
|
79
|
-
|
|
80
|
-
- `user:create` - 创建用户
|
|
81
|
-
- `user:read` - 查看用户
|
|
82
|
-
- `user:update` - 更新用户
|
|
83
|
-
- `user:delete` - 删除用户
|
|
84
|
-
- `user:batch-delete` - 批量删除用户
|
|
85
|
-
- `user:reset-password` - 重置密码
|
|
86
|
-
|
|
87
|
-
## 测试接口
|
|
88
|
-
|
|
89
|
-
### 查看用户列表(需要 admin 或 manager)
|
|
90
|
-
|
|
91
|
-
```bash
|
|
92
|
-
curl http://localhost:3000/examples/users
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
### 查看用户详情(所有用户)
|
|
96
|
-
|
|
97
|
-
```bash
|
|
98
|
-
curl http://localhost:3000/examples/users/1
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
### 创建用户(需要 admin)
|
|
102
|
-
|
|
103
|
-
```bash
|
|
104
|
-
curl -X POST http://localhost:3000/examples/users \
|
|
105
|
-
-H "Content-Type: application/json" \
|
|
106
|
-
-d '{"name":"New User","email":"user@example.com"}'
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
### 更新用户(需要 user:update 权限)
|
|
110
|
-
|
|
111
|
-
```bash
|
|
112
|
-
curl -X PUT http://localhost:3000/examples/users/1 \
|
|
113
|
-
-H "Content-Type: application/json" \
|
|
114
|
-
-d '{"name":"Updated Name"}'
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
### 删除用户(需要 admin 角色和 user:delete 权限)
|
|
118
|
-
|
|
119
|
-
```bash
|
|
120
|
-
curl -X DELETE http://localhost:3000/examples/users/1
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
## 权限配置
|
|
124
|
-
|
|
125
|
-
在 `src/config/authz.config.ts` 中配置:
|
|
126
|
-
|
|
127
|
-
```typescript
|
|
128
|
-
export const useAuthzConfig = (configService: ConfigService) => ({
|
|
129
|
-
roles: ['admin', 'manager', 'user', 'guest'],
|
|
130
|
-
defaultRole: 'guest',
|
|
131
|
-
rolePermissions: {
|
|
132
|
-
admin: ['*'], // 所有权限
|
|
133
|
-
manager: [
|
|
134
|
-
'user:read',
|
|
135
|
-
'user:update',
|
|
136
|
-
'user:reset-password',
|
|
137
|
-
],
|
|
138
|
-
user: [
|
|
139
|
-
'user:read',
|
|
140
|
-
],
|
|
141
|
-
guest: [],
|
|
142
|
-
},
|
|
143
|
-
});
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
## 实现原理
|
|
147
|
-
|
|
148
|
-
### 1. 定义守卫
|
|
149
|
-
|
|
150
|
-
```typescript
|
|
151
|
-
@Injectable()
|
|
152
|
-
export class RolesGuard implements CanActivate {
|
|
153
|
-
canActivate(context: ExecutionContext): boolean {
|
|
154
|
-
const requiredRoles = this.reflector.get('roles', context.getHandler());
|
|
155
|
-
const user = context.switchToHttp().getRequest().user;
|
|
156
|
-
|
|
157
|
-
return requiredRoles.some(role => user.role === role);
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
### 2. 应用守卫
|
|
163
|
-
|
|
164
|
-
```typescript
|
|
165
|
-
@Controller('users')
|
|
166
|
-
@UseGuards(RolesGuard)
|
|
167
|
-
export class UserController {
|
|
168
|
-
// 所有接口都会应用权限检查
|
|
169
|
-
}
|
|
170
|
-
```
|
|
171
|
-
|
|
172
|
-
### 3. 使用装饰器
|
|
173
|
-
|
|
174
|
-
```typescript
|
|
175
|
-
@Roles('admin')
|
|
176
|
-
@Get('admin')
|
|
177
|
-
async adminOnly() { }
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
## 最佳实践
|
|
181
|
-
|
|
182
|
-
1. **最小权限原则**:只授予必要的权限
|
|
183
|
-
2. **角色分层**:设计合理的角色层级
|
|
184
|
-
3. **权限粒度**:根据业务需求设计权限点
|
|
185
|
-
4. **动态权限**:支持运行时动态调整权限
|
|
186
|
-
5. **权限缓存**:缓存用户权限,提高性能
|
|
187
|
-
|
|
188
|
-
## 常见场景
|
|
189
|
-
|
|
190
|
-
### 用户管理
|
|
191
|
-
|
|
192
|
-
```typescript
|
|
193
|
-
@Roles('admin')
|
|
194
|
-
@Get('users')
|
|
195
|
-
async getUsers() { } // 只有管理员可以查看用户列表
|
|
196
|
-
|
|
197
|
-
@Permissions('user:update')
|
|
198
|
-
@Put('users/:id')
|
|
199
|
-
async updateUser() { } // 需要更新权限
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
### 内容管理
|
|
203
|
-
|
|
204
|
-
```typescript
|
|
205
|
-
@Roles('admin', 'editor')
|
|
206
|
-
@Post('articles')
|
|
207
|
-
async createArticle() { } // 管理员和编辑可以创建文章
|
|
208
|
-
|
|
209
|
-
@Permissions('article:publish')
|
|
210
|
-
@Post('articles/:id/publish')
|
|
211
|
-
async publishArticle() { } // 需要发布权限
|
|
212
|
-
```
|
|
213
|
-
|
|
214
|
-
### 数据导出
|
|
215
|
-
|
|
216
|
-
```typescript
|
|
217
|
-
@Roles('admin', 'manager')
|
|
218
|
-
@Get('export')
|
|
219
|
-
async export() { } // 管理员和管理者可以导出数据
|
|
220
|
-
```
|
|
221
|
-
|
|
222
|
-
## 高级用法
|
|
223
|
-
|
|
224
|
-
### 动态权限检查
|
|
225
|
-
|
|
226
|
-
```typescript
|
|
227
|
-
@Get(':id')
|
|
228
|
-
async findOne(@Param('id') id: string, @Req() req) {
|
|
229
|
-
const user = req.user;
|
|
230
|
-
|
|
231
|
-
// 用户只能查看自己的数据,管理员可以查看所有
|
|
232
|
-
if (user.role !== 'admin' && user.id !== parseInt(id)) {
|
|
233
|
-
throw new ForbiddenException('Access denied');
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
return this.userService.findOne(id);
|
|
237
|
-
}
|
|
238
|
-
```
|
|
239
|
-
|
|
240
|
-
### 资源级权限
|
|
241
|
-
|
|
242
|
-
```typescript
|
|
243
|
-
@Put(':id')
|
|
244
|
-
async update(@Param('id') id: string, @Req() req) {
|
|
245
|
-
const resource = await this.userService.findOne(id);
|
|
246
|
-
|
|
247
|
-
// 检查用户是否有权限修改这个资源
|
|
248
|
-
if (!this.authzService.canModify(req.user, resource)) {
|
|
249
|
-
throw new ForbiddenException('Access denied');
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
return this.userService.update(id, data);
|
|
253
|
-
}
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
### 条件权限
|
|
257
|
-
|
|
258
|
-
```typescript
|
|
259
|
-
@Post('approve')
|
|
260
|
-
@Permissions('order:approve')
|
|
261
|
-
async approve(@Body() data, @Req() req) {
|
|
262
|
-
// 只能审批金额小于 10000 的订单
|
|
263
|
-
if (data.amount > 10000 && !req.user.permissions.includes('order:approve-large')) {
|
|
264
|
-
throw new ForbiddenException('Cannot approve large orders');
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
return this.orderService.approve(data.id);
|
|
268
|
-
}
|
|
269
|
-
```
|
|
270
|
-
|
|
271
|
-
## 更多信息
|
|
272
|
-
|
|
273
|
-
查看官方文档:https://751848178.github.io/svton/packages/nestjs-authz
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
|
|
2
|
-
import { Reflector } from '@nestjs/core';
|
|
3
|
-
|
|
4
|
-
@Injectable()
|
|
5
|
-
export class RolesGuard implements CanActivate {
|
|
6
|
-
constructor(private reflector: Reflector) {}
|
|
7
|
-
|
|
8
|
-
canActivate(context: ExecutionContext): boolean {
|
|
9
|
-
// 获取装饰器设置的角色
|
|
10
|
-
const requiredRoles = this.reflector.getAllAndOverride<string[]>('roles', [
|
|
11
|
-
context.getHandler(),
|
|
12
|
-
context.getClass(),
|
|
13
|
-
]);
|
|
14
|
-
|
|
15
|
-
if (!requiredRoles) {
|
|
16
|
-
return true;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const request = context.switchToHttp().getRequest();
|
|
20
|
-
const user = request.user;
|
|
21
|
-
|
|
22
|
-
// TODO: 实际项目中从 JWT 或 Session 获取用户信息
|
|
23
|
-
// 这里模拟用户信息
|
|
24
|
-
if (!user) {
|
|
25
|
-
// 模拟用户(实际应从认证中间件获取)
|
|
26
|
-
request.user = {
|
|
27
|
-
id: 1,
|
|
28
|
-
name: 'Test User',
|
|
29
|
-
role: 'admin', // 可以改为 'user', 'manager', 'guest' 测试不同角色
|
|
30
|
-
permissions: ['user:update', 'user:delete', 'user:batch-delete', 'user:reset-password'],
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// 检查用户角色
|
|
35
|
-
return requiredRoles.some((role) => user.role === role);
|
|
36
|
-
}
|
|
37
|
-
}
|